Browse Source

Use RoundToEven when calculating offsets and watermark size

DarthSim 2 years ago
parent
commit
7d1f7c903a
5 changed files with 22 additions and 12 deletions
  1. 8 0
      imath/imath.go
  2. 1 1
      options/processing_options.go
  3. 7 5
      processing/calc_position.go
  4. 4 4
      processing/padding.go
  5. 2 2
      processing/watermark.go

+ 8 - 0
imath/imath.go

@@ -58,3 +58,11 @@ func Shrink(a int, shrink float64) int {
 
 	return Round(float64(a) / shrink)
 }
+
+func ShrinkToEven(a int, shrink float64) int {
+	if a == 0 {
+		return 0
+	}
+
+	return RoundToEven(float64(a) / shrink)
+}

+ 1 - 1
options/processing_options.go

@@ -1113,7 +1113,7 @@ func defaultProcessingOptions(headers http.Header) (*ProcessingOptions, error) {
 		}
 		if len(headerWidth) > 0 {
 			if w, err := strconv.Atoi(headerWidth); err == nil {
-				po.Width = imath.Scale(w, 1/po.Dpr)
+				po.Width = imath.Shrink(w, po.Dpr)
 			}
 		}
 	}

+ 7 - 5
processing/calc_position.go

@@ -1,22 +1,24 @@
 package processing
 
 import (
+	"math"
+
 	"github.com/imgproxy/imgproxy/v3/imath"
 	"github.com/imgproxy/imgproxy/v3/options"
 )
 
 func calcPosition(width, height, innerWidth, innerHeight int, gravity *options.GravityOptions, dpr float64, allowOverflow bool) (left, top int) {
 	if gravity.Type == options.GravityFocusPoint {
-		pointX := imath.Scale(width, gravity.X)
-		pointY := imath.Scale(height, gravity.Y)
+		pointX := imath.ScaleToEven(width, gravity.X)
+		pointY := imath.ScaleToEven(height, gravity.Y)
 
 		left = pointX - innerWidth/2
 		top = pointY - innerHeight/2
 	} else {
-		offX, offY := int(gravity.X*dpr), int(gravity.Y*dpr)
+		offX, offY := int(math.RoundToEven(gravity.X*dpr)), int(math.RoundToEven(gravity.Y*dpr))
 
-		left = (width-innerWidth+1)/2 + offX
-		top = (height-innerHeight+1)/2 + offY
+		left = imath.ShrinkToEven(width-innerWidth+1, 2) + offX
+		top = imath.ShrinkToEven(height-innerHeight+1, 2) + offY
 
 		if gravity.Type == options.GravityNorth || gravity.Type == options.GravityNorthEast || gravity.Type == options.GravityNorthWest {
 			top = 0 + offY

+ 4 - 4
processing/padding.go

@@ -12,10 +12,10 @@ func padding(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptio
 		return nil
 	}
 
-	paddingTop := imath.Scale(po.Padding.Top, pctx.dprScale)
-	paddingRight := imath.Scale(po.Padding.Right, pctx.dprScale)
-	paddingBottom := imath.Scale(po.Padding.Bottom, pctx.dprScale)
-	paddingLeft := imath.Scale(po.Padding.Left, pctx.dprScale)
+	paddingTop := imath.ScaleToEven(po.Padding.Top, pctx.dprScale)
+	paddingRight := imath.ScaleToEven(po.Padding.Right, pctx.dprScale)
+	paddingBottom := imath.ScaleToEven(po.Padding.Bottom, pctx.dprScale)
+	paddingLeft := imath.ScaleToEven(po.Padding.Left, pctx.dprScale)
 
 	return img.Embed(
 		img.Width()+paddingLeft+paddingRight,

+ 2 - 2
processing/watermark.go

@@ -32,8 +32,8 @@ func prepareWatermark(wm *vips.Image, wmData *imagedata.ImageData, opts *options
 	po.Format = wmData.Type
 
 	if opts.Scale > 0 {
-		po.Width = imath.Max(imath.Scale(imgWidth, opts.Scale), 1)
-		po.Height = imath.Max(imath.Scale(imgHeight, opts.Scale), 1)
+		po.Width = imath.Max(imath.ScaleToEven(imgWidth, opts.Scale), 1)
+		po.Height = imath.Max(imath.ScaleToEven(imgHeight, opts.Scale), 1)
 	}
 
 	if opts.Replicate {