I am trying to apply hue and saturation effects to all frames of a gif using this library.
The adjust.Hue()
and adjust.Saturation()
functions accept an *image.RGBA
, so I am converting the *image.Paletted
gif frames to *image.RGBA
, applying the filters, and then converting them back to *image.Paletted
.
The filters appear to be working, however the frames are distorted.
Input:
Output:
Here is my code:
package mainimport ("image""image/color""image/draw""image/gif""log""os""github.com/anthonynsimon/bild/adjust")type ImageData struct { Hue int Saturation float64}func ProcessGif(inputPath string, outputPath string, imageData ImageData) error { file, err := os.Open(inputPath) if err != nil { return err } defer file.Close() gifImage, err := gif.DecodeAll(file) if err != nil { return err } // Process each frame for i, img := range gifImage.Image { // Convert *image.Paletted to *image.RGBA rgba := PalettedToRGBA(img) // Apply adjustments rgba = adjust.Hue(rgba, imageData.Hue) rgba = adjust.Saturation(rgba, imageData.Saturation) // Convert *image.RGBA to *image.Paletted gifImage.Image[i] = RGBAToPaletted(rgba) } outputFile, err := os.Create(outputPath) if err != nil { return err } defer outputFile.Close() return gif.EncodeAll(outputFile, gifImage)}func PalettedToRGBA(paletted *image.Paletted) *image.RGBA { bounds := paletted.Bounds() rgba := image.NewRGBA(bounds) draw.Draw(rgba, bounds, paletted, image.Point{}, draw.Over) return rgba}func RGBAToPaletted(rgba *image.RGBA) *image.Paletted { bounds := rgba.Bounds() // Extract the unique colors from the RGBA image palette := color.Palette{} for y := bounds.Min.Y; y < bounds.Max.Y; y++ { for x := bounds.Min.X; x < bounds.Max.X; x++ { c := rgba.At(x, y) if !sliceIncludes(palette, c) { palette = append(palette, c) } } } // Create the Paletted image with the constructed palette paletted := image.NewPaletted(bounds, palette) draw.Draw(paletted, bounds, rgba, image.Point{}, draw.Over) return paletted}func sliceIncludes[T comparable](slice []T, t T) bool { for _, c := range slice { if c == t { return true } } return false}func main() { imgData := ImageData{ Hue: 80, Saturation: 0.4, } log.Fatal(ProcessGif("image.gif", "output.gif", imgData))}
What might the issue be?