Add animated GIF support

Note that this is for GIFs only (and not Webp).

Fixes #5030
This commit is contained in:
Bjørn Erik Pedersen
2022-06-11 18:52:55 +02:00
parent 2e1c81770a
commit cf12fa6161
6 changed files with 104 additions and 26 deletions

View File

@@ -86,6 +86,10 @@ func (i *Image) EncodeTo(conf ImageConfig, img image.Image, w io.Writer) error {
return encoder.Encode(w, img)
case GIF:
if giphy, ok := img.(Giphy); ok {
g := giphy.GIF()
return gif.EncodeAll(w, g)
}
return gif.Encode(w, img, &gif.Options{
NumColors: 256,
})
@@ -252,8 +256,29 @@ func (p *ImageProcessor) ApplyFiltersFromConfig(src image.Image, conf ImageConfi
}
func (p *ImageProcessor) Filter(src image.Image, filters ...gift.Filter) (image.Image, error) {
g := gift.New(filters...)
bounds := g.Bounds(src.Bounds())
filter := gift.New(filters...)
if giph, ok := src.(Giphy); ok && len(giph.GIF().Image) > 1 {
g := giph.GIF()
var bounds image.Rectangle
firstFrame := g.Image[0]
tmp := image.NewNRGBA(firstFrame.Bounds())
for i := range g.Image {
gift.New().DrawAt(tmp, g.Image[i], g.Image[i].Bounds().Min, gift.OverOperator)
bounds = filter.Bounds(tmp.Bounds())
dst := image.NewPaletted(bounds, g.Image[i].Palette)
filter.Draw(dst, tmp)
g.Image[i] = dst
}
g.Config.Width = bounds.Dx()
g.Config.Height = bounds.Dy()
return giph, nil
}
bounds := filter.Bounds(src.Bounds())
var dst draw.Image
switch src.(type) {
case *image.RGBA:
@@ -265,7 +290,8 @@ func (p *ImageProcessor) Filter(src image.Image, filters ...gift.Filter) (image.
default:
dst = image.NewNRGBA(bounds)
}
g.Draw(dst, src)
filter.Draw(dst, src)
return dst, nil
}
@@ -376,3 +402,9 @@ type ImageSource interface {
DecodeImage() (image.Image, error)
Key() string
}
// Giphy represents a GIF Image that may be animated.
type Giphy interface {
image.Image // The first frame.
GIF() *gif.GIF // All frames.
}