Search code examples
go

Can't use Color array as color.Palette value in argument to image.NewPaletted


I'm currently trying to create an image with a palette read from the first row of a png file that has known dimensions. I'm doing this by declaring a Color array with a known size, then setting the entries in that array individually, then passing that array into image.NewPaletted as the palette argument. I know the following works from the example in Donovan & Kernighan:

var palette = []color.Color{color.White, color.Black}
rect := image.Rect(0, 0, 200, 200)
img := image.NewPaletted(rect, palette)

...but the following does not work in my code (i have checked errors from os.Open and png.Decode but omitted this for brevity):

file, _ := os.Open("palette.png")
img, _ := png.Decode(file)

// image width is guaranteed to == paletteSize
var palette [paletteSize]color.Color
for i := range(paletteSize) {
    palette[i] = img.At(i, 0)
}

rect := image.Rect(0, 0, 200, 200)
img := image.NewPaletted(rect, palette)

Which fails with cannot use palette (variable of type [256]color.Color) as color.Palette value in argument to image.NewPaletted. Notably, the docs show that color.Palette is defined as type Palette []Color.

It feels like the two arrays should be equivalent, given that they're both obviously known size and only initialised differently, but clearly I've missed something. I have tried reducing paletteSize down to 2 and it still throws the same error, so I don't think it's a case of array size. Does anyone have an idea what I'm doing wrong?


Solution

  • [256]color.Color is an array, whereas color.Palette is defined as type Palette []Color, so is a slice. This means you are attempting to pass an array to a function that requires a slice; the error is letting you know that this is not supported.

    You have a few options; the smallest change would be to use image.NewPaletted(rect, palette[:]) (this will create a slice using the array as the underlying buffer ref). Alternatively you could just use a slice:

    func main() {
        file, _ := os.Open("palette.png")
        img, _ := png.Decode(file)
    
        paletteSize:= 256
        palette := make([]color.Color, paletteSize)
        for i := range paletteSize {
            palette[i] = img.At(i, 0)
        }
    
        rect := image.Rect(0, 0, 200, 200)
        _ = image.NewPaletted(rect, palette)
    }