mirror of
https://github.com/imgproxy/imgproxy.git
synced 2024-11-29 08:22:11 +02:00
177 lines
3.8 KiB
Go
177 lines
3.8 KiB
Go
package processing
|
|
|
|
import (
|
|
"math"
|
|
|
|
"github.com/imgproxy/imgproxy/v3/imagedata"
|
|
"github.com/imgproxy/imgproxy/v3/imagetype"
|
|
"github.com/imgproxy/imgproxy/v3/imath"
|
|
"github.com/imgproxy/imgproxy/v3/options"
|
|
"github.com/imgproxy/imgproxy/v3/vips"
|
|
)
|
|
|
|
func extractMeta(img *vips.Image, baseAngle int, useOrientation bool) (int, int, int, bool) {
|
|
width := img.Width()
|
|
height := img.Height()
|
|
|
|
angle := 0
|
|
flip := false
|
|
|
|
if useOrientation {
|
|
orientation := img.Orientation()
|
|
|
|
if orientation == 3 || orientation == 4 {
|
|
angle = 180
|
|
}
|
|
if orientation == 5 || orientation == 6 {
|
|
angle = 90
|
|
}
|
|
if orientation == 7 || orientation == 8 {
|
|
angle = 270
|
|
}
|
|
if orientation == 2 || orientation == 4 || orientation == 5 || orientation == 7 {
|
|
flip = true
|
|
}
|
|
}
|
|
|
|
if (angle+baseAngle)%180 != 0 {
|
|
width, height = height, width
|
|
}
|
|
|
|
return width, height, angle, flip
|
|
}
|
|
|
|
func calcScale(width, height int, po *options.ProcessingOptions, imgtype imagetype.Type) (float64, float64) {
|
|
var wshrink, hshrink float64
|
|
|
|
srcW, srcH := float64(width), float64(height)
|
|
dstW, dstH := float64(po.Width), float64(po.Height)
|
|
|
|
if po.Width == 0 {
|
|
dstW = srcW
|
|
}
|
|
|
|
if dstW == srcW {
|
|
wshrink = 1
|
|
} else {
|
|
wshrink = srcW / dstW
|
|
}
|
|
|
|
if po.Height == 0 {
|
|
dstH = srcH
|
|
}
|
|
|
|
if dstH == srcH {
|
|
hshrink = 1
|
|
} else {
|
|
hshrink = srcH / dstH
|
|
}
|
|
|
|
wshrink /= po.Dpr
|
|
hshrink /= po.Dpr
|
|
|
|
if wshrink != 1 || hshrink != 1 {
|
|
rt := po.ResizingType
|
|
|
|
if rt == options.ResizeAuto {
|
|
srcD := srcW - srcH
|
|
dstD := dstW - dstH
|
|
|
|
if (srcD >= 0 && dstD >= 0) || (srcD < 0 && dstD < 0) {
|
|
rt = options.ResizeFill
|
|
} else {
|
|
rt = options.ResizeFit
|
|
}
|
|
}
|
|
|
|
switch {
|
|
case po.Width == 0 && rt != options.ResizeForce:
|
|
wshrink = hshrink
|
|
case po.Height == 0 && rt != options.ResizeForce:
|
|
hshrink = wshrink
|
|
case rt == options.ResizeFit:
|
|
wshrink = math.Max(wshrink, hshrink)
|
|
hshrink = wshrink
|
|
case rt == options.ResizeFill || rt == options.ResizeFillDown:
|
|
wshrink = math.Min(wshrink, hshrink)
|
|
hshrink = wshrink
|
|
}
|
|
}
|
|
|
|
if !po.Enlarge && imgtype != imagetype.SVG {
|
|
if wshrink < 1 {
|
|
hshrink /= wshrink
|
|
wshrink = 1
|
|
}
|
|
if hshrink < 1 {
|
|
wshrink /= hshrink
|
|
hshrink = 1
|
|
}
|
|
}
|
|
|
|
if po.MinWidth > 0 {
|
|
if minShrink := srcW / float64(po.MinWidth); minShrink < wshrink {
|
|
hshrink /= wshrink / minShrink
|
|
wshrink = minShrink
|
|
}
|
|
}
|
|
|
|
if po.MinHeight > 0 {
|
|
if minShrink := srcH / float64(po.MinHeight); minShrink < hshrink {
|
|
wshrink /= hshrink / minShrink
|
|
hshrink = minShrink
|
|
}
|
|
}
|
|
|
|
if wshrink > srcW {
|
|
wshrink = srcW
|
|
}
|
|
|
|
if hshrink > srcH {
|
|
hshrink = srcH
|
|
}
|
|
|
|
return 1.0 / wshrink, 1.0 / hshrink
|
|
}
|
|
|
|
func calcCropSize(orig int, crop float64) int {
|
|
switch {
|
|
case crop == 0.0:
|
|
return 0
|
|
case crop >= 1.0:
|
|
return int(crop)
|
|
default:
|
|
return imath.Max(1, imath.Scale(orig, crop))
|
|
}
|
|
}
|
|
|
|
func prepare(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptions, imgdata *imagedata.ImageData) error {
|
|
pctx.imgtype = imagetype.Unknown
|
|
if imgdata != nil {
|
|
pctx.imgtype = imgdata.Type
|
|
}
|
|
|
|
pctx.srcWidth, pctx.srcHeight, pctx.angle, pctx.flip = extractMeta(img, po.Rotate, po.AutoRotate)
|
|
|
|
pctx.cropWidth = calcCropSize(pctx.srcWidth, po.Crop.Width)
|
|
pctx.cropHeight = calcCropSize(pctx.srcHeight, po.Crop.Height)
|
|
|
|
widthToScale := imath.MinNonZero(pctx.cropWidth, pctx.srcWidth)
|
|
heightToScale := imath.MinNonZero(pctx.cropHeight, pctx.srcHeight)
|
|
|
|
pctx.wscale, pctx.hscale = calcScale(widthToScale, heightToScale, po, pctx.imgtype)
|
|
|
|
if pctx.cropWidth > 0 {
|
|
pctx.cropWidth = imath.Max(1, imath.Scale(pctx.cropWidth, pctx.wscale))
|
|
}
|
|
if pctx.cropHeight > 0 {
|
|
pctx.cropHeight = imath.Max(1, imath.Scale(pctx.cropHeight, pctx.hscale))
|
|
}
|
|
if pctx.cropGravity.Type != options.GravityFocusPoint {
|
|
pctx.cropGravity.X *= pctx.wscale
|
|
pctx.cropGravity.Y *= pctx.hscale
|
|
}
|
|
|
|
return nil
|
|
}
|