1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-11-27 22:48:53 +02:00

Use heic/avif embedded thumbnails

This commit is contained in:
DarthSim
2022-04-14 21:41:00 +06:00
parent d1679b0046
commit 9b146991c5
6 changed files with 81 additions and 17 deletions

View File

@@ -1,9 +1,12 @@
# Changelog # Changelog
## [Unreleased] ## [Unreleased]
## Add ### Add
- Add support of RLE-encoded BMP. - Add support of RLE-encoded BMP.
### Change
- Use thumbnail embedded to HEIC/AVIF if its size is larger than or equal to the requested.
## [3.4.0] - 2022-04-07 ## [3.4.0] - 2022-04-07
### Add ### Add
- Add `IMGPROXY_FALLBACK_IMAGE_TTL` config. - Add `IMGPROXY_FALLBACK_IMAGE_TTL` config.

View File

@@ -130,3 +130,7 @@ func (it Type) SupportsColourProfile() bool {
it == WEBP || it == WEBP ||
it == AVIF it == AVIF
} }
func (it Type) SupportsThumbnail() bool {
return it == HEIC || it == AVIF
}

View File

@@ -11,8 +11,12 @@ import (
"github.com/imgproxy/imgproxy/v3/vips" "github.com/imgproxy/imgproxy/v3/vips"
) )
func canScaleOnLoad(imgtype imagetype.Type, scale float64) bool { func canScaleOnLoad(pctx *pipelineContext, imgdata *imagedata.ImageData, scale float64) bool {
if imgtype == imagetype.SVG { if imgdata == nil || pctx.trimmed || scale == 1 {
return false
}
if imgdata.Type == imagetype.SVG {
return true return true
} }
@@ -20,7 +24,10 @@ func canScaleOnLoad(imgtype imagetype.Type, scale float64) bool {
return false return false
} }
return imgtype == imagetype.JPEG || imgtype == imagetype.WEBP return imgdata.Type == imagetype.JPEG ||
imgdata.Type == imagetype.WEBP ||
imgdata.Type == imagetype.HEIC ||
imgdata.Type == imagetype.AVIF
} }
func calcJpegShink(scale float64, imgtype imagetype.Type) int { func calcJpegShink(scale float64, imgtype imagetype.Type) int {
@@ -41,10 +48,31 @@ func calcJpegShink(scale float64, imgtype imagetype.Type) int {
func scaleOnLoad(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptions, imgdata *imagedata.ImageData) error { func scaleOnLoad(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptions, imgdata *imagedata.ImageData) error {
prescale := math.Max(pctx.wscale, pctx.hscale) prescale := math.Max(pctx.wscale, pctx.hscale)
if pctx.trimmed || prescale == 1 || imgdata == nil || !canScaleOnLoad(pctx.imgtype, prescale) { if !canScaleOnLoad(pctx, imgdata, prescale) {
return nil return nil
} }
var newWidth, newHeight int
if imgdata.Type.SupportsThumbnail() {
thumbnail := new(vips.Image)
defer thumbnail.Clear()
if err := thumbnail.LoadThumbnail(imgdata); err != nil {
return err
}
angle, flip := 0, false
newWidth, newHeight, angle, flip = extractMeta(thumbnail, po.Rotate, po.AutoRotate)
if newWidth >= pctx.srcWidth || float64(newWidth)/float64(pctx.srcWidth) < prescale {
return nil
}
img.Swap(thumbnail)
pctx.angle = angle
pctx.flip = flip
} else {
jpegShrink := calcJpegShink(prescale, pctx.imgtype) jpegShrink := calcJpegShink(prescale, pctx.imgtype)
if pctx.imgtype == imagetype.JPEG && jpegShrink == 1 { if pctx.imgtype == imagetype.JPEG && jpegShrink == 1 {
@@ -55,9 +83,10 @@ func scaleOnLoad(pctx *pipelineContext, img *vips.Image, po *options.ProcessingO
return err return err
} }
// Update scales after scale-on-load newWidth, newHeight, _, _ = extractMeta(img, po.Rotate, po.AutoRotate)
newWidth, newHeight, _, _ := extractMeta(img, po.Rotate, po.AutoRotate) }
// Update scales after scale-on-load
wpreshrink := float64(pctx.srcWidth) / float64(newWidth) wpreshrink := float64(pctx.srcWidth) / float64(newWidth)
hpreshrink := float64(pctx.srcHeight) / float64(newHeight) hpreshrink := float64(pctx.srcHeight) / float64(newHeight)

View File

@@ -82,8 +82,13 @@ vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out) {
} }
int int
vips_heifload_go(void *buf, size_t len, VipsImage **out) { vips_heifload_go(void *buf, size_t len, VipsImage **out, int thumbnail) {
return vips_heifload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL); return vips_heifload_buffer(
buf, len, out,
"access", VIPS_ACCESS_SEQUENTIAL,
"thumbnail", thumbnail,
NULL
);
} }
int int

View File

@@ -229,7 +229,7 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64,
case imagetype.SVG: case imagetype.SVG:
err = C.vips_svgload_go(data, dataSize, C.double(scale), &tmp) err = C.vips_svgload_go(data, dataSize, C.double(scale), &tmp)
case imagetype.HEIC, imagetype.AVIF: case imagetype.HEIC, imagetype.AVIF:
err = C.vips_heifload_go(data, dataSize, &tmp) err = C.vips_heifload_go(data, dataSize, &tmp, C.int(0))
case imagetype.TIFF: case imagetype.TIFF:
err = C.vips_tiffload_go(data, dataSize, &tmp) err = C.vips_tiffload_go(data, dataSize, &tmp)
default: default:
@@ -244,6 +244,25 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64,
return nil return nil
} }
func (img *Image) LoadThumbnail(imgdata *imagedata.ImageData) error {
if imgdata.Type != imagetype.HEIC && imgdata.Type != imagetype.AVIF {
return errors.New("Usupported image type to load thumbnail")
}
var tmp *C.VipsImage
data := unsafe.Pointer(&imgdata.Data[0])
dataSize := C.size_t(len(imgdata.Data))
if err := C.vips_heifload_go(data, dataSize, &tmp, C.int(1)); err != 0 {
return Error()
}
C.swap_and_clear(&img.VipsImage, tmp)
return nil
}
func (img *Image) Save(imgtype imagetype.Type, quality int) (*imagedata.ImageData, error) { func (img *Image) Save(imgtype imagetype.Type, quality int) (*imagedata.ImageData, error) {
if imgtype == imagetype.ICO { if imgtype == imagetype.ICO {
return img.saveAsIco() return img.saveAsIco()
@@ -314,6 +333,10 @@ func (img *Image) Arrayjoin(in []*Image) error {
return nil return nil
} }
func (img *Image) Swap(in *Image) {
img.VipsImage, in.VipsImage = in.VipsImage, img.VipsImage
}
func (img *Image) IsAnimated() bool { func (img *Image) IsAnimated() bool {
return C.vips_is_animated(img.VipsImage) > 0 return C.vips_is_animated(img.VipsImage) > 0
} }

View File

@@ -19,7 +19,7 @@ int vips_pngload_go(void *buf, size_t len, VipsImage **out);
int vips_webpload_go(void *buf, size_t len, double scale, int pages, VipsImage **out); int vips_webpload_go(void *buf, size_t len, double scale, int pages, 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);
int vips_heifload_go(void *buf, size_t len, VipsImage **out); int vips_heifload_go(void *buf, size_t len, VipsImage **out, int thumbnail);
int vips_tiffload_go(void *buf, size_t len, VipsImage **out); int vips_tiffload_go(void *buf, size_t len, VipsImage **out);
int vips_black_go(VipsImage **out, int width, int height, int bands); int vips_black_go(VipsImage **out, int width, int height, int bands);