diff --git a/process.go b/process.go index e2121ed2..b8afad12 100644 --- a/process.go +++ b/process.go @@ -120,8 +120,8 @@ func calcJpegShink(scale float64, imgtype imageType) int { func calcCrop(width, height, cropWidth, cropHeight int, gravity *gravityOptions) (left, top int) { if gravity.Type == gravityFocusPoint { - pointX := int(float64(width) * gravity.X) - pointY := int(float64(height) * gravity.Y) + pointX := scaleInt(width, gravity.X) + pointY := scaleInt(height, gravity.Y) left = maxInt(0, minInt(pointX-cropWidth/2, width-cropWidth)) top = maxInt(0, minInt(pointY-cropHeight/2, height-cropHeight)) @@ -163,17 +163,8 @@ func cropImage(img *vipsImage, cropWidth, cropHeight int, gravity *gravityOption imgWidth, imgHeight := img.Width(), img.Height() - if cropWidth == 0 { - cropWidth = imgWidth - } else { - cropWidth = minInt(cropWidth, imgWidth) - } - - if cropHeight == 0 { - cropHeight = imgHeight - } else { - cropHeight = minInt(cropHeight, imgHeight) - } + cropWidth = minNonZeroInt(cropWidth, imgWidth) + cropHeight = minNonZeroInt(cropHeight, imgHeight) if cropWidth >= imgWidth && cropHeight >= imgHeight { return nil @@ -195,32 +186,23 @@ func cropImage(img *vipsImage, cropWidth, cropHeight int, gravity *gravityOption return img.Crop(left, top, cropWidth, cropHeight) } -func scaleSize(size int, scale float64) int { - if size == 0 { - return 0 - } - - return roundToInt(float64(size) * scale) -} - func prepareWatermark(wm *vipsImage, wmData *watermarkData, opts *watermarkOptions, imgWidth, imgHeight int) error { if err := wm.Load(wmData.data, wmData.imgtype, 1, 1.0, 1); err != nil { return err } - po := processingOptions{ - Resize: resizeFit, - Dpr: 1, - Enlarge: true, - Format: wmData.imgtype, - } + po := newProcessingOptions() + po.Resize = resizeFit + po.Dpr = 1 + po.Enlarge = true + po.Format = wmData.imgtype if opts.Scale > 0 { - po.Width = maxInt(int(float64(imgWidth)*opts.Scale), 1) - po.Height = maxInt(int(float64(imgHeight)*opts.Scale), 1) + po.Width = maxInt(scaleInt(imgWidth, opts.Scale), 1) + po.Height = maxInt(scaleInt(imgHeight, opts.Scale), 1) } - if err := transformImage(context.Background(), wm, wmData.data, &po, wmData.imgtype); err != nil { + if err := transformImage(context.Background(), wm, wmData.data, po, wmData.imgtype); err != nil { return err } @@ -261,7 +243,6 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces var err error srcWidth, srcHeight, angle, flip := extractMeta(img) - cropWidth, cropHeight := po.Crop.Width, po.Crop.Height cropGravity := po.Crop.Gravity @@ -269,19 +250,13 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces cropGravity = po.Gravity } - widthToScale, heightToScale := srcWidth, srcHeight - - if cropWidth > 0 { - widthToScale = minInt(cropWidth, srcWidth) - } - if cropHeight > 0 { - heightToScale = minInt(cropHeight, srcHeight) - } + widthToScale := minNonZeroInt(cropWidth, srcWidth) + heightToScale := minNonZeroInt(cropHeight, srcHeight) scale := calcScale(widthToScale, heightToScale, po, imgtype) - cropWidth = scaleSize(cropWidth, scale) - cropHeight = scaleSize(cropHeight, scale) + cropWidth = scaleInt(cropWidth, scale) + cropHeight = scaleInt(cropHeight, scale) cropGravity.X *= scale cropGravity.Y *= scale @@ -303,8 +278,8 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces // Update scale after scale-on-load newWidth, newHeight, _, _ := extractMeta(img) - widthToScale = scaleSize(widthToScale, float64(newWidth)/float64(srcWidth)) - heightToScale = scaleSize(heightToScale, float64(newHeight)/float64(srcHeight)) + widthToScale = scaleInt(widthToScale, float64(newWidth)/float64(srcWidth)) + heightToScale = scaleInt(heightToScale, float64(newHeight)/float64(srcHeight)) scale = calcScale(widthToScale, heightToScale, po, imgtype) } @@ -363,21 +338,12 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces checkTimeout(ctx) - dprWidth := roundToInt(float64(po.Width) * po.Dpr) - dprHeight := roundToInt(float64(po.Height) * po.Dpr) + dprWidth := scaleInt(po.Width, po.Dpr) + dprHeight := scaleInt(po.Height, po.Dpr) if cropGravity.Type == po.Gravity.Type && cropGravity.Type != gravityFocusPoint { - if cropWidth == 0 { - cropWidth = dprWidth - } else if dprWidth > 0 { - cropWidth = minInt(cropWidth, dprWidth) - } - - if cropHeight == 0 { - cropHeight = dprHeight - } else if dprHeight > 0 { - cropHeight = minInt(cropHeight, dprHeight) - } + cropWidth = minNonZeroInt(cropWidth, dprWidth) + cropHeight = minNonZeroInt(cropHeight, dprHeight) sumGravity := gravityOptions{ Type: cropGravity.Type, diff --git a/processing_options.go b/processing_options.go index 389b050b..3c2c485e 100644 --- a/processing_options.go +++ b/processing_options.go @@ -158,6 +158,24 @@ func (rt resizeType) String() string { return "" } +func newProcessingOptions() *processingOptions { + return &processingOptions{ + Resize: resizeFit, + Width: 0, + Height: 0, + Gravity: gravityOptions{Type: gravityCenter}, + Enlarge: false, + Quality: conf.Quality, + Format: imageTypeUnknown, + Background: rgbColor{255, 255, 255}, + Blur: 0, + Sharpen: 0, + Dpr: 1, + Watermark: watermarkOptions{Opacity: 1, Replicate: false, Gravity: gravityCenter}, + UsedPresets: make([]string, 0, len(conf.Presets)), + } +} + func (po *processingOptions) isPresetUsed(name string) bool { for _, usedName := range po.UsedPresets { if usedName == name { @@ -736,21 +754,7 @@ func parseURLOptions(opts []string) (urlOptions, []string) { } func defaultProcessingOptions(headers *processingHeaders) (*processingOptions, error) { - po := processingOptions{ - Resize: resizeFit, - Width: 0, - Height: 0, - Gravity: gravityOptions{Type: gravityCenter}, - Enlarge: false, - Quality: conf.Quality, - Format: imageTypeUnknown, - Background: rgbColor{255, 255, 255}, - Blur: 0, - Sharpen: 0, - Dpr: 1, - Watermark: watermarkOptions{Opacity: 1, Replicate: false, Gravity: gravityCenter}, - UsedPresets: make([]string, 0, len(conf.Presets)), - } + po := newProcessingOptions() if strings.Contains(headers.Accept, "image/webp") { po.PreferWebP = conf.EnableWebpDetection || conf.EnforceWebp @@ -773,12 +777,12 @@ func defaultProcessingOptions(headers *processingHeaders) (*processingOptions, e } } if _, ok := conf.Presets["default"]; ok { - if err := applyPresetOption(&po, []string{"default"}); err != nil { - return &po, err + if err := applyPresetOption(po, []string{"default"}); err != nil { + return po, err } } - return &po, nil + return po, nil } func parsePathAdvanced(parts []string, headers *processingHeaders) (string, *processingOptions, error) { diff --git a/utils.go b/utils.go index d6b880c8..ecafd3bd 100644 --- a/utils.go +++ b/utils.go @@ -16,6 +16,25 @@ func minInt(a, b int) int { return b } +func minNonZeroInt(a, b int) int { + switch { + case a == 0: + return b + case b == 0: + return a + } + + return minInt(a, b) +} + func roundToInt(a float64) int { return int(math.Round(a)) } + +func scaleInt(a int, scale float64) int { + if a == 0 { + return 0 + } + + return roundToInt(float64(a) * scale) +}