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
}
func calcShink(scale float64, imgtype imageType) int {
switch imgtype {
case imageTypeWEBP:
return int(1.0 / scale)
case imageTypeJPEG:
shrink := int(1.0 / scale)
func canScaleOnLoad(imgtype imageType, scale float64) bool {
if imgtype == imageTypeSVG {
return true
}
switch {
case shrink >= 8:
return 8
case shrink >= 4:
return 4
case shrink >= 2:
return 2
}
if conf.DisableShrinkOnLoad || scale >= 1 {
return false
}
return imgtype == imageTypeJPEG || imgtype == imageTypeWEBP
}
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
@ -292,28 +299,28 @@ func transformImage(ctx context.Context, img **C.VipsImage, data []byte, po *pro
scale := calcScale(imgWidth, imgHeight, po, imgtype)
if scale != 1 && data != nil {
if imgtype == imageTypeSVG {
// Load SVG with desired scale
if scale != 1 && data != nil && canScaleOnLoad(imgtype, scale) {
if imgtype == imageTypeWEBP || imgtype == imageTypeSVG {
// Do some scale-on-load
if tmp, err := vipsLoadImage(data, imgtype, 1, scale, false); err == nil {
C.swap_and_clear(img, tmp)
} else {
return err
}
scale = 1
} else if !conf.DisableShrinkOnLoad && scale < 1.0 {
} else if imgtype == imageTypeJPEG {
// 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 {
C.swap_and_clear(img, tmp)
} else {
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 {
@ -628,7 +635,7 @@ func vipsPrepareWatermark() error {
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
err := C.int(0)
@ -639,7 +646,7 @@ func vipsLoadImage(data []byte, imgtype imageType, shrink int, svgScale float64,
case imageTypePNG:
err = C.vips_pngload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), &img)
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:
pages := C.int(1)
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)
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:
rawData, width, height, icoErr := icoData(data)
if icoErr != nil {

18
vips.c
View File

@ -19,6 +19,9 @@
#define VIPS_SUPPORT_PNG_QUANTIZATION \
(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 \
(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
vips_webpload_go(void *buf, size_t len, int shrink, VipsImage **out) {
if (shrink > 1)
return vips_webpload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, "shrink", shrink, NULL);
vips_webpload_go(void *buf, size_t len, double scale, VipsImage **out) {
if (scale < 1)
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);
}

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_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_svgload_go(void *buf, size_t len, double scale, VipsImage **out);