func make_lzw(t *Transport, config map[string]interface{}) (uint64, tagfn, tagfn) { var wbuf bytes.Buffer enc := func(in, out []byte) int { if len(in) == 0 { return 0 } wbuf.Reset() writer := lzw.NewWriter(&wbuf, lzw.LSB, 8 /*litWidth*/) if _, err := writer.Write(in); err != nil { panic(err) } writer.Close() return copy(out, wbuf.Bytes()) } dec := func(in, out []byte) int { if len(in) == 0 { return 0 } reader := lzw.NewReader(bytes.NewReader(in), lzw.LSB, 8 /*litWidth*/) n, err := readAll(reader, out) if err != nil { panic(err) } reader.Close() return n } return tagLzw, enc, dec }
// UpdateDeps is used to update the values of the dependencies for a template func (d *DedupManager) UpdateDeps(t *Template, deps []dep.Dependency) error { // Calculate the path to write updates to dataPath := path.Join(d.config.Deduplicate.Prefix, t.hexMD5, "data") // Package up the dependency data td := templateData{ Data: make(map[string]interface{}), } for _, dp := range deps { // Skip any dependencies that can't be shared if !dp.CanShare() { continue } // Pull the current value from the brain val, ok := d.brain.Recall(dp) if ok { td.Data[dp.HashCode()] = val } } // Encode via GOB and LZW compress var buf bytes.Buffer compress := lzw.NewWriter(&buf, lzw.LSB, 8) enc := gob.NewEncoder(compress) if err := enc.Encode(&td); err != nil { return fmt.Errorf("encode failed: %v", err) } compress.Close() // Compute MD5 of the buffer hash := md5.Sum(buf.Bytes()) d.lastWriteLock.RLock() existing, ok := d.lastWrite[t] d.lastWriteLock.RUnlock() if ok && bytes.Equal(existing, hash[:]) { log.Printf("[INFO] (dedup) de-duplicate data '%s' already current", dataPath) return nil } // Write the KV update kvPair := consulapi.KVPair{ Key: dataPath, Value: buf.Bytes(), Flags: templateDataFlag, } client, err := d.clients.Consul() if err != nil { return fmt.Errorf("failed to get consul client: %v", err) } if _, err := client.KV().Put(&kvPair, nil); err != nil { return fmt.Errorf("failed to write '%s': %v", dataPath, err) } log.Printf("[INFO] (dedup) updated de-duplicate data '%s'", dataPath) d.lastWriteLock.Lock() d.lastWrite[t] = hash[:] d.lastWriteLock.Unlock() return nil }
func compressLZW(s []byte) []byte { var b bytes.Buffer w := lzw.NewWriter(&b, lzw.LSB, 8) w.Write([]byte("hello, world\n")) defer w.Close() return b.Bytes() }
func TestNoPalette(t *testing.T) { b := &bytes.Buffer{} // Manufacture a GIF with no palette, so any pixel at all // will be invalid. b.WriteString(header[:len(header)-3]) b.WriteString("\x00\x00\x00") // No global palette. // Image descriptor: 2x1, no local palette. b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02") // Encode the pixels: neither is in range, because there is no palette. pix := []byte{0, 128} enc := &bytes.Buffer{} w := lzw.NewWriter(enc, lzw.LSB, 2) w.Write(pix) w.Close() b.WriteByte(byte(len(enc.Bytes()))) b.Write(enc.Bytes()) b.WriteByte(0x00) // An empty block signifies the end of the image data. b.WriteString(trailer) try(t, b.Bytes(), "gif: invalid pixel value") }
// lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes. func lzwEncode(n int) []byte { b := &bytes.Buffer{} w := lzw.NewWriter(b, lzw.LSB, 2) w.Write(make([]byte, n)) w.Close() return b.Bytes() }
func (e *encoder) writeFrame(index int) (err error) { e.buildFrameHeader(index) _, err = e.w.Write(e.frameHeader[:]) if err != nil { return } codeSize := log2(e.colorTableSize + 2) _, err = e.w.Write([]byte{uint8(codeSize)}) // Start of LZW with minimum code size. if err != nil { return } lzww := lzw.NewWriter(&blockWriter{e.w, 0}, lzw.LSB, codeSize) _, err = lzww.Write(e.g.Image[index].Pix) lzww.Close() if err != nil { return } _, err = e.w.Write([]byte{uint8(0x00)}) // End of LZW data. if err != nil { return } return nil }
func RunTestLZW(data []byte) { log.Printf("encoding/RunTestLZW: Testing comprssion LZW\n") var compressed bytes.Buffer w := lzw.NewWriter(&compressed, lzw.MSB, 8) defer w.Close() now := time.Now() w.Write(data) cl := compressed.Len() log.Printf("encoding/RunTestLZW: Compressed from %d bytes to %d bytes in %d ns\n", len(data), cl, time.Since(now).Nanoseconds()) recovered := make([]byte, len(data)) r := lzw.NewReader(&compressed, lzw.MSB, 8) defer r.Close() total := 0 n := 100 var err error = nil for err != io.EOF && n != 0 { n, err = r.Read(recovered[total:]) total += n } log.Printf("encoding/RunTestLZW: Uncompressed from %d bytes to %d bytes in %d ns\n", cl, len(recovered), time.Since(now).Nanoseconds()) }
/* compressRateLzw return compression rate of `text` as length of compressed text / length of text */ func compressRateLzw(text string) (float64, error) { var buf bytes.Buffer btext := []byte(text) btextlen := len(btext) if btextlen <= 0 { return 0, nil } w := lzw.NewWriter(&buf, lzw.MSB, 8) n, e := w.Write(btext) if e != nil { fmt.Printf("error: %s, rate: %d, len: %d\n", e, n, btextlen) return 1, e } e = w.Close() if e != nil { fmt.Printf("error: %s, rate: %d, len: %d\n", e, n, btextlen) return 1, e } return float64(buf.Len()) / float64(btextlen), nil }
func TestPixelOutsidePaletteRange(t *testing.T) { for _, pval := range []byte{0, 1, 2, 3, 255} { b := &bytes.Buffer{} // Manufacture a GIF with a 2 color palette. b.WriteString(header) b.WriteString(palette) // Image descriptor: 2x1, no local palette. b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02") // Encode the pixels; some pvals trigger the expected error. pix := []byte{pval, pval} enc := &bytes.Buffer{} w := lzw.NewWriter(enc, lzw.LSB, 2) w.Write(pix) w.Close() b.WriteByte(byte(len(enc.Bytes()))) b.Write(enc.Bytes()) b.WriteByte(0x00) // An empty block signifies the end of the image data. b.WriteString(trailer) // No error expected, unless the pixels are beyond the 2 color palette. want := "" if pval >= 2 { want = "gif: invalid pixel value" } try(t, b.Bytes(), want) } }
func lzwCompress(input io.Reader, out io.Writer) error { writer := lzw.NewWriter(out, lzw.MSB, 8) _, err := io.Copy(writer, input) if err != nil { return err } writer.Close() return nil }
func (self *LzwCompressor) Compress(src []byte) ([]byte, error) { cdest := bytes.NewBuffer(make([]byte, 0, len(src))) compressor := lzw.NewWriter(cdest, self.order, self.litWidth) compressor.Write(src) err := compressor.Close() if err != nil { fmt.Println("Compress Close err:%s", err.Error()) } return cdest.Bytes(), err }
// Compress places the canary byte in a buffer and uses the same buffer to fill // in the compressed information of the given input. The configuration supports // two type of compression: LZW and Gzip. When using Gzip compression format, // if GzipCompressionLevel is not specified, the 'gzip.DefaultCompression' will // be assumed. func Compress(data []byte, config *CompressionConfig) ([]byte, error) { var buf bytes.Buffer var writer io.WriteCloser var err error if config == nil { return nil, fmt.Errorf("config is nil") } // Write the canary into the buffer and create writer to compress the // input data based on the configured type switch config.Type { case CompressionTypeLzw: buf.Write([]byte{CompressionCanaryLzw}) writer = lzw.NewWriter(&buf, lzw.LSB, 8) case CompressionTypeGzip: buf.Write([]byte{CompressionCanaryGzip}) switch { case config.GzipCompressionLevel == gzip.BestCompression, config.GzipCompressionLevel == gzip.BestSpeed, config.GzipCompressionLevel == gzip.DefaultCompression: // These are valid compression levels default: // If compression level is set to NoCompression or to // any invalid value, fallback to Defaultcompression config.GzipCompressionLevel = gzip.DefaultCompression } writer, err = gzip.NewWriterLevel(&buf, config.GzipCompressionLevel) default: return nil, fmt.Errorf("unsupported compression type") } if err != nil { return nil, fmt.Errorf("failed to create a compression writer; err: %v", err) } if writer == nil { return nil, fmt.Errorf("failed to create a compression writer") } // Compress the input and place it in the same buffer containing the // canary byte. if _, err = writer.Write(data); err != nil { return nil, fmt.Errorf("failed to compress input data; err: %v", err) } // Close the io.WriteCloser if err = writer.Close(); err != nil { return nil, err } // Return the compressed bytes with canary byte at the start return buf.Bytes(), nil }
// lzwEncode returns an LZW encoding (with 2-bit literals) of in. func lzwEncode(in []byte) []byte { b := &bytes.Buffer{} w := lzw.NewWriter(b, lzw.LSB, 2) if _, err := w.Write(in); err != nil { panic(err) } if err := w.Close(); err != nil { panic(err) } return b.Bytes() }
func LzwMustCompress(inb []byte) (outb []byte) { buf := &bytes.Buffer{} w := lzw.NewWriter(buf, lzw.LSB, 8) _, err := w.Write(inb) if err != nil { w.Close() panic(err) } err = w.Close() if err != nil { panic(err) } return buf.Bytes() }
// Sérialise le réseau à l'interrieur d'un fichier func (self *Reto) Serialize(filename string) { file, err := os.Create(filename) if err != nil { log.Fatal(err) } defer file.Close() stream := lzw.NewWriter(file, lzw.LSB, 8) defer stream.Close() encoder := json.NewEncoder(stream) encoder.Encode(self) if err != nil { log.Fatal(err) } }
func newStream(filter name) *stream { st := new(stream) st.filter = filter switch filter { case streamLZWDecode: st.writer = lzw.NewWriter(&st.Buffer, lzw.MSB, 8) case streamFlateDecode: st.writer = zlib.NewWriter(&st.Buffer) default: // TODO: warn about bad filter names? st.writer = &st.Buffer } return st }
func (e *Engine) lzw_lsb() error { var buf bytes.Buffer var litWidth int var err error litWidth, err = e.stack.PopInt() if err == nil { w := lzw.NewWriter(&buf, lzw.LSB, litWidth) _, err = w.Write(e.stack.Pop()) w.Close() } if err == nil { e.stack.Push(buf.Bytes()) } return err }
func main() { ugo.MaxProcs() ufs.NewDirWalker(false, nil, func(fullPath string) bool { blobs = append(blobs, ufs.ReadBinaryFile(fullPath, true)) return true }).Walk(dirPath) testComp("flate1", func(w io.Writer) (wc io.WriteCloser) { var err error if wc, err = flate.NewWriter(w, 1); err != nil { panic(err) } return }, flate.NewReader) testComp("flate9", func(w io.Writer) (wc io.WriteCloser) { var err error if wc, err = flate.NewWriter(w, 9); err != nil { panic(err) } return }, flate.NewReader) testComp("lzw\t", func(w io.Writer) io.WriteCloser { return lzw.NewWriter(w, lzw.MSB, 8) }, func(r io.Reader) io.ReadCloser { return lzw.NewReader(r, lzw.MSB, 8) }) testComp("zlib", func(w io.Writer) io.WriteCloser { return zlib.NewWriter(w) }, func(r io.Reader) (rc io.ReadCloser) { var err error if rc, err = zlib.NewReader(r); err != nil { panic(err) } return }) testComp("gzip", func(w io.Writer) io.WriteCloser { return gzip.NewWriter(w) }, func(r io.Reader) (rc io.ReadCloser) { var err error if rc, err = gzip.NewReader(r); err != nil { panic(err) } return }) printStats("PACK:", packStats) printStats("UNPACK:", unpackStats) }
func Fuzz(data []byte) int { r := lzw.NewReader(bytes.NewReader(data), lzw.MSB, 8) uncomp := make([]byte, 64<<10) n, err := r.Read(uncomp) if err != nil && err != io.EOF { return 0 } if n == len(uncomp) { return 0 // too large } uncomp = uncomp[:n] for width := 2; width <= 8; width++ { uncomp0 := append([]byte{}, uncomp...) for i, v := range uncomp0 { uncomp0[i] = v & (1<<uint(width) - 1) } for _, order := range []lzw.Order{lzw.MSB, lzw.LSB} { buf := new(bytes.Buffer) w := lzw.NewWriter(buf, order, width) n, err := w.Write(uncomp0) if err != nil { fmt.Printf("order=%v width=%v\n", order, width) panic(err) } if n != len(uncomp0) { fmt.Printf("order=%v width=%v\n", order, width) panic("short write") } if err := w.Close(); err != nil { fmt.Printf("order=%v width=%v\n", order, width) panic(err) } r1 := lzw.NewReader(buf, order, width) uncomp1, err := ioutil.ReadAll(r1) if err != nil { fmt.Printf("order=%v width=%v\n", order, width) panic(err) } if !bytes.Equal(uncomp0, uncomp1) { fmt.Printf("order=%v width=%v\n", order, width) panic("data differs") } } } return 1 }
func encodeImageBlock(w io.Writer, img *image.Paletted) error { // start image litWidth := int(paletteBits(img.Palette)) if litWidth < 2 { litWidth = 2 } bounds := img.Bounds() if err := writeData(w, byte(0x2C), uint16(bounds.Min.X), uint16(bounds.Min.Y), uint16(bounds.Dx()), uint16(bounds.Dy()), byte(0), byte(litWidth), ); err != nil { return err } // start compression blocks := &blockWriter{w: w} compress := lzw.NewWriter(blocks, lzw.LSB, litWidth) // write each scan line (might not be contiguous) startX := img.Rect.Min.X stopX := img.Rect.Max.X stopY := img.Rect.Max.Y for y := img.Rect.Min.Y; y < stopY; y++ { start := img.PixOffset(startX, y) stop := img.PixOffset(stopX, y) if _, err := compress.Write(img.Pix[start:stop]); err != nil { return err } } if err := compress.Close(); err != nil { return err } return blocks.Close() }
func (p *wmDecisionCore) bodyEncoder(w io.Writer) (io.Writer, os.Error) { var outW io.Writer var err os.Error switch p.encoding { default: outW = w case "identity": outW = w case "deflate": outW = flate.NewWriter(w, 6) case "gzip": outW, err = gzip.NewWriter(w) case "lzw": outW = lzw.NewWriter(w, lzw.LSB, 8) case "zlib": outW, err = zlib.NewWriter(w) } return outW, err }
func main() { flag.Parse() fname := "event.gob" switch *compr { case "gzip": fname = fmt.Sprintf("%s.gz", fname) case "zlib": fname = fmt.Sprintf("%s.z", fname) case "lzw": fname = fmt.Sprintf("%s.lzw", fname) case "none", "": fname = fname default: fname = fname } f, err := os.Create(fname) if err != nil { panic(err) } var ff io.WriteCloser = nil switch *compr { case "gzip": ff = gzip.NewWriter(f) case "zlib": ff = zlib.NewWriter(f) case "lzw": ff = lzw.NewWriter(f, lzw.MSB, 8) err = nil default: ff = f } if err != nil { panic(err) } tree0(ff) ff.Close() f.Close() }
// compressPayload takes an opaque input buffer, compresses it // and wraps it in a compress{} message that is encoded. func compressPayload(inp []byte) (*bytes.Buffer, error) { var buf bytes.Buffer compressor := lzw.NewWriter(&buf, lzw.LSB, lzwLitWidth) _, err := compressor.Write(inp) if err != nil { return nil, err } // Ensure we flush everything out if err := compressor.Close(); err != nil { return nil, err } // Create a compressed message c := compress{ Algo: lzwAlgo, Buf: buf.Bytes(), } return encode(compressMsg, &c) }
func getCompressor(out io.Writer) io.WriteCloser { switch *algorithm { case "bzip2": log.Fatalf("no compressor for bzip2. Try `bzip2 -c everything.go > everything.go.bzip2`") case "flate": compressor, err := flate.NewWriter(out, flate.BestCompression) if err != nil { log.Fatalf("failed making flate compressor: %s", err) } return compressor case "gzip": return gzip.NewWriter(out) case "lzw": // More specific uses of Order and litWidth are in the package docs return lzw.NewWriter(out, lzw.MSB, 8) case "zlib": return zlib.NewWriter(out) default: log.Fatalf("choose one of bzip2, flate, gzip, lzw, zlib with -algorithm") } panic("not reached") }
func main() { var ( file string pngfile string size int dpi int minset bool packstr bool ) flag.StringVar(&file, "f", "font.ttf", "truetype font filename") flag.StringVar(&pngfile, "png", "", "filename for png result") flag.IntVar(&size, "pt", 12, "font size") flag.IntVar(&dpi, "dpi", 144, "resolution") flag.BoolVar(&minset, "min", false, "reduced set of characters") flag.BoolVar(&packstr, "lzw", false, "print lzw compressed and base64 encoded string") flag.Parse() data, err := ioutil.ReadFile(file) if err != nil { log.Fatal(err) } font, err := freetype.ParseFont(data) if err != nil { log.Fatal(err) } scale := int32(dpi * size) fc := freetype.NewContext() fc.SetDPI(float64(dpi)) fc.SetHinting(freetype.FullHinting) fc.SetFontSize(float64(size)) fc.SetFont(font) bounds := font.Bounds(scale) width := int((bounds.XMax-bounds.XMin)+71) / 72 height := int((bounds.YMax-bounds.YMin)+71) / 72 dx := int(-bounds.XMin+71) / 72 dy := int(bounds.YMax+71) / 72 offset := 0 cols, rows := 32, 8 if minset { offset = 32 cols, rows = 16, 6 } dst := image.NewAlpha(image.Rect(0, 0, width*cols, height*rows)) fc.SetDst(dst) fc.SetSrc(image.White) fc.SetClip(dst.Bounds()) maxAdvance := int32(0) for y := 0; y < rows; y++ { for x := 0; x < cols; x++ { c := y*cols + x + offset hm := font.HMetric(scale/72, font.Index(rune(c))) if maxAdvance < hm.AdvanceWidth { maxAdvance = hm.AdvanceWidth } p := freetype.Pt(x*width+dx, y*height+dy) fc.DrawString(string(c), p) } } fmt.Printf("// %vx%v\n", dst.Rect.Dx(), dst.Rect.Dy()) fmt.Println("//", width, "x", height, "->", maxAdvance) if len(pngfile) > 0 { dstfile, err := os.Create(pngfile) if err != nil { log.Fatal(err) } defer dstfile.Close() png.Encode(dstfile, dst) } if packstr { var b bytes.Buffer e := base64.NewEncoder(base64.StdEncoding, &b) w := lzw.NewWriter(e, lzw.MSB, 8) w.Write(dst.Pix) w.Close() e.Close() nbytes := len(b.Bytes()) linelen := 72 rows := nbytes / linelen fmt.Println("//", nbytes) for r := 0; r < rows; r++ { slice := b.Bytes()[r*linelen : (r+1)*linelen] fmt.Printf("\"%s\"\n", slice) } if rows*linelen < nbytes { fmt.Printf("\"%s\"\n", b.Bytes()[rows*linelen:]) } } if len(pngfile) == 0 && !packstr { nbytes := len(dst.Pix) cols := 12 rows := nbytes / cols for y := 0; y < rows; y++ { for x := 0; x < cols; x++ { fmt.Printf(" %#02x,", dst.Pix[y*cols+x]) } fmt.Println("") } for r := rows * cols; r < nbytes; r++ { fmt.Printf(" %#02x,", dst.Pix[r]) } fmt.Println("") } }
func (c compressor) GetWriter(w io.Writer) io.WriteCloser { return lzw.NewWriter(w, lzw.LSB, 8) }
func (e *encoder) writeImageBlock(pm *image.Paletted, delay int, disposal byte) { if e.err != nil { return } if len(pm.Palette) == 0 { e.err = errors.New("gif: cannot encode image block with empty palette") return } b := pm.Bounds() if b.Min.X < 0 || b.Max.X >= 1<<16 || b.Min.Y < 0 || b.Max.Y >= 1<<16 { e.err = errors.New("gif: image block is too large to encode") return } if !b.In(image.Rectangle{Max: image.Point{e.g.Config.Width, e.g.Config.Height}}) { e.err = errors.New("gif: image block is out of bounds") return } transparentIndex := -1 for i, c := range pm.Palette { if _, _, _, a := c.RGBA(); a == 0 { transparentIndex = i break } } if delay > 0 || disposal != 0 || transparentIndex != -1 { e.buf[0] = sExtension // Extension Introducer. e.buf[1] = gcLabel // Graphic Control Label. e.buf[2] = gcBlockSize // Block Size. if transparentIndex != -1 { e.buf[3] = 0x01 | disposal<<2 } else { e.buf[3] = 0x00 | disposal<<2 } writeUint16(e.buf[4:6], uint16(delay)) // Delay Time (1/100ths of a second) // Transparent color index. if transparentIndex != -1 { e.buf[6] = uint8(transparentIndex) } else { e.buf[6] = 0x00 } e.buf[7] = 0x00 // Block Terminator. e.write(e.buf[:8]) } e.buf[0] = sImageDescriptor writeUint16(e.buf[1:3], uint16(b.Min.X)) writeUint16(e.buf[3:5], uint16(b.Min.Y)) writeUint16(e.buf[5:7], uint16(b.Dx())) writeUint16(e.buf[7:9], uint16(b.Dy())) e.write(e.buf[:9]) paddedSize := log2(len(pm.Palette)) // Size of Local Color Table: 2^(1+n). ct := encodeColorTable(e.localColorTable[:], pm.Palette, paddedSize) if ct != e.globalCT || !bytes.Equal(e.globalColorTable[:ct], e.localColorTable[:ct]) { // Use a local color table. e.writeByte(fColorTable | uint8(paddedSize)) e.write(e.localColorTable[:ct]) } else { // Use the global color table. e.writeByte(0) } litWidth := paddedSize + 1 if litWidth < 2 { litWidth = 2 } e.writeByte(uint8(litWidth)) // LZW Minimum Code Size. lzww := lzw.NewWriter(blockWriter{e: e}, lzw.LSB, litWidth) if dx := b.Dx(); dx == pm.Stride { _, e.err = lzww.Write(pm.Pix) if e.err != nil { lzww.Close() return } } else { for i, y := 0, b.Min.Y; y < b.Max.Y; i, y = i+pm.Stride, y+1 { _, e.err = lzww.Write(pm.Pix[i : i+dx]) if e.err != nil { lzww.Close() return } } } lzww.Close() e.writeByte(0x00) // Block Terminator. }
func compressStream(file io.WriteCloser) io.WriteCloser { return lzw.NewWriter(file, lzw.LSB, 8) }
func TestDecode(t *testing.T) { // lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes. lzwEncode := func(n int) []byte { b := &bytes.Buffer{} w := lzw.NewWriter(b, lzw.LSB, 2) w.Write(make([]byte, n)) w.Close() return b.Bytes() } testCases := []struct { nPix int // The number of pixels in the image data. extra bool // Whether to write an extra block after the LZW-encoded data. wantErr error }{ {0, false, errNotEnough}, {1, false, errNotEnough}, {2, false, nil}, {2, true, errTooMuch}, {3, false, errTooMuch}, } for _, tc := range testCases { b := &bytes.Buffer{} b.WriteString(header) b.WriteString(palette) // Write an image with bounds 2x1 but tc.nPix pixels. If tc.nPix != 2 // then this should result in an invalid GIF image. First, write a // magic 0x2c (image descriptor) byte, bounds=(0,0)-(2,1), a flags // byte, and 2-bit LZW literals. b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02") if tc.nPix > 0 { enc := lzwEncode(tc.nPix) if len(enc) > 0xff { t.Errorf("nPix=%d, extra=%t: compressed length %d is too large", tc.nPix, tc.extra, len(enc)) continue } b.WriteByte(byte(len(enc))) b.Write(enc) } if tc.extra { b.WriteString("\x01\x02") // A 1-byte payload with an 0x02 byte. } b.WriteByte(0x00) // An empty block signifies the end of the image data. b.WriteString(trailer) got, err := Decode(b) if err != tc.wantErr { t.Errorf("nPix=%d, extra=%t\ngot %v\nwant %v", tc.nPix, tc.extra, err, tc.wantErr) } if tc.wantErr != nil { continue } want := &image.Paletted{ Pix: []uint8{0, 0}, Stride: 2, Rect: image.Rect(0, 0, 2, 1), Palette: color.Palette{ color.RGBA{0x10, 0x20, 0x30, 0xff}, color.RGBA{0x40, 0x50, 0x60, 0xff}, }, } if !reflect.DeepEqual(got, want) { t.Errorf("nPix=%d, extra=%t\ngot %v\nwant %v", tc.nPix, tc.extra, got, want) } } }
func (e *encoder) writeImageBlock(pm *image.Paletted, delay, transparentIndex int) { if e.err != nil { return } if len(pm.Palette) == 0 { e.err = errors.New("gif: cannot encode image block with empty palette") return } b := pm.Bounds() if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 || b.Min.X < 0 || b.Min.X >= 1<<16 || b.Min.Y < 0 || b.Min.Y >= 1<<16 { e.err = errors.New("gif: image block is too large to encode") return } // -1 means unknown transparent index; -2 means definitely no transparent index. if transparentIndex == -1 { for i, c := range pm.Palette { if _, _, _, a := c.RGBA(); a == 0 { transparentIndex = i break } } transparentIndex = -2 } if delay > 0 || transparentIndex >= 0 { e.buf[0] = sExtension // Extension Introducer. e.buf[1] = gcLabel // Graphic Control Label. e.buf[2] = gcBlockSize // Block Size. if transparentIndex >= 0 { e.buf[3] = 0x01 } else { e.buf[3] = 0x00 } writeUint16(e.buf[4:6], uint16(delay)) // Delay Time (1/100ths of a second) // Transparent color index. if transparentIndex >= 0 { e.buf[6] = uint8(transparentIndex) } else { e.buf[6] = 0x00 } e.buf[7] = 0x00 // Block Terminator. e.write(e.buf[:8]) } e.buf[0] = sImageDescriptor writeUint16(e.buf[1:3], uint16(b.Min.X)) writeUint16(e.buf[3:5], uint16(b.Min.Y)) writeUint16(e.buf[5:7], uint16(b.Dx())) writeUint16(e.buf[7:9], uint16(b.Dy())) e.write(e.buf[:9]) paddedSize := log2(len(pm.Palette)) // Size of Local Color Table: 2^(1+n). // Interlacing is not supported. e.writeByte(0x80 | uint8(paddedSize)) // Local Color Table. e.writeColorTable(pm.Palette, paddedSize) litWidth := paddedSize + 1 if litWidth < 2 { litWidth = 2 } e.writeByte(uint8(litWidth)) // LZW Minimum Code Size. lzww := lzw.NewWriter(blockWriter{e: e}, lzw.LSB, litWidth) _, e.err = lzww.Write(pm.Pix) if e.err != nil { lzww.Close() return } lzww.Close() e.writeByte(0x00) // Block Terminator. }