1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-02-07 11:36:25 +02:00

Fix sizes of GIF and ICO before save

This commit is contained in:
DarthSim 2022-07-18 18:49:40 +06:00
parent f368ed13e9
commit 97e15c717d
6 changed files with 110 additions and 36 deletions

87
processing/fix_size.go Normal file
View File

@ -0,0 +1,87 @@
package processing
import (
"math"
"github.com/imgproxy/imgproxy/v3/imagedata"
"github.com/imgproxy/imgproxy/v3/imagetype"
"github.com/imgproxy/imgproxy/v3/imath"
"github.com/imgproxy/imgproxy/v3/options"
"github.com/imgproxy/imgproxy/v3/vips"
log "github.com/sirupsen/logrus"
)
const (
// https://chromium.googlesource.com/webm/libwebp/+/refs/heads/master/src/webp/encode.h#529
webpMaxDimension = 16383.0
gifMaxDimension = 65535.0
icoMaxDimension = 256.0
)
func fixWebpSize(img *vips.Image) error {
webpLimitShrink := float64(imath.Max(img.Width(), img.Height())) / webpMaxDimension
if webpLimitShrink <= 1.0 {
return nil
}
scale := 1.0 / webpLimitShrink
if err := img.Resize(scale, scale); err != nil {
return err
}
log.Warningf("WebP dimension size is limited to %d. The image is rescaled to %dx%d", int(webpMaxDimension), img.Width(), img.Height())
return img.CopyMemory()
}
func fixGifSize(img *vips.Image) error {
gifMaxResolution := float64(vips.GifResolutionLimit())
gifResLimitShrink := float64(img.Width()*img.Height()) / gifMaxResolution
gifDimLimitShrink := float64(imath.Max(img.Width(), img.Height())) / gifMaxDimension
gifLimitShrink := math.Max(gifResLimitShrink, gifDimLimitShrink)
if gifLimitShrink <= 1.0 {
return nil
}
scale := math.Sqrt(1.0 / gifLimitShrink)
if err := img.Resize(scale, scale); err != nil {
return err
}
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())
return img.CopyMemory()
}
func fixIcoSize(img *vips.Image) error {
icoLimitShrink := float64(imath.Max(img.Width(), img.Height())) / icoMaxDimension
if icoLimitShrink <= 1.0 {
return nil
}
scale := 1.0 / icoLimitShrink
if err := img.Resize(scale, scale); err != nil {
return err
}
log.Warningf("ICO dimension size is limited to %d. The image is rescaled to %dx%d", int(icoMaxDimension), img.Width(), img.Height())
return img.CopyMemory()
}
func fixSize(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptions, imgdata *imagedata.ImageData) error {
switch po.Format {
case imagetype.WEBP:
return fixWebpSize(img)
case imagetype.GIF:
return fixGifSize(img)
case imagetype.ICO:
return fixIcoSize(img)
}
return nil
}

View File

@ -1,33 +0,0 @@
package processing
import (
"github.com/imgproxy/imgproxy/v3/imagedata"
"github.com/imgproxy/imgproxy/v3/imagetype"
"github.com/imgproxy/imgproxy/v3/imath"
"github.com/imgproxy/imgproxy/v3/options"
"github.com/imgproxy/imgproxy/v3/vips"
log "github.com/sirupsen/logrus"
)
// https://chromium.googlesource.com/webm/libwebp/+/refs/heads/master/src/webp/encode.h#529
const webpMaxDimension = 16383.0
func fixWebpSize(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptions, imgdata *imagedata.ImageData) error {
if po.Format != imagetype.WEBP {
return nil
}
webpLimitShrink := float64(imath.Max(img.Width(), img.Height())) / webpMaxDimension
if webpLimitShrink <= 1.0 {
return nil
}
scale := 1.0 / webpLimitShrink
if err := img.Resize(scale, scale); err != nil {
return err
}
log.Warningf("WebP dimension size is limited to %d. The image is rescaled to %dx%d", int(webpMaxDimension), img.Width(), img.Height())
return img.CopyMemory()
}

View File

@ -27,10 +27,10 @@ var mainPipeline = pipeline{
scale,
rotateAndFlip,
cropToResult,
fixWebpSize,
applyFilters,
extend,
padding,
fixSize,
flatten,
watermark,
exportColorProfile,

View File

@ -12,6 +12,9 @@
#define VIPS_SUPPORT_GIFSAVE \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 12))
#define VIPS_GIF_RESOLUTION_LIMITED \
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION <= 12)
int
vips_initialize() {
return vips_init("imgproxy");
@ -33,6 +36,16 @@ swap_and_clear(VipsImage **in, VipsImage *out) {
*in = out;
}
int
gif_resolution_limit() {
#if VIPS_GIF_RESOLUTION_LIMITED
// https://github.com/libvips/libvips/blob/v8.12.2/libvips/foreign/cgifsave.c#L437-L442
return 2000 * 2000;
#else
return INT_MAX / 4;
#endif
}
int
vips_jpegload_go(void *buf, size_t len, int shrink, VipsImage **out) {
if (shrink > 1)

View File

@ -31,6 +31,8 @@ type Image struct {
var (
typeSupportLoad sync.Map
typeSupportSave sync.Map
gifResolutionLimit int
)
var vipsConf struct {
@ -69,6 +71,8 @@ func Init() error {
C.vips_cache_set_trace(C.gboolean(1))
}
gifResolutionLimit = int(C.gif_resolution_limit())
vipsConf.JpegProgressive = gbool(config.JpegProgressive)
vipsConf.PngInterlaced = gbool(config.PngInterlaced)
vipsConf.PngQuantize = gbool(config.PngQuantize)
@ -183,6 +187,10 @@ func SupportsSave(it imagetype.Type) bool {
return sup
}
func GifResolutionLimit() int {
return gifResolutionLimit
}
func gbool(b bool) C.gboolean {
if b {
return C.gboolean(1)

View File

@ -11,8 +11,7 @@ void g_free_go(void **buf);
void swap_and_clear(VipsImage **in, VipsImage *out);
int vips_type_find_load_go(int imgtype);
int vips_type_find_save_go(int imgtype);
int gif_resolution_limit();
int vips_jpegload_go(void *buf, size_t len, int shrink, VipsImage **out);
int vips_pngload_go(void *buf, size_t len, VipsImage **out);