Ejemplo n.º 1
0
func makeMotionReport(dVal []int, maxVal int) *image.Paletted {
	// Make Colour Pal
	width := len(dVal)
	height := maxVal / 1000

	tempPal := color.Palette([]color.Color{
		color.RGBA{0, 0, 0, 0},
		color.RGBA{255, 255, 255, 255},
	})

	m := image.NewPaletted(image.Rect(0, 0, width, height), tempPal)

	for i, v := range dVal {
		hOff := int(v / 1000)
		if hOff >= height {
			hOff = height - 1
			fmt.Println("Height too large, corrected")
		}

		for off, y := i, 0; y <= hOff; off, y = off+width, y+1 {
			m.Pix[off] = 1
		}

	}

	return m
}
Ejemplo n.º 2
0
func convertBw(w http.ResponseWriter, req *http.Request) {
	img := imageFromURL(req.FormValue("url"))

	bw := []color.Color{color.Black, color.White}
	gr := &Converted{img, color.Palette(bw)}

	w.Header().Set("Content-Type", "image/png")
	png.Encode(w, gr)
}
Ejemplo n.º 3
0
func init() {
	cs := []color.Color{}
	for _, r := range []uint8{0x00, 0x80, 0xff} {
		for _, g := range []uint8{0x00, 0x80, 0xff} {
			for _, b := range []uint8{0x00, 0x80, 0xff} {
				cs = append(cs, color.RGBA{r, g, b, 0xff})
			}
		}
	}
	cheapPalette = color.Palette(cs)
}
Ejemplo n.º 4
0
// convertToPaletted converts the given image into a paletted one.
// Colors are converted using a naive approache. The first 256 unique colors
// are retained, and the rest are mapped to hopefully a nearby color.
func convertToPaletted(src image.Image) *image.Paletted {

	if dst, ok := src.(*image.Paletted); ok {
		return dst
	}

	bounds := src.Bounds()
	colors := uniqueColors(src)

	dst := image.NewPaletted(bounds, color.Palette(colors))
	draw.Draw(dst, bounds, src, bounds.Min, draw.Src)
	return dst
}
Ejemplo n.º 5
0
Archivo: grad.go Proyecto: Kimau/GoCam
func (cg ColourGrad) makePal(min, max float64, numCol int) color.Palette {
	pal := make([]color.Color, numCol, numCol)

	p := min
	pStep := (max - min) / float64(numCol)

	for i := range pal {
		pal[i] = cg.getColour(p)
		p += pStep
	}

	return color.Palette(pal)
}
Ejemplo n.º 6
0
func TestCopyImage(t *testing.T) {
	cases := []struct {
		In  image.Image
		Out *image.RGBA
	}{
		{
			In: &image.Paletted{
				Pix:    []uint8{0, 1, 1, 0},
				Stride: 2,
				Rect:   image.Rect(0, 0, 2, 2),
				Palette: color.Palette([]color.Color{
					color.Transparent, color.White,
				}),
			},
			Out: &image.RGBA{
				Pix:    []uint8{0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0},
				Stride: 8,
				Rect:   image.Rect(0, 0, 2, 2),
			},
		},
		{
			In: &image.RGBA{
				Pix:    []uint8{0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0},
				Stride: 8,
				Rect:   image.Rect(0, 0, 2, 2),
			},
			Out: &image.RGBA{
				Pix:    []uint8{0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0},
				Stride: 8,
				Rect:   image.Rect(0, 0, 2, 2),
			},
		},
	}
	for _, c := range cases {
		got := CopyImage(c.In)
		if got.Rect != c.Out.Rect {
			t.Errorf("Rect: %v, want: %v", got.Rect, c.Out.Rect)
		}
		size := got.Rect.Size()
		w, h := size.X, size.Y
		for j := 0; j < h; j++ {
			for i := 0; i < w; i++ {
				got := got.At(i, j)
				want := c.Out.At(i, j)
				if got != want {
					t.Errorf("At(%d, %d): %v, want: %v", i, j, got, want)
				}
			}
		}
	}
}
Ejemplo n.º 7
0
func image2paletted(height uint, img image.Image) *image.Paletted {
	resimg := resize.Resize(0, height, img, resize.Bilinear)
	pal := color.Palette(palette.Plan9)

	paletted := image.NewPaletted(resimg.Bounds(), pal)

	for y := 0; y < resimg.Bounds().Size().Y; y++ {
		for x := 0; x < resimg.Bounds().Size().X; x++ {
			paletted.Set(x, y, resimg.At(x, y))
		}
	}

	return paletted
}
Ejemplo n.º 8
0
func render(x, y, z int) []byte {
	// tileX and tileY is the absolute position of this tile at the current zoom level.
	tileX, tileY := x*tileSize, y*tileSize
	scale := 1 / float64(int(1<<uint(z))*tileSize)

	img := image.NewPaletted(image.Rect(0, 0, tileSize, tileSize), color.Palette(color_[:]))
	for i := 0; i < tileSize; i++ {
		for j := 0; j < tileSize; j++ {
			c := complex(float64(tileX+i)*scale, float64(tileY+j)*scale)
			img.SetColorIndex(i, j, mandelbrotValue(c))
		}
	}

	buf := new(bytes.Buffer)
	png.Encode(buf, img)
	return buf.Bytes()
}
Ejemplo n.º 9
0
func (d *decoder) parsePLTE(length uint32) error {
	np := int(length / 3) // The number of palette entries.
	if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) {
		return FormatError("bad PLTE length")
	}
	n, err := io.ReadFull(d.r, d.tmp[:3*np])
	if err != nil {
		return err
	}
	d.crc.Write(d.tmp[:n])
	switch d.cb {
	case cbP1, cbP2, cbP4, cbP8:
		d.palette = color.Palette(make([]color.Color, np))
		for i := 0; i < np; i++ {
			d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
		}
	case cbTC8, cbTCA8, cbTC16, cbTCA16:
		// As per the PNG spec, a PLTE chunk is optional (and for practical purposes,
		// ignorable) for the ctTrueColor and ctTrueColorAlpha color types (section 4.1.2).
	default:
		return FormatError("PLTE, color type mismatch")
	}
	return d.verifyChecksum()
}
Ejemplo n.º 10
0
// decode reads a GIF image from r and stores the result in d.
func (d *decoder) decode(r io.Reader, configOnly bool) error {
	// Add buffering if r does not provide ReadByte.
	if rr, ok := r.(reader); ok {
		d.r = rr
	} else {
		d.r = bufio.NewReader(r)
	}

	err := d.readHeaderAndScreenDescriptor()
	if err != nil {
		return err
	}
	if configOnly {
		return nil
	}

	if d.headerFields&fColorMapFollows != 0 {
		if d.globalColorMap, err = d.readColorMap(); err != nil {
			return err
		}
	}

	for {
		c, err := d.r.ReadByte()
		if err != nil {
			return err
		}
		switch c {
		case sExtension:
			if err = d.readExtension(); err != nil {
				return err
			}

		case sImageDescriptor:
			m, err := d.newImageFromDescriptor()
			if err != nil {
				return err
			}
			useLocalColorMap := d.imageFields&fColorMapFollows != 0
			if useLocalColorMap {
				m.Palette, err = d.readColorMap()
				if err != nil {
					return err
				}
			} else {
				m.Palette = d.globalColorMap
			}
			if d.hasTransparentIndex && int(d.transparentIndex) < len(m.Palette) {
				if !useLocalColorMap {
					// Clone the global color map.
					m.Palette = append(color.Palette(nil), d.globalColorMap...)
				}
				m.Palette[d.transparentIndex] = color.RGBA{}
			}
			litWidth, err := d.r.ReadByte()
			if err != nil {
				return err
			}
			if litWidth < 2 || litWidth > 8 {
				return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
			}
			// A wonderfully Go-like piece of magic.
			br := &blockReader{r: d.r}
			lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth))
			defer lzwr.Close()
			if _, err = io.ReadFull(lzwr, m.Pix); err != nil {
				if err != io.ErrUnexpectedEOF {
					return err
				}
				return errNotEnough
			}
			// Both lzwr and br should be exhausted. Reading from them
			// should yield (0, io.EOF).
			if n, err := lzwr.Read(d.tmp[:1]); n != 0 || err != io.EOF {
				if err != nil {
					return err
				}
				return errTooMuch
			}
			if n, err := br.Read(d.tmp[:1]); n != 0 || err != io.EOF {
				if err != nil {
					return err
				}
				return errTooMuch
			}

			// Check that the color indexes are inside the palette.
			if len(m.Palette) < 256 {
				for _, pixel := range m.Pix {
					if int(pixel) >= len(m.Palette) {
						return errBadPixel
					}
				}
			}

			// Undo the interlacing if necessary.
			if d.imageFields&ifInterlace != 0 {
				uninterlace(m)
			}

			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.
			d.delayTime = 0
			d.hasTransparentIndex = false

		case sTrailer:
			if len(d.image) == 0 {
				return io.ErrUnexpectedEOF
			}
			return nil

		default:
			return fmt.Errorf("gif: unknown block type: 0x%.2x", c)
		}
	}
}
Ejemplo n.º 11
0
func testEncodeAll(t *testing.T, go1Dot5Fields bool, useGlobalColorModel bool) {
	const width, height = 150, 103

	g0 := &GIF{
		Image:     make([]*image.Paletted, len(frames)),
		Delay:     make([]int, len(frames)),
		LoopCount: 5,
	}
	for i, f := range frames {
		g, err := readGIF(f)
		if err != nil {
			t.Fatal(f, err)
		}
		m := g.Image[0]
		if m.Bounds().Dx() != width || m.Bounds().Dy() != height {
			t.Fatalf("frame %d had unexpected bounds: got %v, want width/height = %d/%d",
				i, m.Bounds(), width, height)
		}
		g0.Image[i] = m
	}
	// The GIF.Disposal, GIF.Config and GIF.BackgroundIndex fields were added
	// in Go 1.5. Valid Go 1.4 or earlier code should still produce valid GIFs.
	//
	// On the following line, color.Model is an interface type, and
	// color.Palette is a concrete (slice) type.
	globalColorModel, backgroundIndex := color.Model(color.Palette(nil)), uint8(0)
	if useGlobalColorModel {
		globalColorModel, backgroundIndex = color.Palette(palette.WebSafe), uint8(1)
	}
	if go1Dot5Fields {
		g0.Disposal = make([]byte, len(g0.Image))
		for i := range g0.Disposal {
			g0.Disposal[i] = DisposalNone
		}
		g0.Config = image.Config{
			ColorModel: globalColorModel,
			Width:      width,
			Height:     height,
		}
		g0.BackgroundIndex = backgroundIndex
	}

	var buf bytes.Buffer
	if err := EncodeAll(&buf, g0); err != nil {
		t.Fatal("EncodeAll:", err)
	}
	encoded := buf.Bytes()
	config, err := DecodeConfig(bytes.NewReader(encoded))
	if err != nil {
		t.Fatal("DecodeConfig:", err)
	}
	g1, err := DecodeAll(bytes.NewReader(encoded))
	if err != nil {
		t.Fatal("DecodeAll:", err)
	}

	if !reflect.DeepEqual(config, g1.Config) {
		t.Errorf("DecodeConfig inconsistent with DecodeAll")
	}
	if !palettesEqual(g1.Config.ColorModel.(color.Palette), globalColorModel.(color.Palette)) {
		t.Errorf("unexpected global color model")
	}
	if w, h := g1.Config.Width, g1.Config.Height; w != width || h != height {
		t.Errorf("got config width * height = %d * %d, want %d * %d", w, h, width, height)
	}

	if g0.LoopCount != g1.LoopCount {
		t.Errorf("loop counts differ: %d and %d", g0.LoopCount, g1.LoopCount)
	}
	if backgroundIndex != g1.BackgroundIndex {
		t.Errorf("background indexes differ: %d and %d", backgroundIndex, g1.BackgroundIndex)
	}
	if len(g0.Image) != len(g1.Image) {
		t.Fatalf("image lengths differ: %d and %d", len(g0.Image), len(g1.Image))
	}
	if len(g1.Image) != len(g1.Delay) {
		t.Fatalf("image and delay lengths differ: %d and %d", len(g1.Image), len(g1.Delay))
	}
	if len(g1.Image) != len(g1.Disposal) {
		t.Fatalf("image and disposal lengths differ: %d and %d", len(g1.Image), len(g1.Disposal))
	}

	for i := range g0.Image {
		m0, m1 := g0.Image[i], g1.Image[i]
		if m0.Bounds() != m1.Bounds() {
			t.Errorf("frame %d: bounds differ: %v and %v", i, m0.Bounds(), m1.Bounds())
		}
		d0, d1 := g0.Delay[i], g1.Delay[i]
		if d0 != d1 {
			t.Errorf("frame %d: delay values differ: %d and %d", i, d0, d1)
		}
		p0, p1 := uint8(0), g1.Disposal[i]
		if go1Dot5Fields {
			p0 = DisposalNone
		}
		if p0 != p1 {
			t.Errorf("frame %d: disposal values differ: %d and %d", i, p0, p1)
		}
	}
}
Ejemplo n.º 12
0
func newDecoder(r io.Reader) (*decoder, error) {
	d := &decoder{
		r:        newReaderAt(r),
		features: make(map[int][]uint),
	}

	p := make([]byte, len(leHeader))
	if _, err := d.r.ReadAt(p, 0); err != nil {
		return nil, err
	}
	if string(p[0:len(leHeader)]) != leHeader {
		return nil, FormatError("malformed header")
	}
	d.byteOrder = binary.LittleEndian

	ifdOffset := int64(d.byteOrder.Uint32(p[4:8]))

	// The first two bytes contain the number of entries (12 bytes each).
	if _, err := d.r.ReadAt(p[0:2], ifdOffset); err != nil {
		return nil, err
	}
	numItems := int(d.byteOrder.Uint16(p[0:2]))

	// All IFD entries are read in one chunk.
	p = make([]byte, ifdLen*numItems)
	if _, err := d.r.ReadAt(p, ifdOffset+2); err != nil {
		return nil, err
	}

	for i := 0; i < len(p); i += ifdLen {
		if err := d.parseIFD(p[i : i+ifdLen]); err != nil {
			return nil, err
		}
	}

	d.config.Width = int(d.firstVal(tImageWidth))
	d.config.Height = int(d.firstVal(tImageLength))

	if _, ok := d.features[tBitsPerSample]; !ok {
		return nil, FormatError("BitsPerSample tag missing")
	}
	d.bpp = d.firstVal(tBitsPerSample)

	// Determine the image mode.
	switch d.firstVal(tPhotometricInterpretation) {
	case pRGB:
		for _, b := range d.features[tBitsPerSample] {
			if b != 8 {
				return nil, UnsupportedError("non-8-bit RGB image")
			}
		}
		d.config.ColorModel = color.RGBAModel
		// RGB images normally have 3 samples per pixel.
		// If there are more, ExtraSamples (p. 31-32 of the spec)
		// gives their meaning (usually an alpha channel).
		//
		// This implementation does not support extra samples
		// of an unspecified type.
		switch len(d.features[tBitsPerSample]) {
		case 3:
			d.mode = mRGB
		case 4:
			switch d.firstVal(tExtraSamples) {
			case 1:
				d.mode = mRGBA
			case 2:
				d.mode = mNRGBA
				d.config.ColorModel = color.NRGBAModel
			default:
				return nil, FormatError("wrong number of samples for RGB")
			}
		default:
			return nil, FormatError("wrong number of samples for RGB")
		}
	case pPaletted:
		d.mode = mPaletted
		d.config.ColorModel = color.Palette(d.palette)
	case pWhiteIsZero:
		d.mode = mGrayInvert
		if d.bpp == 16 {
			d.config.ColorModel = color.Gray16Model
		} else {
			d.config.ColorModel = color.GrayModel
		}
	case pBlackIsZero:
		d.mode = mGray
		if d.bpp == 16 {
			d.config.ColorModel = color.Gray16Model
		} else {
			d.config.ColorModel = color.GrayModel
		}
	default:
		return nil, UnsupportedError("color model")
	}

	return d, nil
}
Ejemplo n.º 13
0
func outputKeyboardImage() (map[string]image.Rectangle, error) {
	keyMap := map[string]image.Rectangle{}
	img := image.NewNRGBA(image.Rect(0, 0, 320, 240))
	x, y := 0, 0
	for j, line := range keyboardKeys {
		x = 0
		const height = 18
		for i, key := range line {
			width := 16
			switch j {
			default:
				switch i {
				case 0:
					width = 16 + 8*(j+2)
				case len(line) - 1:
					width = 16 + 8*(j+2)
				}
			case 4:
				switch i {
				case 0:
					width = 16 + 8*(j+2)
				case 1:
					width = 16 * 2
				case 2:
					width = 16 * 5
				case 3:
					width = 16 * 2
				case 4:
					width = 16 + 8*(j+2)
				}
			case 6, 7:
				width = 16 * 3
			}
			if key != "" {
				if err := drawKey(img, key, x, y, width); err != nil {
					return nil, err
				}
				if key != " " {
					keyMap[key] = image.Rect(x, y, x+width, y+height)
				}
			}
			x += width
		}
		y += height
	}

	palette := color.Palette([]color.Color{
		color.Transparent, color.Opaque,
	})
	palettedImg := image.NewPaletted(img.Bounds(), palette)
	draw.Draw(palettedImg, palettedImg.Bounds(), img, image.ZP, draw.Src)

	f, err := os.Create("../../_resources/images/keyboard/keyboard.png")
	if err != nil {
		return nil, err
	}
	defer f.Close()
	if err := png.Encode(f, palettedImg); err != nil {
		return nil, err
	}
	return keyMap, nil
}
Ejemplo n.º 14
0
func main() {
	const charFullWidth = 12
	const charHalfWidth = 6
	const charHeight = 16

	files := []string{
		"latin.png",
		"bmp-0.png",
		"bmp-2.png",
		"bmp-3.png",
		"bmp-4.png",
		"bmp-5.png",
		"bmp-6.png",
		"bmp-7.png",
		"bmp-8.png",
		"bmp-9.png",
		"bmp-15.png",
	}
	palette := color.Palette([]color.Color{
		color.Transparent, color.Opaque,
	})
	result := image.NewPaletted(image.Rect(0, 0, 256*charFullWidth, 256*charHeight), palette)
	for _, file := range files {
		f, err := os.Open(file)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		img, _, err := image.Decode(f)
		if err != nil {
			panic(err)
		}
		if file == "latin.png" {
			for i := 0; i < 256; i++ {
				dx := i * charFullWidth
				dy := 0
				dr := image.Rect(dx, dy, dx+charHalfWidth, dy+charHeight)
				sp := image.Point{
					(i % 32) * charHalfWidth,
					(i / 32) * charHeight,
				}
				draw.Draw(result, dr, img, sp, draw.Src)
			}
			continue
		}
		id, err := strconv.Atoi(regexp.MustCompile(`\d+`).FindString(file))
		if err != nil {
			panic(err)
		}
		for i := 0; i < 4096; i++ {
			if id == 0 && i < 256 {
				continue
			}
			dx := (i % 256) * charFullWidth
			dy := id*256 + (i/256)*charHeight
			dr := image.Rect(dx, dy, dx+charFullWidth, dy+charHeight)
			sp := image.Point{
				(i % 64) * charFullWidth,
				(i / 64) * charHeight,
			}
			draw.Draw(result, dr, img, sp, draw.Src)
		}
	}
	e := png.Encoder{CompressionLevel: png.BestCompression}
	if err := e.Encode(os.Stdout, result); err != nil {
		panic(err)
	}
}
Ejemplo n.º 15
0
func main() {

	objpath := ""
	flag.Parse()
	if flag.NArg() > 0 {
		objpath = flag.Arg(0)
	} else {
		showUsage()
		os.Exit(0)
	}

	obj, err := ReadObjFile(objpath, *dbg)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	if *dbg {
		fmt.Println("num vertices: ", len(obj.Vertices()))
		fmt.Println("num faces: ", len(obj.Triangles()))
		fmt.Println("scale factor: ", *scale)
	}

	// get image w/h by scaling the mesh aabb by the user-defined scale factor
	aabb := obj.AABB()
	aabb.Scale(float64(*scale))
	offx, offy := int(math.Floor(aabb.MinX)), int(math.Floor(aabb.MinZ))
	w, h := int(math.Ceil(aabb.MaxX)), int(math.Ceil(aabb.MaxZ))

	dc := gg.NewContext(w, h)
	dc.SetRGB255(255, 255, 255)
	dc.Clear()

	for _, t := range obj.Triangles() {
		// scale current triangle
		t.Scale(float64(*scale))

		// draw the triangle
		dc.MoveTo(t.P1.X(), t.P1.Z())
		dc.LineTo(t.P2.X(), t.P2.Z())
		dc.LineTo(t.P3.X(), t.P3.Z())
		dc.LineTo(t.P1.X(), t.P1.Z())
		dc.SetRGB255(0, 0, 0)
		dc.SetLineWidth(1)
		dc.FillPreserve()
		dc.Stroke()
	}
	fmt.Println("Rasterization completed")
	fmt.Println("Creating", *pngfile)

	f, err := os.Create(*pngfile)
	if err != nil {
		fmt.Println("Can't create ", *pngfile, ": ", err)
		os.Exit(1)
	}

	// convert image into a black and white one
	bw := []color.Color{color.Black, color.White}
	gr := &Converter{dc.Image(), color.Palette(bw)}

	err = png.Encode(f, gr)
	if err != nil {
		fmt.Println("Can't encode ", *pngfile, ": ", err)
		os.Exit(1)
	}

	fmt.Println("Resulting image details")

	if *dbg {
		fmt.Println("original mesh bounding box: ", obj.AABB())
		fmt.Println("scaled mesh bounding box: ", aabb)
	}
	fmt.Println("x, y offset: ", offx, offy)
	fmt.Println("scale: ", *scale)
	fmt.Println("width/height: ", w, h)
}
Ejemplo n.º 16
0
func (i WebSafePalettedImage) ColorModel() color.Model { return color.Palette(palette.WebSafe) }
Ejemplo n.º 17
0
func (i Plan9PalettedImage) ColorModel() color.Model { return color.Palette(palette.Plan9) }
Ejemplo n.º 18
0
package main

