github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/app/imaging/encode.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package imaging 5 6 import ( 7 "errors" 8 "fmt" 9 "image" 10 "io" 11 12 "image/jpeg" 13 "image/png" 14 ) 15 16 // EncoderOptions holds configuration options for an image encoder. 17 type EncoderOptions struct { 18 // The level of concurrency for the encoder. This defines a limit on the 19 // number of concurrently running encoding goroutines. 20 ConcurrencyLevel int 21 } 22 23 func (o *EncoderOptions) validate() error { 24 if o.ConcurrencyLevel < 0 { 25 return errors.New("ConcurrencyLevel must be non-negative") 26 } 27 return nil 28 } 29 30 // Decoder holds the necessary state to encode images. 31 // This is safe to be used from multiple goroutines. 32 type Encoder struct { 33 sem chan struct{} 34 opts EncoderOptions 35 pngEncoder *png.Encoder 36 } 37 38 // NewEncoder creates and returns a new image encoder with the given options. 39 func NewEncoder(opts EncoderOptions) (*Encoder, error) { 40 var e Encoder 41 if err := opts.validate(); err != nil { 42 return nil, fmt.Errorf("imaging: error validating encoder options: %w", err) 43 } 44 if opts.ConcurrencyLevel > 0 { 45 e.sem = make(chan struct{}, opts.ConcurrencyLevel) 46 } 47 e.opts = opts 48 e.pngEncoder = &png.Encoder{} 49 return &e, nil 50 } 51 52 // EncodeJPEG encodes the given image in JPEG format and writes the data to 53 // the passed writer. 54 func (e *Encoder) EncodeJPEG(wr io.Writer, img image.Image, quality int) error { 55 if e.opts.ConcurrencyLevel > 0 { 56 e.sem <- struct{}{} 57 defer func() { 58 <-e.sem 59 }() 60 } 61 62 var encOpts jpeg.Options 63 encOpts.Quality = quality 64 if err := jpeg.Encode(wr, img, &encOpts); err != nil { 65 return fmt.Errorf("imaging: failed to encode jpeg: %w", err) 66 } 67 68 return nil 69 } 70 71 // EncodePNG encodes the given image in PNG format and writes the data to 72 // the passed writer. 73 func (e *Encoder) EncodePNG(wr io.Writer, img image.Image) error { 74 if e.opts.ConcurrencyLevel > 0 { 75 e.sem <- struct{}{} 76 defer func() { 77 <-e.sem 78 }() 79 } 80 81 if err := e.pngEncoder.Encode(wr, img); err != nil { 82 return fmt.Errorf("imaging: failed to encode png: %w", err) 83 } 84 85 return nil 86 }