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:
parent
f368ed13e9
commit
97e15c717d
87
processing/fix_size.go
Normal file
87
processing/fix_size.go
Normal 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
|
||||
}
|
@ -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()
|
||||
}
|
@ -27,10 +27,10 @@ var mainPipeline = pipeline{
|
||||
scale,
|
||||
rotateAndFlip,
|
||||
cropToResult,
|
||||
fixWebpSize,
|
||||
applyFilters,
|
||||
extend,
|
||||
padding,
|
||||
fixSize,
|
||||
flatten,
|
||||
watermark,
|
||||
exportColorProfile,
|
||||
|
13
vips/vips.c
13
vips/vips.c
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user