Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

image/gif: last color in per-image Palette is different from global Palette #13724

Closed
pierrre opened this issue Dec 24, 2015 · 2 comments
Closed

Comments

@pierrre
Copy link

pierrre commented Dec 24, 2015

Go version: 1.5.2 & 1.6beta1

I tried to decode an animated GIF image. (https://raw.githubusercontent.com/pierrre/imageserver/master/testdata/animated.gif)
I get a GIF with a Palette ColorModel, and a slice of Paletted images.
If I compare the global palette, with the palette of each frame, the last color is different.

I wrote a small program:

package main

import (
    "bytes"
    "fmt"
    "image/color"
    "image/gif"
    "io/ioutil"
)

func main() {
    b, err := ioutil.ReadFile("/home/pierre/Go/src/github.com/pierrre/imageserver/testdata/animated.gif")
    if err != nil {
        panic(err)
    }
    g, err := gif.DecodeAll(bytes.NewReader(b))
    if err != nil {
        panic(err)
    }
    if g.Config.ColorModel == nil {
        fmt.Println("no global color model")
        return
    }
    pa, ok := g.Config.ColorModel.(color.Palette)
    if !ok {
        fmt.Println("global color model is not a Palette")
        return
    }
    if len(pa) == 0 {
        fmt.Println("global palette is empty")
        return
    }
    for i, p := range g.Image {
        if len(p.Palette) != len(pa) {
            fmt.Printf("image %d: palette length is not equal: current=%d, global=%d\n", i, len(p.Palette), len(pa))
            continue
        }
        for j := range p.Palette {
            if p.Palette[j] != pa[j] {
                fmt.Printf("image %d: palette index %d: color is not equal: current=%#v, global=%#v\n", i, j, p.Palette[j], pa[j])
            }
        }
    }
    fmt.Printf("background index: %d\n", g.BackgroundIndex)
}

I get:

image 0: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 1: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 2: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 3: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 4: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 5: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 6: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 7: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 8: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 9: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 10: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 11: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 12: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 13: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 14: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 15: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 16: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 17: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 18: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 19: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 20: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 21: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 22: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 23: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 24: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 25: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 26: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 27: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 28: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 29: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 30: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 31: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 32: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 33: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 34: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
image 35: palette index 255: color is not equal: current=color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, global=color.RGBA{R:0xff, G:0xff, B:0xff, A:0xff}
background index: 255

At index 255, the color is transparent in all frames, and white in the global palette.

If the ColorModel is defined in GIF, and it's a non empty Palette, I expect to have the same Palette in all frames.

Is it related to the background color index?

Thank you.

@rsc rsc changed the title image/gif.GIF: last color in Palette is different image/gif: last color in per-image Palette is different from global Palette Dec 28, 2015
@rsc
Copy link
Contributor

rsc commented Dec 28, 2015

Yes, that's probably why. The background color index says that that color is "transparent", meaning R=G=B=A=0. White would be R=G=B=A=0xFF, and black would be R=G=B=0, A=0xFF. So the global palette says white, but the per-image palette correctly says transparent. But I still don't understand why the global palette doesn't report transparent too.

/cc @nigeltao @robpike

@rsc rsc added this to the Unplanned milestone Dec 28, 2015
@nigeltao
Copy link
Contributor

It's to do with the Transparent Color Index values, not the Background Color Index value. As per the https://www.w3.org/Graphics/GIF/spec-gif89a.txt spec:

Background Color Index (a property of the Global Color Table) is defined in section 18.

Transparent Color Index (a property of a Local Color Table) is defined in section 23. Transparency is important when composing successive frames, using the "Do not dispose" disposal method, but a limitation of the GIF format is that none of the Global Color Table's entries can be transparent.

Note that, even without a Transparent Color Index set, a frame of an animated GIF can have a different ColorModel (i.e. palette) than the overall global ColorModel. See section 21 re Local Color Tables.

@golang golang locked and limited conversation to collaborators Mar 20, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants