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 main
import (
"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?
1