From 2d8f5a52f76f9bff318e061f73dd931c012cf940 Mon Sep 17 00:00:00 2001 From: Sorunome <mail@sorunome.de> Date: Wed, 3 Jun 2020 20:46:08 +0200 Subject: [PATCH] better handle frames --- .../thumbnail_resource_handler.go | 37 ++++++------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/controllers/thumbnail_controller/thumbnail_resource_handler.go b/controllers/thumbnail_controller/thumbnail_resource_handler.go index 521afb65..11ed6f88 100644 --- a/controllers/thumbnail_controller/thumbnail_resource_handler.go +++ b/controllers/thumbnail_controller/thumbnail_resource_handler.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "image" - "image/color" "image/draw" "image/gif" "io" @@ -240,23 +239,29 @@ func GenerateThumbnail(media *types.Media, width int, height int, method string, // Prepare a blank frame to use as swap space frameImg := image.NewRGBA(image.Rectangle{image.Point{0, 0}, image.Point{g.Config.Width, g.Config.Height}}) - // make sure the image is transparent at the start - draw.Draw(frameImg, frameImg.Bounds(), image.Transparent, image.ZP, draw.Src) for i := range g.Image { img := g.Image[i] var disposal byte if g.Disposal == nil { - // go 1.14 disposal = 0 } else { disposal = g.Disposal[i] } - var previousImg draw.Image + // if disposal type is 1 (preserve previous frame) we can get artifacts from re-scaling + // as such, we re-render those frames to disposal type 0 (start with a transparent frame) + // see https://www.w3.org/Graphics/GIF/spec-gif89a.txt + if disposal == 1 { + g.Disposal[i] = 0 + } else { + draw.Draw(frameImg, frameImg.Bounds(), image.Transparent, image.ZP, draw.Src) + } + + var previousFrameImg draw.Image if disposal == 3 { - previousImg = image.NewRGBA(g.Image[0].Bounds()) - draw.Draw(previousImg, frameImg.Bounds(), frameImg, image.ZP, draw.Over) + previousFrameImg = image.NewRGBA(frameImg.Bounds()) + draw.Draw(previousFrameImg, frameImg.Bounds(), frameImg, image.ZP, draw.Over) } // Copy the frame to a new image and use that @@ -274,24 +279,6 @@ func GenerateThumbnail(media *types.Media, width int, height int, method string, targetImg := image.NewPaletted(frameThumb.Bounds(), img.Palette) draw.FloydSteinberg.Draw(targetImg, frameThumb.Bounds(), frameThumb, image.ZP) g.Image[i] = targetImg - - // determine how to dispose the frame - // see https://www.w3.org/Graphics/GIF/spec-gif89a.txt - if disposal == 0 { - // Clear the transparency of the previous frame - draw.Draw(frameImg, frameImg.Bounds(), image.Transparent, image.ZP, draw.Src) - } else if disposal == 1 { - // do nothing - } else if disposal == 2 && g.Config.ColorModel != nil { - // restore background color - background := g.Config.ColorModel.(color.Palette)[g.BackgroundIndex] - if background != nil { - draw.Draw(frameImg, frameImg.Bounds(), image.NewUniform(background), image.ZP, draw.Src) - } - } else if disposal == 3 && previousImg != nil { - // restore previous frame - draw.Draw(frameImg, frameImg.Bounds(), previousImg, image.ZP, draw.Over) - } } // Set the image size to the first frame's size -- GitLab