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:
parent
29fb55db55
commit
bad20a3f02
39
process.go
39
process.go
@ -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
20
vips.c
@ -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
47
vips.go
@ -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
3
vips.h
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user