1
0

fix_size.go 2.6 KB

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