You've already forked imgproxy
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:
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
25
vips/vips.go
25
vips/vips.go
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user