1
0
mirror of https://github.com/golang/go synced 2024-11-18 22:24:50 -07:00

image/gif: expose disposal, bg index and Config

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>
This commit is contained in:
Colin Kennedy 2015-02-11 16:58:55 -06:00 committed by Nigel Tao
parent 926616da3f
commit e6092d64a7

View File

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