scale_on_load.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package processing
  2. import (
  3. "math"
  4. "github.com/imgproxy/imgproxy/v3/config"
  5. "github.com/imgproxy/imgproxy/v3/imagedata"
  6. "github.com/imgproxy/imgproxy/v3/imagetype"
  7. "github.com/imgproxy/imgproxy/v3/imath"
  8. "github.com/imgproxy/imgproxy/v3/options"
  9. "github.com/imgproxy/imgproxy/v3/vips"
  10. )
  11. func canScaleOnLoad(imgtype imagetype.Type, scale float64) bool {
  12. if imgtype == imagetype.SVG {
  13. return true
  14. }
  15. if config.DisableShrinkOnLoad || scale >= 1 {
  16. return false
  17. }
  18. return imgtype == imagetype.JPEG || imgtype == imagetype.WEBP
  19. }
  20. func calcJpegShink(scale float64, imgtype imagetype.Type) int {
  21. shrink := int(1.0 / scale)
  22. switch {
  23. case shrink >= 8:
  24. return 8
  25. case shrink >= 4:
  26. return 4
  27. case shrink >= 2:
  28. return 2
  29. }
  30. return 1
  31. }
  32. func scaleOnLoad(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptions, imgdata *imagedata.ImageData) error {
  33. prescale := math.Max(pctx.wscale, pctx.hscale)
  34. if pctx.trimmed || prescale == 1 || imgdata == nil || !canScaleOnLoad(pctx.imgtype, prescale) {
  35. return nil
  36. }
  37. jpegShrink := calcJpegShink(prescale, pctx.imgtype)
  38. if pctx.imgtype == imagetype.JPEG && jpegShrink == 1 {
  39. return nil
  40. }
  41. if err := img.Load(imgdata, jpegShrink, prescale, 1); err != nil {
  42. return err
  43. }
  44. // Update scales after scale-on-load
  45. newWidth, newHeight, _, _ := extractMeta(img, po.Rotate, po.AutoRotate)
  46. wpreshrink := float64(pctx.srcWidth) / float64(newWidth)
  47. hpreshrink := float64(pctx.srcHeight) / float64(newHeight)
  48. pctx.wscale = wpreshrink * pctx.wscale
  49. if newWidth == imath.Scale(newWidth, pctx.wscale) {
  50. pctx.wscale = 1.0
  51. }
  52. pctx.hscale = hpreshrink * pctx.hscale
  53. if newHeight == imath.Scale(newHeight, pctx.hscale) {
  54. pctx.hscale = 1.0
  55. }
  56. if pctx.cropWidth > 0 {
  57. pctx.cropWidth = imath.Max(1, imath.Shrink(pctx.cropWidth, wpreshrink))
  58. }
  59. if pctx.cropHeight > 0 {
  60. pctx.cropHeight = imath.Max(1, imath.Shrink(pctx.cropHeight, hpreshrink))
  61. }
  62. if pctx.cropGravity.Type != options.GravityFocusPoint {
  63. pctx.cropGravity.X /= wpreshrink
  64. pctx.cropGravity.Y /= hpreshrink
  65. }
  66. return nil
  67. }