1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2024-11-24 08:12:38 +02:00

Fix animations loops and delays

This commit is contained in:
DarthSim 2021-02-22 19:30:55 +06:00
parent 29fb55db55
commit bad20a3f02
4 changed files with 104 additions and 5 deletions

View File

@ -595,19 +595,30 @@ func transformAnimated(ctx context.Context, img *vipsImage, data []byte, po *pro
}
// Vips 8.8+ supports n-pages and doesn't load the whole animated image on header access
if nPages, _ := img.GetInt("n-pages"); nPages > framesCount {
if nPages, _ := img.GetIntDefault("n-pages", 0); nPages > framesCount {
// Load only the needed frames
if err = img.Load(data, imgtype, 1, 1.0, framesCount); err != nil {
return err
}
}
delay, err := img.GetInt("gif-delay")
delay, err := img.GetIntSliceDefault("delay", nil)
if err != nil {
return err
}
loop, err := img.GetInt("gif-loop")
loop, err := img.GetIntDefault("loop", 0)
if err != nil {
return err
}
// Legacy fields
// TODO: remove this in major update
gifLoop, err := img.GetIntDefault("gif-loop", -1)
if err != nil {
return err
}
gifDelay, err := img.GetIntDefault("gif-delay", -1)
if err != nil {
return err
}
@ -661,11 +672,29 @@ func transformAnimated(ctx context.Context, img *vipsImage, data []byte, po *pro
return err
}
if len(delay) == 0 {
delay = make([]int, framesCount)
for i := range delay {
delay[i] = 40
}
} else if len(delay) > framesCount {
delay = delay[:framesCount]
}
img.SetInt("page-height", frames[0].Height())
img.SetInt("gif-delay", delay)
img.SetInt("gif-loop", loop)
img.SetIntSlice("delay", delay)
img.SetInt("loop", loop)
img.SetInt("n-pages", framesCount)
// Legacy fields
// TODO: remove this in major update
if gifLoop >= 0 {
img.SetInt("gif-loop", gifLoop)
}
if gifDelay >= 0 {
img.SetInt("gif-delay", gifDelay)
}
return nil
}

20
vips.c
View File

@ -28,6 +28,9 @@
#define VIPS_SUPPORT_WEBP_ANIMATION \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
#define VIPS_SUPPORT_ARRAY_HEADERS \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 9))
#define VIPS_SUPPORT_HEIF \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
@ -245,6 +248,23 @@ vips_is_animated(VipsImage * in) {
vips_image_get_typeof(in, "gif-loop") != G_TYPE_INVALID );
}
int
vips_image_get_array_int_go(VipsImage *image, const char *name, int **out, int *n) {
#if VIPS_SUPPORT_ARRAY_HEADERS
return vips_image_get_array_int(image, name, out, n);
#else
vips_error("vips_image_get_array_int_go", "Array headers are not supported (libvips 8.9+ reuired)");
return 1;
#endif
}
void
vips_image_set_array_int_go(VipsImage *image, const char *name, const int *array, int n) {
#if VIPS_SUPPORT_ARRAY_HEADERS
vips_image_set_array_int(image, name, array, n);
#endif
}
gboolean
vips_image_hasalpha_go(VipsImage * in) {
#if VIPS_SUPPORT_HASALPHA

47
vips.go
View File

@ -13,6 +13,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"math"
"os"
"runtime"
"unsafe"
@ -330,10 +331,56 @@ func (img *vipsImage) GetInt(name string) (int, error) {
return int(i), nil
}
func (img *vipsImage) GetIntDefault(name string, def int) (int, error) {
if C.vips_image_get_typeof(img.VipsImage, cachedCString(name)) == 0 {
return def, nil
}
return img.GetInt(name)
}
func (img *vipsImage) GetIntSlice(name string) ([]int, error) {
var ptr unsafe.Pointer
size := C.int(0)
if C.vips_image_get_array_int_go(img.VipsImage, cachedCString(name), (**C.int)(unsafe.Pointer(&ptr)), &size) != 0 {
return nil, vipsError()
}
if size == 0 {
return []int{}, nil
}
cOut := (*[math.MaxInt32]C.int)(ptr)[:int(size):int(size)]
out := make([]int, int(size))
for i, el := range cOut {
out[i] = int(el)
}
return out, nil
}
func (img *vipsImage) GetIntSliceDefault(name string, def []int) ([]int, error) {
if C.vips_image_get_typeof(img.VipsImage, cachedCString(name)) == 0 {
return def, nil
}
return img.GetIntSlice(name)
}
func (img *vipsImage) SetInt(name string, value int) {
C.vips_image_set_int(img.VipsImage, cachedCString(name), C.int(value))
}
func (img *vipsImage) SetIntSlice(name string, value []int) {
in := make([]C.int, len(value))
for i, el := range value {
in[i] = C.int(el)
}
C.vips_image_set_array_int_go(img.VipsImage, cachedCString(name), &in[0], C.int(len(value)))
}
func (img *vipsImage) CastUchar() error {
var tmp *C.VipsImage

3
vips.h
View File

@ -47,6 +47,9 @@ VipsBandFormat vips_band_format(VipsImage *in);
gboolean vips_support_webp_animation();
gboolean vips_is_animated(VipsImage * in);
int vips_image_get_array_int_go(VipsImage *image, const char *name, int **out, int *n);
void vips_image_set_array_int_go(VipsImage *image, const char *name, const int *array, int n);
gboolean vips_image_hasalpha_go(VipsImage * in);
int vips_addalpha_go(VipsImage *in, VipsImage **out);