import (
	"image"
	"image/color"
	"image/color/palette"
	"image/draw"
	"image/gif"
	"math"
	"os"
)

var (
	pal = color.Palette(palette.Plan9) // TODO(aray) smaller palette
)

type HexMask struct {
	p    image.Point // top left of bounding rectangle
	size int         // size in pixels (dimension in both width and height)
}

func (hm *HexMask) ColorModel() color.Model {
	return color.AlphaModel
}

func (hm *HexMask) Bounds() image.Rectangle {
	return image.Rect(hm.p.X, hm.p.Y, hm.p.X+hm.size, hm.p.Y+hm.size)
}

func (hm *HexMask) At(xx, yy int) color.Color {
	x := float64(xx - hm.p.X)
Ejemplo n.º 19
0
// decode reads a GIF image from r and stores the result in d.
func (d *decoder) decode(r io.Reader, configOnly bool) error {
	// Add buffering if r does not provide ReadByte.
	if rr, ok := r.(reader); ok {
		d.r = rr
	} else {
		d.r = bufio.NewReader(r)
	}

	err := d.readHeaderAndScreenDescriptor()
	if err != nil {
		return err
	}
	if configOnly {
		return nil
	}

	for {
		c, err := d.r.ReadByte()
		if err != nil {
			return err
		}
		switch c {
		case sExtension:
			if err = d.readExtension(); err != nil {
				return err
			}

		case sImageDescriptor:
			m, err := d.newImageFromDescriptor()
			if err != nil {
				return err
			}
			useLocalColorTable := d.imageFields&fColorTable != 0
			if useLocalColorTable {
				m.Palette, err = d.readColorTable(d.imageFields)
				if err != nil {
					return err
				}
			} else {
				if d.globalColorTable == nil {
					return errors.New("gif: no color table")
				}
				m.Palette = d.globalColorTable
			}
			if d.hasTransparentIndex {
				if !useLocalColorTable {
					// Clone the global color table.
					m.Palette = append(color.Palette(nil), d.globalColorTable...)
				}
				if ti := int(d.transparentIndex); ti < len(m.Palette) {
					m.Palette[ti] = color.RGBA{}
				} else {
					// The transparentIndex is out of range, which is an error
					// according to the spec, but Firefox and Google Chrome
					// seem OK with this, so we enlarge the palette with
					// transparent colors. See golang.org/issue/15059.
					p := make(color.Palette, ti+1)
					copy(p, m.Palette)
					for i := len(m.Palette); i < len(p); i++ {
						p[i] = color.RGBA{}
					}
					m.Palette = p
				}
			}
			litWidth, err := d.r.ReadByte()
			if err != nil {
				return err
			}
			if litWidth < 2 || litWidth > 8 {
				return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
			}
			// A wonderfully Go-like piece of magic.
			br := &blockReader{r: d.r}
			lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth))
			defer lzwr.Close()
			if _, err = io.ReadFull(lzwr, m.Pix); err != nil {
				if err != io.ErrUnexpectedEOF {
					return err
				}
				return errNotEnough
			}
			// Both lzwr and br should be exhausted. Reading from them should
			// yield (0, io.EOF).
			//
			// The spec (Appendix F - Compression), says that "An End of
			// Information code... must be the last code output by the encoder
			// for an image". In practice, though, giflib (a widely used C
			// library) does not enforce this, so we also accept lzwr returning
			// io.ErrUnexpectedEOF (meaning that the encoded stream hit io.EOF
			// before the LZW decoder saw an explicit end code), provided that
			// the io.ReadFull call above successfully read len(m.Pix) bytes.
			// See https://golang.org/issue/9856 for an example GIF.
			if n, err := lzwr.Read(d.tmp[:1]); n != 0 || (err != io.EOF && err != io.ErrUnexpectedEOF) {
				if err != nil {
					return err
				}
				return errTooMuch
			}
			if n, err := br.Read(d.tmp[:1]); n != 0 || err != io.EOF {
				if err != nil {
					return err
				}
				return errTooMuch
			}

			// Check that the color indexes are inside the palette.
			if len(m.Palette) < 256 {
				for _, pixel := range m.Pix {
					if int(pixel) >= len(m.Palette) {
						return errBadPixel
					}
				}
			}

			// Undo the interlacing if necessary.
			if d.imageFields&fInterlace != 0 {
				uninterlace(m)
			}

			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.
			d.delayTime = 0
			d.hasTransparentIndex = false

		case sTrailer:
			if len(d.image) == 0 {
				return io.ErrUnexpectedEOF
			}
			return nil

		default:
			return fmt.Errorf("gif: unknown block type: 0x%.2x", c)
		}
	}
}