Kaynağa Gözat

force resizing type

DarthSim 4 yıl önce
ebeveyn
işleme
c711791f7a
7 değiştirilmiş dosya ile 78 ekleme ve 52 silme
  1. 1 0
      CHANGELOG.md
  2. 1 0
      docs/generating_the_url.md
  3. 62 40
      process.go
  4. 5 3
      processing_options.go
  5. 4 4
      vips.c
  6. 3 3
      vips.go
  7. 2 2
      vips.h

+ 1 - 0
CHANGELOG.md

@@ -6,6 +6,7 @@
 - [expires](https://docs.imgproxy.net/#/generating_the_url?id=expires) processing option.
 - [skip processing](https://docs.imgproxy.net/#/generating_the_url?id=skip-processing) processing option.
 - [Datadog](./docs/datadog.md) metrics.
+- `force` resizing type.
 
 ### Removed
 - Removed basic URL format, use [advanced one](./docs/generating_the_url.md) instead.

+ 1 - 0
docs/generating_the_url.md

@@ -56,6 +56,7 @@ Defines how imgproxy will resize the source image. Supported resizing types are:
 
 * `fit`: resizes the image while keeping aspect ratio to fit given size;
 * `fill`: resizes the image while keeping aspect ratio to fill given size and cropping projecting parts;
+* `force`: resizes the image without keeping aspect ratio;
 * `auto`: if both source and resulting dimensions have the same orientation (portrait or landscape), imgproxy will use `fill`. Otherwise, it will use `fit`.
 
 Default: `fit`

+ 62 - 40
process.go

@@ -70,8 +70,8 @@ func extractMeta(img *vipsImage, baseAngle int, useOrientation bool) (int, int,
 	return width, height, angle, flip
 }
 
-func calcScale(width, height int, po *processingOptions, imgtype imageType) float64 {
-	var shrink float64
+func calcScale(width, height int, po *processingOptions, imgtype imageType) (float64, float64) {
+	var wshrink, hshrink float64
 
 	srcW, srcH := float64(width), float64(height)
 	dstW, dstH := float64(po.Width), float64(po.Height)
@@ -80,21 +80,28 @@ func calcScale(width, height int, po *processingOptions, imgtype imageType) floa
 		dstW = srcW
 	}
 
+	if dstW == srcW {
+		wshrink = 1
+	} else {
+		wshrink = srcW / dstW
+	}
+
 	if po.Height == 0 {
 		dstH = srcH
 	}
 
-	if dstW == srcW && dstH == srcH {
-		shrink = 1
+	if dstH == srcH {
+		hshrink = 1
 	} else {
-		wshrink := srcW / dstW
-		hshrink := srcH / dstH
+		hshrink = srcH / dstH
+	}
 
+	if wshrink != 1 || hshrink != 1 {
 		rt := po.ResizingType
 
 		if rt == resizeAuto {
-			srcD := width - height
-			dstD := po.Width - po.Height
+			srcD := srcW - srcH
+			dstD := dstW - dstH
 
 			if (srcD >= 0 && dstD >= 0) || (srcD < 0 && dstD < 0) {
 				rt = resizeFill
@@ -105,31 +112,41 @@ func calcScale(width, height int, po *processingOptions, imgtype imageType) floa
 
 		switch {
 		case po.Width == 0:
-			shrink = hshrink
+			wshrink = hshrink
 		case po.Height == 0:
-			shrink = wshrink
+			hshrink = wshrink
 		case rt == resizeFit:
-			shrink = math.Max(wshrink, hshrink)
-		default:
-			shrink = math.Min(wshrink, hshrink)
+			wshrink = math.Max(wshrink, hshrink)
+			hshrink = wshrink
+		case rt == resizeFill:
+			wshrink = math.Min(wshrink, hshrink)
+			hshrink = wshrink
 		}
 	}
 
-	if !po.Enlarge && shrink < 1 && imgtype != imageTypeSVG {
-		shrink = 1
+	if !po.Enlarge && imgtype != imageTypeSVG {
+		if wshrink < 1 {
+			hshrink /= wshrink
+			wshrink = 1
+		}
+		if hshrink < 1 {
+			wshrink /= hshrink
+			hshrink = 1
+		}
 	}
 
-	shrink /= po.Dpr
+	wshrink /= po.Dpr
+	hshrink /= po.Dpr
 
-	if shrink > srcW {
-		shrink = srcW
+	if wshrink > srcW {
+		wshrink = srcW
 	}
 
-	if shrink > srcH {
-		shrink = srcH
+	if hshrink > srcH {
+		hshrink = srcH
 	}
 
-	return 1.0 / shrink
+	return 1.0 / wshrink, 1.0 / hshrink
 }
 
 func canScaleOnLoad(imgtype imageType, scale float64) bool {
@@ -353,38 +370,42 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces
 	widthToScale := minNonZeroInt(cropWidth, srcWidth)
 	heightToScale := minNonZeroInt(cropHeight, srcHeight)
 
-	scale := calcScale(widthToScale, heightToScale, po, imgtype)
+	wscale, hscale := calcScale(widthToScale, heightToScale, po, imgtype)
 
 	if cropWidth > 0 {
-		cropWidth = maxInt(1, scaleInt(cropWidth, scale))
+		cropWidth = maxInt(1, scaleInt(cropWidth, wscale))
 	}
 	if cropHeight > 0 {
-		cropHeight = maxInt(1, scaleInt(cropHeight, scale))
+		cropHeight = maxInt(1, scaleInt(cropHeight, hscale))
 	}
 	if cropGravity.Type != gravityFocusPoint {
-		cropGravity.X *= scale
-		cropGravity.Y *= scale
+		cropGravity.X *= wscale
+		cropGravity.Y *= hscale
 	}
 
-	if !trimmed && scale != 1 && data != nil && canScaleOnLoad(imgtype, scale) {
-		jpegShrink := calcJpegShink(scale, imgtype)
+	prescale := math.Max(wscale, hscale)
+
+	if !trimmed && prescale != 1 && data != nil && canScaleOnLoad(imgtype, prescale) {
+		jpegShrink := calcJpegShink(prescale, imgtype)
 
 		if imgtype != imageTypeJPEG || jpegShrink != 1 {
 			// Do some scale-on-load
-			if err = img.Load(data, imgtype, jpegShrink, scale, 1); err != nil {
+			if err = img.Load(data, imgtype, jpegShrink, prescale, 1); err != nil {
 				return err
 			}
 		}
 
-		// Update scale after scale-on-load
+		// Update scales after scale-on-load
 		newWidth, newHeight, _, _ := extractMeta(img, po.Rotate, po.AutoRotate)
-		if srcWidth > srcHeight {
-			scale = float64(srcWidth) * scale / float64(newWidth)
-		} else {
-			scale = float64(srcHeight) * scale / float64(newHeight)
+
+		wscale = float64(srcWidth) * wscale / float64(newWidth)
+		if srcWidth == scaleInt(srcWidth, wscale) {
+			wscale = 1.0
 		}
-		if srcWidth == scaleInt(srcWidth, scale) && srcHeight == scaleInt(srcHeight, scale) {
-			scale = 1.0
+
+		hscale = float64(srcHeight) * hscale / float64(newHeight)
+		if srcHeight == scaleInt(srcHeight, hscale) {
+			hscale = 1.0
 		}
 	}
 
@@ -393,7 +414,7 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces
 	}
 
 	iccImported := false
-	convertToLinear := conf.UseLinearColorspace && scale != 1
+	convertToLinear := conf.UseLinearColorspace && (wscale != 1 || hscale != 1)
 
 	if convertToLinear || !img.IsSRGB() {
 		if err = img.ImportColourProfile(); err != nil {
@@ -414,8 +435,8 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces
 
 	hasAlpha := img.HasAlpha()
 
-	if scale != 1 {
-		if err = img.Resize(scale, hasAlpha); err != nil {
+	if wscale != 1 || hscale != 1 {
+		if err = img.Resize(wscale, hscale, hasAlpha); err != nil {
 			return err
 		}
 	}
@@ -452,7 +473,8 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces
 		webpLimitShrink := float64(maxInt(img.Width(), img.Height())) / webpMaxDimension
 
 		if webpLimitShrink > 1.0 {
-			if err = img.Resize(1.0/webpLimitShrink, hasAlpha); err != nil {
+			scale := 1.0 / webpLimitShrink
+			if err = img.Resize(scale, scale, hasAlpha); err != nil {
 				return err
 			}
 			logWarning("WebP dimension size is limited to %d. The image is rescaled to %dx%d", int(webpMaxDimension), img.Width(), img.Height())

+ 5 - 3
processing_options.go

@@ -65,13 +65,15 @@ type resizeType int
 const (
 	resizeFit resizeType = iota
 	resizeFill
+	resizeForce
 	resizeAuto
 )
 
 var resizeTypes = map[string]resizeType{
-	"fit":  resizeFit,
-	"fill": resizeFill,
-	"auto": resizeAuto,
+	"fit":   resizeFit,
+	"fill":  resizeFill,
+	"force": resizeForce,
+	"auto":  resizeAuto,
 }
 
 type rgbColor struct{ R, G, B uint8 }

+ 4 - 4
vips.c

@@ -211,12 +211,12 @@ vips_rad2float_go(VipsImage *in, VipsImage **out) {
 }
 
 int
-vips_resize_go(VipsImage *in, VipsImage **out, double scale) {
-  return vips_resize(in, out, scale, NULL);
+vips_resize_go(VipsImage *in, VipsImage **out, double wscale, double hscale) {
+  return vips_resize(in, out, wscale, "vscale", hscale, NULL);
 }
 
 int
-vips_resize_with_premultiply(VipsImage *in, VipsImage **out, double scale) {
+vips_resize_with_premultiply(VipsImage *in, VipsImage **out, double wscale, double hscale) {
 	VipsBandFormat format;
   VipsImage *tmp1, *tmp2;
 
@@ -225,7 +225,7 @@ vips_resize_with_premultiply(VipsImage *in, VipsImage **out, double scale) {
   if (vips_premultiply(in, &tmp1, NULL))
     return 1;
 
-	if (vips_resize(tmp1, &tmp2, scale, NULL)) {
+	if (vips_resize(tmp1, &tmp2, wscale, "vscale", hscale, NULL)) {
     clear_image(&tmp1);
 		return 1;
   }

+ 3 - 3
vips.go

@@ -403,15 +403,15 @@ func (img *vipsImage) Rad2Float() error {
 	return nil
 }
 
-func (img *vipsImage) Resize(scale float64, hasAlpa bool) error {
+func (img *vipsImage) Resize(wscale, hscale float64, hasAlpa bool) error {
 	var tmp *C.VipsImage
 
 	if hasAlpa {
-		if C.vips_resize_with_premultiply(img.VipsImage, &tmp, C.double(scale)) != 0 {
+		if C.vips_resize_with_premultiply(img.VipsImage, &tmp, C.double(wscale), C.double(hscale)) != 0 {
 			return vipsError()
 		}
 	} else {
-		if C.vips_resize_go(img.VipsImage, &tmp, C.double(scale)) != 0 {
+		if C.vips_resize_go(img.VipsImage, &tmp, C.double(wscale), C.double(hscale)) != 0 {
 			return vipsError()
 		}
 	}

+ 2 - 2
vips.h

@@ -55,8 +55,8 @@ int vips_copy_go(VipsImage *in, VipsImage **out);
 int vips_cast_go(VipsImage *in, VipsImage **out, VipsBandFormat format);
 int vips_rad2float_go(VipsImage *in, VipsImage **out);
 
-int vips_resize_go(VipsImage *in, VipsImage **out, double scale);
-int vips_resize_with_premultiply(VipsImage *in, VipsImage **out, double scale);
+int vips_resize_go(VipsImage *in, VipsImage **out, double wscale, double hscale);
+int vips_resize_with_premultiply(VipsImage *in, VipsImage **out, double wscale, double hscale);
 
 int vips_icc_is_srgb_iec61966(VipsImage *in);
 int vips_has_embedded_icc(VipsImage *in);