56 lines
1.4 KiB
Go
56 lines
1.4 KiB
Go
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)),
|
|
)
|
|
}
|