Fix loading animated images with a huge number of frames

This commit is contained in:
DarthSim
2023-12-20 19:34:29 +03:00
parent 9e5abde24e
commit 22e16ebe56
3 changed files with 12 additions and 5 deletions

View File

@@ -14,6 +14,7 @@
- (pro) If the `step` argument of the `video_thumbnail_tile` is negative, calculate `step` automatically. - (pro) If the `step` argument of the `video_thumbnail_tile` is negative, calculate `step` automatically.
### Fix ### 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 `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 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. - (pro) Fix `video_thumbnail_tile` behavior when the `step` argument value is less than frame duration.

View File

@@ -102,21 +102,19 @@ func transformAnimated(ctx context.Context, img *vips.Image, po *options.Process
} }
imgWidth := img.Width() imgWidth := img.Width()
framesCount := imath.Min(img.Pages(), po.SecurityOptions.MaxAnimationFrames)
frameHeight, err := img.GetInt("page-height") frameHeight, err := img.GetInt("page-height")
if err != nil { if err != nil {
return err return err
} }
framesCount := imath.Min(img.Height()/frameHeight, po.SecurityOptions.MaxAnimationFrames)
// Double check dimensions because animated image has many frames // Double check dimensions because animated image has many frames
if err = security.CheckDimensions(imgWidth, frameHeight, framesCount, po.SecurityOptions); err != nil { if err = security.CheckDimensions(imgWidth, frameHeight, framesCount, po.SecurityOptions); err != nil {
return err return err
} }
// Vips 8.8+ supports n-pages and doesn't load the whole animated image on header access if img.Pages() > framesCount {
if nPages, _ := img.GetIntDefault("n-pages", 1); nPages > framesCount {
// Load only the needed frames // Load only the needed frames
if err = img.Load(imgdata, 1, 1.0, framesCount); err != nil { if err = img.Load(imgdata, 1, 1.0, framesCount); err != nil {
return err 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.SetInt("page-height", frames[0].Height())
img.SetIntSlice("delay", delay) img.SetIntSlice("delay", delay)
img.SetInt("loop", loop) img.SetInt("loop", loop)
img.SetInt("n-pages", framesCount) img.SetInt("n-pages", img.Height()/frames[0].Height())
return nil return nil
} }

View File

@@ -292,6 +292,14 @@ func (img *Image) Height() int {
return int(img.VipsImage.Ysize) 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 { func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64, pages int) error {
if imgdata.Type == imagetype.ICO { if imgdata.Type == imagetype.ICO {
return img.loadIco(imgdata.Data, shrink, scale, pages) return img.loadIco(imgdata.Data, shrink, scale, pages)