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

Better scale-on-load for WebP with libvips 8.8

This commit is contained in:
DarthSim 2019-05-30 18:58:55 +06:00
parent eb60f0567c
commit 3fb3a327a3
3 changed files with 49 additions and 30 deletions

View File

@ -230,21 +230,28 @@ func calcScale(width, height int, po *processingOptions, imgtype imageType) floa
return scale return scale
} }
func calcShink(scale float64, imgtype imageType) int { func canScaleOnLoad(imgtype imageType, scale float64) bool {
switch imgtype { if imgtype == imageTypeSVG {
case imageTypeWEBP: return true
return int(1.0 / scale) }
case imageTypeJPEG:
shrink := int(1.0 / scale)
switch { if conf.DisableShrinkOnLoad || scale >= 1 {
case shrink >= 8: return false
return 8 }
case shrink >= 4:
return 4 return imgtype == imageTypeJPEG || imgtype == imageTypeWEBP
case shrink >= 2: }
return 2
} func calcJpegShink(scale float64, imgtype imageType) int {
shrink := int(1.0 / scale)
switch {
case shrink >= 8:
return 8
case shrink >= 4:
return 4
case shrink >= 2:
return 2
} }
return 1 return 1
@ -292,28 +299,28 @@ func transformImage(ctx context.Context, img **C.VipsImage, data []byte, po *pro
scale := calcScale(imgWidth, imgHeight, po, imgtype) scale := calcScale(imgWidth, imgHeight, po, imgtype)
if scale != 1 && data != nil { if scale != 1 && data != nil && canScaleOnLoad(imgtype, scale) {
if imgtype == imageTypeSVG { if imgtype == imageTypeWEBP || imgtype == imageTypeSVG {
// Load SVG with desired scale // Do some scale-on-load
if tmp, err := vipsLoadImage(data, imgtype, 1, scale, false); err == nil { if tmp, err := vipsLoadImage(data, imgtype, 1, scale, false); err == nil {
C.swap_and_clear(img, tmp) C.swap_and_clear(img, tmp)
} else { } else {
return err return err
} }
} else if imgtype == imageTypeJPEG {
scale = 1
} else if !conf.DisableShrinkOnLoad && scale < 1.0 {
// Do some shrink-on-load // Do some shrink-on-load
if shrink := calcShink(scale, imgtype); shrink != 1 { if shrink := calcJpegShink(scale, imgtype); shrink != 1 {
if tmp, err := vipsLoadImage(data, imgtype, shrink, 1.0, false); err == nil { if tmp, err := vipsLoadImage(data, imgtype, shrink, 1.0, false); err == nil {
C.swap_and_clear(img, tmp) C.swap_and_clear(img, tmp)
} else { } else {
return err return err
} }
scale = scale * float64(shrink)
} }
} }
// Update actual image size ans scale after scale-on-load
imgWidth, imgHeight, _, _ = extractMeta(*img)
scale = calcScale(imgWidth, imgHeight, po, imgtype)
} }
if err = vipsRad2Float(img); err != nil { if err = vipsRad2Float(img); err != nil {
@ -628,7 +635,7 @@ func vipsPrepareWatermark() error {
return nil return nil
} }
func vipsLoadImage(data []byte, imgtype imageType, shrink int, svgScale float64, allPages bool) (*C.VipsImage, error) { func vipsLoadImage(data []byte, imgtype imageType, shrink int, scale float64, allPages bool) (*C.VipsImage, error) {
var img *C.VipsImage var img *C.VipsImage
err := C.int(0) err := C.int(0)
@ -639,7 +646,7 @@ func vipsLoadImage(data []byte, imgtype imageType, shrink int, svgScale float64,
case imageTypePNG: case imageTypePNG:
err = C.vips_pngload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), &img) err = C.vips_pngload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), &img)
case imageTypeWEBP: case imageTypeWEBP:
err = C.vips_webpload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.int(shrink), &img) err = C.vips_webpload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.double(scale), &img)
case imageTypeGIF: case imageTypeGIF:
pages := C.int(1) pages := C.int(1)
if allPages { if allPages {
@ -648,7 +655,7 @@ func vipsLoadImage(data []byte, imgtype imageType, shrink int, svgScale float64,
err = C.vips_gifload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), pages, &img) err = C.vips_gifload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), pages, &img)
case imageTypeSVG: case imageTypeSVG:
err = C.vips_svgload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.double(svgScale), &img) err = C.vips_svgload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.double(scale), &img)
case imageTypeICO: case imageTypeICO:
rawData, width, height, icoErr := icoData(data) rawData, width, height, icoErr := icoData(data)
if icoErr != nil { if icoErr != nil {

18
vips.c
View File

@ -19,6 +19,9 @@
#define VIPS_SUPPORT_PNG_QUANTIZATION \ #define VIPS_SUPPORT_PNG_QUANTIZATION \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 7)) (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 7))
#define VIPS_SUPPORT_WEBP_SCALE_ON_LOAD \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
#define VIPS_SUPPORT_BUILTIN_ICC \ #define VIPS_SUPPORT_BUILTIN_ICC \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8)) (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
@ -102,9 +105,18 @@ vips_pngload_go(void *buf, size_t len, VipsImage **out) {
} }
int int
vips_webpload_go(void *buf, size_t len, int shrink, VipsImage **out) { vips_webpload_go(void *buf, size_t len, double scale, VipsImage **out) {
if (shrink > 1) if (scale < 1)
return vips_webpload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, "shrink", shrink, NULL); return vips_webpload_buffer(
buf, len, out,
"access", VIPS_ACCESS_SEQUENTIAL,
#if VIPS_SUPPORT_WEBP_SCALE_ON_LOAD
"scale", scale,
#else
"shrink", (int)(1.0 / scale),
#endif
NULL
);
return vips_webpload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL); return vips_webpload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
} }

2
vips.h
View File

@ -25,7 +25,7 @@ int vips_type_find_save_go(int imgtype);
int vips_jpegload_go(void *buf, size_t len, int shrink, VipsImage **out); int vips_jpegload_go(void *buf, size_t len, int shrink, VipsImage **out);
int vips_pngload_go(void *buf, size_t len, VipsImage **out); int vips_pngload_go(void *buf, size_t len, VipsImage **out);
int vips_webpload_go(void *buf, size_t len, int shrink, VipsImage **out); int vips_webpload_go(void *buf, size_t len, double scale, VipsImage **out);
int vips_gifload_go(void *buf, size_t len, int pages, VipsImage **out); int vips_gifload_go(void *buf, size_t len, int pages, VipsImage **out);
int vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out); int vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out);