// Copyright 2011 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.
// Package lzw implements the Lempel-Ziv-Welch compressed data format,// described in T. A. Welch, “A Technique for High-Performance Data// Compression”, Computer, 17(6) (June 1984), pp 8-19.//// In particular, it implements LZW as used by the GIF and PDF file// formats, which means variable-width codes up to 12 bits and the first// two non-literal codes are a clear code and an EOF code.//// The TIFF file format uses a similar but incompatible version of the LZW// algorithm. See the [golang.org/x/image/tiff/lzw] package for an// implementation.
package lzw// TODO(nigeltao): check that PDF uses LZW in the same way as GIF,// modulo LSB/MSB packing order.import ()// Order specifies the bit ordering in an LZW data stream.typeOrderintconst (// LSB means Least Significant Bits first, as used in the GIF file format.LSBOrder = iota// MSB means Most Significant Bits first, as used in the TIFF and PDF // file formats.MSB)const ( maxWidth = 12 decoderInvalidCode = 0xffff flushBuffer = 1 << maxWidth)// Reader is an [io.Reader] which can be used to read compressed data in the// LZW format.typeReaderstruct { r io.ByteReader bits uint32 nBits uint width uint read func(*Reader) (uint16, error) // readLSB or readMSB litWidth int// width in bits of literal codes err error// The first 1<<litWidth codes are literal codes. // The next two codes mean clear and EOF. // Other valid codes are in the range [lo, hi] where lo := clear + 2, // with the upper bound incrementing on each code seen. // // overflow is the code at which hi overflows the code width. It always // equals 1 << width. // // last is the most recently seen code, or decoderInvalidCode. // // An invariant is that hi < overflow. clear, eof, hi, overflow, last uint16// Each code c in [lo, hi] expands to two or more bytes. For c != hi: // suffix[c] is the last of these bytes. // prefix[c] is the code for all but the last byte. // This code can either be a literal code or another code in [lo, c). // The c == hi case is a special case. suffix [1 << maxWidth]uint8 prefix [1 << maxWidth]uint16// output is the temporary output buffer. // Literal codes are accumulated from the start of the buffer. // Non-literal codes decode to a sequence of suffixes that are first // written right-to-left from the end of the buffer before being copied // to the start of the buffer. // It is flushed when it contains >= 1<<maxWidth bytes, // so that there is always room to decode an entire code. output [2 * 1 << maxWidth]byte o int// write index into output toRead []byte// bytes to return from Read}// readLSB returns the next code for "Least Significant Bits first" data.func ( *Reader) () (uint16, error) {for .nBits < .width { , := .r.ReadByte()if != nil {return0, } .bits |= uint32() << .nBits .nBits += 8 } := uint16(.bits & (1<<.width - 1)) .bits >>= .width .nBits -= .widthreturn , nil}// readMSB returns the next code for "Most Significant Bits first" data.func ( *Reader) () (uint16, error) {for .nBits < .width { , := .r.ReadByte()if != nil {return0, } .bits |= uint32() << (24 - .nBits) .nBits += 8 } := uint16(.bits >> (32 - .width)) .bits <<= .width .nBits -= .widthreturn , nil}// Read implements io.Reader, reading uncompressed bytes from its underlying reader.func ( *Reader) ( []byte) (int, error) {for {iflen(.toRead) > 0 { := copy(, .toRead) .toRead = .toRead[:]return , nil }if .err != nil {return0, .err } .decode() }}// decode decompresses bytes from r and leaves them in d.toRead.// read specifies how to decode bytes into codes.// litWidth is the width in bits of literal codes.func ( *Reader) () {// Loop over the code stream, converting codes into decompressed bytes.:for { , := .read()if != nil {if == io.EOF { = io.ErrUnexpectedEOF } .err = break }switch {case < .clear:// We have a literal code. .output[.o] = uint8() .o++if .last != decoderInvalidCode {// Save what the hi code expands to. .suffix[.hi] = uint8() .prefix[.hi] = .last }case == .clear: .width = 1 + uint(.litWidth) .hi = .eof .overflow = 1 << .width .last = decoderInvalidCodecontinuecase == .eof: .err = io.EOFbreakcase <= .hi: , := , len(.output)-1if == .hi && .last != decoderInvalidCode {// code == hi is a special case which expands to the last expansion // followed by the head of the last expansion. To find the head, we walk // the prefix chain until we find a literal code. = .lastfor >= .clear { = .prefix[] } .output[] = uint8() -- = .last }// Copy the suffix chain into output and then write that to w.for >= .clear { .output[] = .suffix[] -- = .prefix[] } .output[] = uint8() .o += copy(.output[.o:], .output[:])if .last != decoderInvalidCode {// Save what the hi code expands to. .suffix[.hi] = uint8() .prefix[.hi] = .last }default: .err = errors.New("lzw: invalid code")break } .last, .hi = , .hi+1if .hi >= .overflow {if .hi > .overflow {panic("unreachable") }if .width == maxWidth { .last = decoderInvalidCode// Undo the d.hi++ a few lines above, so that (1) we maintain // the invariant that d.hi < d.overflow, and (2) d.hi does not // eventually overflow a uint16. .hi-- } else { .width++ .overflow = 1 << .width } }if .o >= flushBuffer {break } }// Flush pending output. .toRead = .output[:.o] .o = 0}var errClosed = errors.New("lzw: reader/writer is closed")// Close closes the [Reader] and returns an error for any future read operation.// It does not close the underlying [io.Reader].func ( *Reader) () error { .err = errClosed// in case any Reads come alongreturnnil}// Reset clears the [Reader]'s state and allows it to be reused again// as a new [Reader].func ( *Reader) ( io.Reader, Order, int) { * = Reader{} .init(, , )}// NewReader creates a new [io.ReadCloser].// Reads from the returned [io.ReadCloser] read and decompress data from r.// If r does not also implement [io.ByteReader],// the decompressor may read more data than necessary from r.// It is the caller's responsibility to call Close on the ReadCloser when// finished reading.// The number of bits to use for literal codes, litWidth, must be in the// range [2,8] and is typically 8. It must equal the litWidth// used during compression.//// It is guaranteed that the underlying type of the returned [io.ReadCloser]// is a *[Reader].func ( io.Reader, Order, int) io.ReadCloser {returnnewReader(, , )}func newReader( io.Reader, Order, int) *Reader { := new(Reader) .init(, , )return}func ( *Reader) ( io.Reader, Order, int) {switch {caseLSB: .read = (*Reader).readLSBcaseMSB: .read = (*Reader).readMSBdefault: .err = errors.New("lzw: unknown order")return }if < 2 || 8 < { .err = fmt.Errorf("lzw: litWidth %d out of range", )return } , := .(io.ByteReader)if ! && != nil { = bufio.NewReader() } .r = .litWidth = .width = 1 + uint() .clear = uint16(1) << uint() .eof, .hi = .clear+1, .clear+1 .overflow = uint16(1) << .width .last = decoderInvalidCode}
The pages are generated with Goldsv0.7.9-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.