package resize import ( "bytes" "github.com/anthonynsimon/bild/transform" "image" "image/jpeg" "image/png" "io" ) var mimeTypes = map[string]string{ "image/jpg": "image/jpg", "image/jpeg": "image/jpeg", "image/png": "image/png", } func IsResizable(mimeType string) bool { _, present := mimeTypes[mimeType] return present } type ResizeType int const ( // Cover - resize preserving image aspect // - resizes to the smallest image where both width and height are larger or equal to given size Cover ResizeType = iota // Contain - resize preserving image aspect // - resizes to the largest image where both width and height are smaller or equal to given size Contain ResizeType = iota // ExactHeight - resize preserving image aspect // - resizes to the image with given height ExactHeight ResizeType = iota // ExactWidth - resize preserving image aspect // - resizes to the image with given width ExactWidth ResizeType = iota // Exact - resize without preserving image aspect // - resizes to exact size defined in request Exact ResizeType = iota ) type Resize struct { Height int Width int Type ResizeType } func ResizeImage(imageBytes []byte, resize Resize) ([]byte, error) { img, format, err := image.Decode(bytes.NewReader(imageBytes)) if err != nil { return nil, err } var buffer bytes.Buffer writer := io.Writer(&buffer) resizeWidth, resizeHeight := calculateResizedDimensions(img.Bounds(), resize) img = transform.Resize(img, resizeWidth, resizeHeight, transform.Gaussian) switch format { case "png": err = png.Encode(writer, img) case "jpeg": err = jpeg.Encode(writer, img, nil) default: err = jpeg.Encode(writer, img, nil) } if err != nil { return nil, err } return buffer.Bytes(), nil } func calculateResizedDimensions(bounds image.Rectangle, resize Resize) (width int, height int) { width = bounds.Dx() height = bounds.Dy() switch resize.Type { case Cover: rWidth := resize.Height * width / height if rWidth >= resize.Width { return rWidth, resize.Height } rHeight := resize.Width * height / width if rHeight >= resize.Height { return resize.Width, rHeight } case Contain: rWidth := resize.Height * width / height if rWidth <= resize.Width { return rWidth, resize.Height } rHeight := resize.Width * height / width if rHeight <= resize.Height { return resize.Width, rHeight } case ExactHeight: rWidth := resize.Height * width / height return rWidth, resize.Height case ExactWidth: rHeight := resize.Width * height / width return resize.Width, rHeight } return }