瀏覽代碼

Fixes to prepare.go

Viktor Sokolov 2 周之前
父節點
當前提交
3b63c08ad6
共有 8 個文件被更改,包括 61 次插入103 次删除
  1. 7 0
      imath/imath.go
  2. 0 1
      imgproxy.go
  3. 2 1
      processing/config.go
  4. 3 3
      processing/pipeline.go
  5. 15 27
      processing/prepare.go
  6. 21 66
      processing/processing_test.go
  7. 2 2
      processing/scale_on_load.go
  8. 11 3
      processing/watermark.go

+ 7 - 0
imath/imath.go

@@ -52,3 +52,10 @@ func ShrinkToEven(a int, shrink float64) int {
 
 	return RoundToEven(float64(a) / shrink)
 }
+
+func NonZero[T ~int | ~float32 | ~float64](a, b T) T {
+	if a != 0 {
+		return a
+	}
+	return b
+}

+ 0 - 1
imgproxy.go

@@ -32,7 +32,6 @@ type ImgproxyHandlers struct {
 	Landing    *landinghandler.Handler
 	Processing *processinghandler.Handler
 	Stream     *streamhandler.Handler
-	Processor  *processing.Processor
 }
 
 // Imgproxy holds all the components needed for imgproxy to function

+ 2 - 1
processing/config.go

