From 22e16ebe5640c73d05a5d51fcdfae8529ac9ca74 Mon Sep 17 00:00:00 2001 From: DarthSim Date: Wed, 20 Dec 2023 19:34:29 +0300 Subject: [PATCH] Fix loading animated images with a huge number of frames --- CHANGELOG.md | 1 + processing/processing.go | 8 +++----- vips/vips.go | 8 ++++++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7feac003..4ebcee35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - (pro) If the `step` argument of the `video_thumbnail_tile` is negative, calculate `step` automatically. ### Fix +- Fix loading animated images with a huge number of frames. - (pro) Fix `video_thumbnail_tile` option behavior when the video has a single keyframe. - (pro) Fix the `trim` argument of the `video_thumbnail_tile` processing option. - (pro) Fix `video_thumbnail_tile` behavior when the `step` argument value is less than frame duration. diff --git a/processing/processing.go b/processing/processing.go index f800489e..97888c3d 100644 --- a/processing/processing.go +++ b/processing/processing.go @@ -102,21 +102,19 @@ func transformAnimated(ctx context.Context, img *vips.Image, po *options.Process } imgWidth := img.Width() + framesCount := imath.Min(img.Pages(), po.SecurityOptions.MaxAnimationFrames) frameHeight, err := img.GetInt("page-height") if err != nil { return err } - framesCount := imath.Min(img.Height()/frameHeight, po.SecurityOptions.MaxAnimationFrames) - // Double check dimensions because animated image has many frames if err = security.CheckDimensions(imgWidth, frameHeight, framesCount, po.SecurityOptions); err != nil { return err } - // Vips 8.8+ supports n-pages and doesn't load the whole animated image on header access - if nPages, _ := img.GetIntDefault("n-pages", 1); nPages > framesCount { + if img.Pages() > framesCount { // Load only the needed frames if err = img.Load(imgdata, 1, 1.0, framesCount); err != nil { return err @@ -197,7 +195,7 @@ func transformAnimated(ctx context.Context, img *vips.Image, po *options.Process img.SetInt("page-height", frames[0].Height()) img.SetIntSlice("delay", delay) img.SetInt("loop", loop) - img.SetInt("n-pages", framesCount) + img.SetInt("n-pages", img.Height()/frames[0].Height()) return nil } diff --git a/vips/vips.go b/vips/vips.go index 89c0d963..23ba6e3c 100644 --- a/vips/vips.go +++ b/vips/vips.go @@ -292,6 +292,14 @@ func (img *Image) Height() int { return int(img.VipsImage.Ysize) } +func (img *Image) Pages() int { + p, err := img.GetIntDefault("n-pages", 1) + if err != nil { + return 1 + } + return p +} + func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64, pages int) error { if imgdata.Type == imagetype.ICO { return img.loadIco(imgdata.Data, shrink, scale, pages)