]> Cypherpunks repositories - gostls13.git/commitdiff
image/gif: expose disposal, bg index and Config
authorColin Kennedy <moshen.colin@gmail.com>
Wed, 11 Feb 2015 22:58:55 +0000 (16:58 -0600)
committerNigel Tao <nigeltao@golang.org>
Mon, 13 Apr 2015 04:35:04 +0000 (04:35 +0000)
The background index in the global palette (located in the image.Config)
is necessary for interpreting GIF frames properly

Frame disposal information is necessary for interpreting GIF frames in
the context of a sequence (or animation)

Removes decoder.flags as it can be a local variable

Change-Id: I6790a7febf6ba0859175c834c807bc6413e6b194
Reviewed-on: https://go-review.googlesource.com/4620
Reviewed-by: Nigel Tao <nigeltao@golang.org>
src/image/gif/reader.go

index 5a863e204f3066b7fc232023ee2ad0450e1a3654..b3ed0388f4f4657f8041180ac75ab1d3018c6e11 100644 (file)
@@ -34,6 +34,9 @@ const (
        // Fields.
        fColorMapFollows = 1 << 7
 
+       // Screen Descriptor flags.
+       sdGlobalColorTable = 1 << 7
+
        // Image fields.
        ifLocalColorTable = 1 << 7
        ifInterlace       = 1 << 6
@@ -41,6 +44,14 @@ const (
 
        // Graphic control flags.
        gcTransparentColorSet = 1 << 0
+       gcDisposalMethodMask  = 7 << 2
+)
+
+// Disposal Methods.
+const (
+       DisposalNone       = 0x01
+       DisposalBackground = 0x02
+       DisposalPrevious   = 0x03
 )
 
 // Section indicators.
@@ -66,11 +77,11 @@ type decoder struct {
        vers            string
        width           int
        height          int
-       flags           byte
        headerFields    byte
        backgroundIndex byte
        loopCount       int
        delayTime       int
+       disposalMethod  byte
 
        // Unused from header.
        aspect byte
@@ -87,9 +98,10 @@ type decoder struct {
        globalColorMap color.Palette
 
        // Used when decoding.
-       delay []int
-       image []*image.Paletted
-       tmp   [1024]byte // must be at least 768 so we can read color map
+       delay    []int
+       disposal []byte
+       image    []*image.Paletted
+       tmp      [1024]byte // must be at least 768 so we can read color map
 }
 
 // blockReader parses the block structure of GIF image data, which
@@ -235,6 +247,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
 
                        d.image = append(d.image, m)
                        d.delay = append(d.delay, d.delayTime)
+                       d.disposal = append(d.disposal, d.disposalMethod)
                        // The GIF89a spec, Section 23 (Graphic Control Extension) says:
                        // "The scope of this extension is the first graphic rendering block
                        // to follow." We therefore reset the GCE fields to zero.
@@ -265,7 +278,9 @@ func (d *decoder) readHeaderAndScreenDescriptor() error {
        d.width = int(d.tmp[6]) + int(d.tmp[7])<<8
        d.height = int(d.tmp[8]) + int(d.tmp[9])<<8
        d.headerFields = d.tmp[10]
-       d.backgroundIndex = d.tmp[11]
+       if d.headerFields&sdGlobalColorTable != 0 {
+               d.backgroundIndex = d.tmp[11]
+       }
        d.aspect = d.tmp[12]
        d.loopCount = -1
        d.pixelSize = uint(d.headerFields&7) + 1
@@ -346,9 +361,10 @@ func (d *decoder) readGraphicControl() error {
        if _, err := io.ReadFull(d.r, d.tmp[0:6]); err != nil {
                return fmt.Errorf("gif: can't read graphic control: %s", err)
        }
-       d.flags = d.tmp[1]
+       flags := d.tmp[1]
+       d.disposalMethod = (flags & gcDisposalMethodMask) >> 2
        d.delayTime = int(d.tmp[2]) | int(d.tmp[3])<<8
-       if d.flags&gcTransparentColorSet != 0 {
+       if flags&gcTransparentColorSet != 0 {
                d.transparentIndex = d.tmp[4]
                d.hasTransparentIndex = true
        }
@@ -428,7 +444,11 @@ func Decode(r io.Reader) (image.Image, error) {
 type GIF struct {
        Image     []*image.Paletted // The successive images.
        Delay     []int             // The successive delay times, one per frame, in 100ths of a second.
+       Disposal  []byte            // The successive disposal methods, one per frame.
        LoopCount int               // The loop count.
+       Config    image.Config
+       // The background index in the Global Color Map.
+       BackgroundIndex byte
 }
 
 // DecodeAll reads a GIF image from r and returns the sequential frames
@@ -442,6 +462,13 @@ func DecodeAll(r io.Reader) (*GIF, error) {
                Image:     d.image,
                LoopCount: d.loopCount,
                Delay:     d.delay,
+               Disposal:  d.disposal,
+               Config: image.Config{
+                       ColorModel: d.globalColorMap,
+                       Width:      d.width,
+                       Height:     d.height,
+               },
+               BackgroundIndex: d.backgroundIndex,
        }
        return gif, nil
 }