1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2024-11-24 08:12:38 +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
## [Unreleased]
## Add
### Add
- 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
### Add
- Add `IMGPROXY_FALLBACK_IMAGE_TTL` config.

View File

@ -130,3 +130,7 @@ func (it Type) SupportsColourProfile() bool {
it == WEBP ||
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"
)
func canScaleOnLoad(imgtype imagetype.Type, scale float64) bool {
if imgtype == imagetype.SVG {
func canScaleOnLoad(pctx *pipelineContext, imgdata *imagedata.ImageData, scale float64) bool {
if imgdata == nil || pctx.trimmed || scale == 1 {
return false
}
if imgdata.Type == imagetype.SVG {
return true
}
@ -20,7 +24,10 @@ func canScaleOnLoad(imgtype imagetype.Type, scale float64) bool {
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 {
@ -41,23 +48,45 @@ func calcJpegShink(scale float64, imgtype imagetype.Type) int {
func scaleOnLoad(pctx *pipelineContext, img *vips.Image, po *options.ProcessingOptions, imgdata *imagedata.ImageData) error {
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
}
jpegShrink := calcJpegShink(prescale, pctx.imgtype)
var newWidth, newHeight int
if pctx.imgtype == imagetype.JPEG && jpegShrink == 1 {
return nil
}
if imgdata.Type.SupportsThumbnail() {
thumbnail := new(vips.Image)
defer thumbnail.Clear()
if err := img.Load(imgdata, jpegShrink, prescale, 1); err != nil {
return err
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)
if pctx.imgtype == imagetype.JPEG && jpegShrink == 1 {
return nil
}
if err := img.Load(imgdata, jpegShrink, prescale, 1); err != nil {
return err
}
newWidth, newHeight, _, _ = extractMeta(img, po.Rotate, po.AutoRotate)
}
// Update scales after scale-on-load
newWidth, newHeight, _, _ := extractMeta(img, po.Rotate, po.AutoRotate)
wpreshrink := float64(pctx.srcWidth) / float64(newWidth)
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
vips_heifload_go(void *buf, size_t len, VipsImage **out) {
return vips_heifload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
vips_heifload_go(void *buf, size_t len, VipsImage **out, int thumbnail) {
return vips_heifload_buffer(
buf, len, out,
"access", VIPS_ACCESS_SEQUENTIAL,
"thumbnail", thumbnail,
NULL
);
}
int

View File

@ -229,7 +229,7 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64,
case imagetype.SVG:
err = C.vips_svgload_go(data, dataSize, C.double(scale), &tmp)
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:
err = C.vips_tiffload_go(data, dataSize, &tmp)
default:
@ -244,6 +244,25 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64,
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) {
if imgtype == imagetype.ICO {
return img.saveAsIco()
@ -314,6 +333,10 @@ func (img *Image) Arrayjoin(in []*Image) error {
return nil
}
func (img *Image) Swap(in *Image) {
img.VipsImage, in.VipsImage = in.VipsImage, img.VipsImage
}
func (img *Image) IsAnimated() bool {
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_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_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_black_go(VipsImage **out, int width, int height, int bands);