@@ -2,6 +2,7 @@ package processing
 
 import (
 	"errors"
+	"fmt"
 	"log/slog"
 
 	"github.com/imgproxy/imgproxy/v3/config"
@@ -54,7 +55,7 @@ func (c *Config) Validate() error {
 
 	for _, t := range c.PreferredFormats {
 		if !vips.SupportsSave(t) {
-			slog.Warn("%s can't be a preferred format as it's saving is not supported", t)
+			slog.Warn(fmt.Sprintf("%s can't be a preferred format as it's saving is not supported", t))
 		} else {
 			filtered = append(filtered, t)
 		}

+ 3 - 3
processing/pipeline.go

@@ -14,13 +14,13 @@ type Context struct {
 	// The context to check for timeouts and cancellations
 	Ctx context.Context
 
-	// VIPS image
+	// Current image being processed
 	Img *vips.Image
 
 	// Processing options this pipeline runs with
 	PO *options.ProcessingOptions
 
-	// Source image data
+	// Original image data
 	ImgData imagedata.ImageData
 
 	// The watermark image provider, if any watermarking is to be done.
@@ -84,7 +84,7 @@ func (p Pipeline) Run(
 	imgdata imagedata.ImageData,
 ) error {
 	pctx := p.newContext(ctx, img, po, imgdata)
-	pctx.CalcParams() // calc initial params if not done before
+	pctx.CalcParams()
 
 	for _, step := range p {
 		if err := step(&pctx); err != nil {

+ 15 - 27
processing/prepare.go

@@ -9,11 +9,11 @@ import (
 )
 
 // ExtractGeometry extracts image width, height, orientation angle and flip flag from the image metadata.
-func (c *Context) ExtractGeometry(img *vips.Image, baseAngle int, autoRotate bool) (int, int, int, bool) {
+func ExtractGeometry(img *vips.Image, baseAngle int, autoRotate bool) (int, int, int, bool) {
 	width := img.Width()
 	height := img.Height()
 
-	angle, flip := c.angleFlip(img, autoRotate)
+	angle, flip := angleFlip(img, autoRotate)
 
 	if (angle+baseAngle)%180 != 0 {
 		width, height = height, width
@@ -24,7 +24,7 @@ func (c *Context) ExtractGeometry(img *vips.Image, baseAngle int, autoRotate boo
 
 // angleFlip returns the orientation angle and flip flag based on the image metadata
 // and po.AutoRotate flag.
-func (c *Context) angleFlip(img *vips.Image, autoRotate bool) (int, bool) {
+func angleFlip(img *vips.Image, autoRotate bool) (int, bool) {
 	if !autoRotate {
 		return 0, false
 	}
@@ -65,28 +65,20 @@ func (c *Context) CalcCropSize(orig int, crop float64) int {
 	}
 }
 
-// calcShrink calculates the destination size and shrink factor
-func calcShrink(value int, src, dst float64) (float64, float64) {
-	if value == 0 {
-		dst = src
-	}
-
-	shrink := 1.0
-	if dst != src {
-		shrink = src / dst
-	}
-
-	return dst, shrink
-}
-
 func (c *Context) calcScale(width, height int, po *options.ProcessingOptions) {
-	var wshrink, hshrink float64
-
+	wshrink, hshrink := 1.0, 1.0
 	srcW, srcH := float64(width), float64(height)
-	dstW, dstH := float64(po.Width), float64(po.Height)
 
-	dstW, wshrink = calcShrink(po.Width, srcW, dstW)
-	dstH, hshrink = calcShrink(po.Height, srcH, dstH)
+	dstW := imath.NonZero(float64(po.Width), srcW)
+	dstH := imath.NonZero(float64(po.Height), srcH)
+
+	if dstW != srcW {
+		wshrink = srcW / dstW
+	}
+
+	if dstH != srcH {
+		hshrink = srcH / dstH
+	}
 
 	if wshrink != 1 || hshrink != 1 {
 		rt := po.ResizingType
@@ -273,11 +265,7 @@ func (c *Context) limitScale(widthToScale, heightToScale int, po *options.Proces
 // Prepare calculates context image parameters based on the current image size.
 // Some steps (like trim) must call this function when finished.
 func (c *Context) CalcParams() {
-	if c.ImgData == nil {
-		return
-	}
-
-	c.SrcWidth, c.SrcHeight, c.Angle, c.Flip = c.ExtractGeometry(c.Img, c.PO.Rotate, c.PO.AutoRotate)
+	c.SrcWidth, c.SrcHeight, c.Angle, c.Flip = ExtractGeometry(c.Img, c.PO.Rotate, c.PO.AutoRotate)
 
 	c.CropWidth = c.CalcCropSize(c.SrcWidth, c.PO.Crop.Width)
 	c.CropHeight = c.CalcCropSize(c.SrcHeight, c.PO.Crop.Height)

+ 21 - 66
processing/processing_test.go

@@ -101,6 +101,14 @@ func (s *ProcessingTestSuite) checkSize(r *Result, width, height int) {
 	s.Require().Equal(height, r.ResultHeight, "Height mismatch")
 }
 
+func (s *ProcessingTestSuite) processImageAndCheck(imgdata imagedata.ImageData, po *options.ProcessingOptions, expectedWidth, expectedHeight int) {
+	result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
+	s.Require().NoError(err)
+	s.Require().NotNil(result)
+
+	s.checkSize(result, expectedWidth, expectedHeight)
+}
+
 func (s *ProcessingTestSuite) TestResizeToFit() {
 	imgdata := s.openFile("test2.jpg")
 
@@ -130,11 +138,7 @@ func (s *ProcessingTestSuite) TestResizeToFit() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -169,11 +173,7 @@ func (s *ProcessingTestSuite) TestResizeToFitEnlarge() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -213,11 +213,7 @@ func (s *ProcessingTestSuite) TestResizeToFitExtend() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -257,11 +253,7 @@ func (s *ProcessingTestSuite) TestResizeToFitExtendAR() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -295,11 +287,7 @@ func (s *ProcessingTestSuite) TestResizeToFill() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -334,11 +322,7 @@ func (s *ProcessingTestSuite) TestResizeToFillEnlarge() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -380,11 +364,7 @@ func (s *ProcessingTestSuite) TestResizeToFillExtend() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -426,11 +406,7 @@ func (s *ProcessingTestSuite) TestResizeToFillExtendAR() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -464,11 +440,7 @@ func (s *ProcessingTestSuite) TestResizeToFillDown() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -503,11 +475,7 @@ func (s *ProcessingTestSuite) TestResizeToFillDownEnlarge() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -549,11 +517,7 @@ func (s *ProcessingTestSuite) TestResizeToFillDownExtend() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -593,11 +557,7 @@ func (s *ProcessingTestSuite) TestResizeToFillDownExtendAR() {
 			po.Width = tc.width
 			po.Height = tc.height
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }
@@ -1022,12 +982,7 @@ func (s *ProcessingTestSuite) TestResultSizeLimit() {
 			po.Rotate = tc.rotate
 			po.Padding = tc.padding
 
-			result, err := s.processor().ProcessImage(context.Background(), imgdata, po, nil)
-
-			s.Require().NoError(err)
-			s.Require().NotNil(result)
-
-			s.checkSize(result, tc.outWidth, tc.outHeight)
+			s.processImageAndCheck(imgdata, po, tc.outWidth, tc.outHeight)
 		})
 	}
 }

+ 2 - 2
processing/scale_on_load.go

@@ -70,7 +70,7 @@ func (p *Processor) scaleOnLoad(c *Context) error {
 		}
 
 		angle, flip := 0, false
-		newWidth, newHeight, angle, flip = c.ExtractGeometry(thumbnail, c.PO.Rotate, c.PO.AutoRotate)
+		newWidth, newHeight, angle, flip = ExtractGeometry(thumbnail, c.PO.Rotate, c.PO.AutoRotate)
 
 		if newWidth >= c.SrcWidth || float64(newWidth)/float64(c.SrcWidth) < prescale {
 			return nil
@@ -90,7 +90,7 @@ func (p *Processor) scaleOnLoad(c *Context) error {
 			return err
 		}
 
-		newWidth, newHeight, _, _ = c.ExtractGeometry(c.Img, c.PO.Rotate, c.PO.AutoRotate)
+		newWidth, newHeight, _, _ = ExtractGeometry(c.Img, c.PO.Rotate, c.PO.AutoRotate)
 	}
 
 	// Update scales after scale-on-load

+ 11 - 3
processing/watermark.go

@@ -24,7 +24,15 @@ func (p *Processor) watermarkPipeline() Pipeline {
 	}
 }
 
-func (p *Processor) prepareWatermark(wm *vips.Image, wmData imagedata.ImageData, po *options.ProcessingOptions, imgWidth, imgHeight int, offsetScale float64, framesCount int) error {
+func (p *Processor) prepareWatermark(
+	ctx context.Context,
+	wm *vips.Image,
+	wmData imagedata.ImageData,
+	po *options.ProcessingOptions,
+	imgWidth, imgHeight int,
+	offsetScale float64,
+	framesCount int,
+) error {
 	if err := wm.Load(wmData, 1, 1.0, 1); err != nil {
 		return err
 	}
@@ -64,7 +72,7 @@ func (p *Processor) prepareWatermark(wm *vips.Image, wmData imagedata.ImageData,
 		wmPo.Padding.Bottom = offY - wmPo.Padding.Top
 	}
 
-	if err := p.watermarkPipeline().Run(context.Background(), wm, wmPo, wmData); err != nil {
+	if err := p.watermarkPipeline().Run(ctx, wm, wmPo, wmData); err != nil {
 		return err
 	}
 
@@ -113,7 +121,7 @@ func (p *Processor) applyWatermark(
 	height := img.Height()
 	frameHeight := height / framesCount
 
-	if err := p.prepareWatermark(wm, wmData, po, width, frameHeight, offsetScale, framesCount); err != nil {
+	if err := p.prepareWatermark(ctx, wm, wmData, po, width, frameHeight, offsetScale, framesCount); err != nil {
 		return err
 	}