fix_size.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package processing
  2. import (
  3. "math"
  4. "github.com/imgproxy/imgproxy/v3/imagedata"
  5. "github.com/imgproxy/imgproxy/v3/imagetype"
  6. "github.com/imgproxy/imgproxy/v3/imath"
  7. "github.com/imgproxy/imgproxy/v3/options"
  8. "github.com/imgproxy/imgproxy/v3/vips"
  9. log "github.com/sirupsen/logrus"
  10. )
  11. const (
  12. // https://chromium.googlesource.com/webm/libwebp/+/refs/heads/master/src/webp/encode.h#529
  13. webpMaxDimension = 16383.0
  14. heifMaxDimension = 16384.0
  15. gifMaxDimension = 65535.0
  16. icoMaxDimension = 256.0
  17. )
  18. func fixWebpSize(img *vips.Image) error {
  19. webpLimitShrink := float64(imath.Max(img.Width(), img.Height())) / webpMaxDimension
  20. if webpLimitShrink <= 1.0 {
  21. return nil
  22. }
  23. scale := 1.0 / webpLimitShrink
  24. if err := img.Resize(scale, scale); err != nil {
  25. return err
  26. }
  27. log.Warningf("WebP dimension size is limited to %d. The image is rescaled to %dx%d", int(webpMaxDimension), img.Width(), img.Height())
  28. return nil
  29. }
  30. func fixHeifSize(img *vips.Image) error {
  31. heifLimitShrink := float64(imath.Max(img.Width(), img.Height())) / heifMaxDimension
  32. if heifLimitShrink <= 1.0 {
  33. return nil
  34. }
  35. scale := 1.0 / heifLimitShrink
  36. if err := img.Resize(scale, scale); err != nil {
  37. return err
  38. }
  39. log.Warningf("AVIF/HEIC dimension size is limited to %d. The image is rescaled to %dx%d", int(heifMaxDimension), img.Width(), img.Height())
  40. return nil
  41. }
  42. func fixGifSize(img *vips.Image) error {
  43. gifMaxResolution := float64(vips.GifResolutionLimit())
  44. gifResLimitShrink := float64(img.Width()*img.Height()) / gifMaxResolution
  45. gifDimLimitShrink := float64(imath.Max(img.Width(), img.Height())) / gifMaxDimension
  46. gifLimitShrink := math.Max(gifResLimitShrink, gifDimLimitShrink)
  47. if gifLimitShrink <= 1.0 {
  48. return nil
  49. }
  50. scale := math.Sqrt(1.0 / gifLimitShrink)
  51. if err := img.Resize(scale, scale); err != nil {
  52. return err
  53. }
  54. log.Warningf("GIF resolution is limited to %d and dimension size is limited to %d. The image is rescaled to %dx%d", int(gifMaxResolution), int(gifMaxDimension), img.Width(), img.Height())
  55. return nil
  56. }
  57. func fixIcoSize(img *vips.Image) error {
  58. icoLimitShrink := float64(imath.Max(img.Width(), img.Height())) / icoMaxDimension
  59. if icoLimitShrink <= 1.0 {
  60. return nil
  61. }
  62. scale := 1.0 / icoLimitShrink
  63. if err := img.Resize(scale, scale); err != nil {
  64. return err
  65. }
  66. log.Warningf("ICO dimension size is limited to %d. The image is rescaled to %dx%d", int(icoMaxDimension), img.Width(), img.Height())
  67. return nil
  68. }
  69. func fixSize(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptions, imgdata *imagedata.ImageData) error {
  70. switch po.Format {
  71. case imagetype.WEBP:
  72. return fixWebpSize(img)
  73. case imagetype.AVIF, imagetype.HEIC:
  74. return fixHeifSize(img)
  75. case imagetype.GIF:
  76. return fixGifSize(img)
  77. case imagetype.ICO:
  78. return fixIcoSize(img)
  79. }
  80. return nil
  81. }