diff --git a/src/pkg/image/gif/reader.go b/src/pkg/image/gif/reader.go index 98ac01cca2c..e39b7974604 100644 --- a/src/pkg/image/gif/reader.go +++ b/src/pkg/image/gif/reader.go @@ -28,7 +28,9 @@ const ( fColorMapFollows = 1 << 7 // Image fields. - ifInterlace = 1 << 6 + ifLocalColorTable = 1 << 7 + ifInterlace = 1 << 6 + ifPixelSizeMask = 7 // Graphic control flags. gcTransparentColorSet = 1 << 0 @@ -190,7 +192,9 @@ Loop: } // Undo the interlacing if necessary. - d.uninterlace(m) + if d.imageFields&ifInterlace != 0 { + uninterlace(m) + } d.image = append(d.image, m) d.delay = append(d.delay, d.delayTime) @@ -236,6 +240,9 @@ func (d *decoder) readColorMap() (image.PalettedColorModel, os.Error) { return nil, fmt.Errorf("gif: can't handle %d bits per pixel", d.pixelSize) } numColors := 1 << d.pixelSize + if d.imageFields&ifLocalColorTable != 0 { + numColors = 1 << ((d.imageFields & ifPixelSizeMask) + 1) + } numValues := 3 * numColors _, err := io.ReadFull(d.r, d.tmp[0:numValues]) if err != nil { @@ -322,15 +329,15 @@ func (d *decoder) newImageFromDescriptor() (*image.Paletted, os.Error) { if _, err := io.ReadFull(d.r, d.tmp[0:9]); err != nil { return nil, fmt.Errorf("gif: can't read image descriptor: %s", err) } - // TODO: This code (throughout) ignores the top and left values, - // and assumes (in interlacing, for example) that the images' - // widths and heights are all the same. - _ = int(d.tmp[0]) + int(d.tmp[1])<<8 // TODO: honor left value - _ = int(d.tmp[2]) + int(d.tmp[3])<<8 // TODO: honor top value + left := int(d.tmp[0]) + int(d.tmp[1])<<8 + top := int(d.tmp[2]) + int(d.tmp[3])<<8 width := int(d.tmp[4]) + int(d.tmp[5])<<8 height := int(d.tmp[6]) + int(d.tmp[7])<<8 d.imageFields = d.tmp[8] - return image.NewPaletted(width, height, nil), nil + m := image.NewPaletted(width, height, nil) + // Overwrite the rectangle to take account of left and top. + m.Rect = image.Rect(left, top, left+width, top+height) + return m, nil } func (d *decoder) readBlock() (int, os.Error) { @@ -354,13 +361,11 @@ var interlacing = []interlaceScan{ {2, 1}, // Group 4 : Every 2nd. row, starting with row 1. } -func (d *decoder) uninterlace(m *image.Paletted) { - if d.imageFields&ifInterlace == 0 { - return - } +// uninterlace rearranges the pixels in m to account for interlaced input. +func uninterlace(m *image.Paletted) { var nPix []uint8 - dx := d.width - dy := d.height + dx := m.Bounds().Dx() + dy := m.Bounds().Dy() nPix = make([]uint8, dx*dy) offset := 0 // steps through the input by sequential scan lines. for _, pass := range interlacing {