package images import ( "image" "math" "golang.org/x/image/draw" ) func scale(src image.Image, options Options) image.Image { // Set the expected size that you want: dst := image.NewRGBA( calculateFit(src.Bounds(), options), ) // Resize: draw.BiLinear.Scale(dst, dst.Rect, src, src.Bounds(), draw.Over, nil) // Encode to `output`: return dst } // calculateFit returns the new dimensions (width, height) that fit within the // provided Options without upscaling and while maintaining the aspect ratio. func calculateFit(bounds image.Rectangle, opt Options) image.Rectangle { // If no limits are set, or the image is already smaller than the limits, // return original dimensions (No Upscaling). if (opt.Width == 0 || bounds.Max.X <= opt.Width) && (opt.Height == 0 || bounds.Max.Y <= opt.Height) { return bounds } // Calculate ratios for width and height ratioW := float64(opt.Width) / float64(bounds.Max.X) ratioH := float64(opt.Height) / float64(bounds.Max.Y) // Determine the scale factor var scale float64 if opt.Width > 0 && opt.Height > 0 { // Use the smaller ratio to ensure it fits in both bounds scale = math.Min(ratioW, ratioH) } else if opt.Width > 0 { scale = ratioW } else if opt.Height > 0 { scale = ratioH } else { return bounds } return image.Rect( 0, 0, int(math.Round(float64(bounds.Max.X)*scale)), int(math.Round(float64(bounds.Max.Y)*scale)), ) }