fix_size.go 2.7 KB

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