I am trying to build an application which manipulates images on the run using Bild. But the above-mentioned methods are eating up a lot CPU(90%) for images. What is the reason for these methods to use high CPU? Are there any other methods or packages which uses less CPU?
func imageDecode(imageBytes []byte) (image.Image, error) {
contentType := http.DetectContentType(imageBytes)
var err error
var img image.Image
if contentType == constants.PngContentType {
img, err = png.Decode(bytes.NewReader(imageBytes))
} else if contentType == constants.JpegContentType {
img, err = jpeg.Decode(bytes.NewReader(imageBytes))
} else if contentType == constants.GifContentType {
img, err = gif.Decode(bytes.NewReader(imageBytes))
} else {
img, err = nil, fmt.Errorf("decode error invalid content-type for filename: ")
}
if err != nil {
return img, err
}
return img, nil
}
func imageEncode(imageBytes []byte, img image.Image) ([]byte, error) {
contentType := http.DetectContentType(imageBytes)
if contentType == constants.PngContentType && isOpaque(img) {
contentType = constants.JpegContentType
}
buf := new(bytes.Buffer)
var err error
var transformedImageBytes []byte
if contentType == constants.PngContentType {
pngEnc := png.Encoder{CompressionLevel: png.BestCompression}
err = pngEnc.Encode(buf, img)
} else if contentType == constants.JpegContentType {
err = jpeg.Encode(buf, img, nil)
} else if contentType == constants.GifContentType {
err = gif.Encode(buf, img, nil)
} else {
err = fmt.Errorf("encode error invalid content-type")
}
if err != nil {
return transformedImageBytes, err
}
transformedImageBytes = buf.Bytes()
return transformedImageBytes, err
}
You don't need to manually detect the image type and use different decoding calls, the image
package does that for you already, when using image.Decode()
. Just make sure you have the image decoders registered prior, which you can achieve by using blank imports, e.g.:
import (
_ "image/gif"
_ "image/jpeg"
_ "image/png"
)
func imageDecode(imageBytes []byte) (image.Image, error) {
img, _, err := image.Decode(bytes.NewReader(imageBytes))
}
Although I'm not sure performance will improve significantly by this.
What you should do is use "smart" conversion. By this I mean in certain cases you can omit decoding and re-encoding the image, you can just send the input to the output as-is (e.g. using io.Copy()
):
You only have to truly decode the image if it is of PNG format. Note that detecting if a PNG image is opaque is slow as it has to examine all the pixels (unless a transparent pixel is found earlier).