//////////////////////////////////////////////////////////////////////////////// // Copyright © 2021 Privategrity Corporation / // / // All rights reserved. / //////////////////////////////////////////////////////////////////////////////// // Provides various utility functions for access over the bindings package api import ( "bytes" "github.com/nfnt/resize" "github.com/pkg/errors" "image/jpeg" "math" ) const ( // Maximum input image size (in bytes) maxSize int64 = 12000000 // Desired number of pixels in output image desiredSize = 307200 ) // CompressJpeg takes a JPEG image in byte format // and compresses it based on the above consts func CompressJpeg(imgBytes []byte) ([]byte, error) { // Convert bytes to a reader imgBuf := bytes.NewReader(imgBytes) // Ensure the size of the image is under the limit if imgSize := imgBuf.Size(); imgSize > maxSize { return nil, errors.Errorf("Image is too large: %d/%d", imgSize, maxSize) } // Decode the image information imgInfo, err := jpeg.DecodeConfig(imgBuf) if err != nil { return nil, errors.Errorf("Unable to decode image config: %+v", err) } // If the dimensions of the image are below desiredSize, no compression is required if imgInfo.Width*imgInfo.Height < desiredSize { return imgBytes, nil } // Reset the buffer to the beginning to begin decoding the image _, err = imgBuf.Seek(0, 0) if err != nil { return nil, errors.Errorf("Unable to reset image buffer: %+v", err) } // Decode image into image.Image object img, err := jpeg.Decode(imgBuf) if err != nil { return nil, errors.Errorf("Unable to decode image: %+v", err) } // Determine the new width of the image based on desiredSize newWidth := uint(math.Sqrt(float64(desiredSize * (imgInfo.Width / imgInfo.Height)))) // Resize the image based on newWidth while preserving aspect ratio newImg := resize.Resize(newWidth, 0, img, resize.Bicubic) // Encode the new image to a buffer newImgBuf := new(bytes.Buffer) err = jpeg.Encode(newImgBuf, newImg, nil) if err != nil { return nil, errors.Errorf("Unable to encode image: %+v", err) } // Return the compressed image in byte form return newImgBuf.Bytes(), nil }