func()

in vncclient/encoding.go [881:937]


func (t *TightEncoding) basicCompressionReader(r io.Reader, size int, stream uint8) (out io.Reader, err error) {
	// After the pixel data has been filtered with one of the above three
	// filters, it is compressed using the zlib library. But if the data
	// size after applying the filter but before the compression is less
	// then 12, then the data is sent as is, uncompressed.
	if size < 12 {
		return io.LimitReader(r, int64(size)), nil
	}

	// Four separate zlib streams (0..3) can be used and the
	// decoder should read the actual stream id from the
	// compression-control byte (see [NOTE1]).
	//
	// If the compression is not used, then the pixel data is sent
	// as is, otherwise the data stream looks like this:
	//
	//  +--------------+----------+----------------------------------+
	//  | No. of bytes | Type     | Description                      |
	//  +--------------+----------+----------------------------------+
	//  | 1-3          |          | length in compact representation |
	//  +--------------+----------+----------------------------------+
	//  | length       | U8 array | zlibData                         |
	//  +--------------+----------+----------------------------------+
	length, err := t.readCompactLength(byteIOReader{Reader: r})
	if err != nil {
		return nil, errors.Trace(err)
	}
	t.size += length

	buf := t.streamBufs[stream]
	if t.reset&(1<<stream) != 0 {
		buf.Reset()
	}
	buf.Grow(length)
	if _, err = buf.ReadFrom(io.LimitReader(r, int64(length))); err != nil {
		return nil, errors.Trace(err)
	}

	if t.streams[stream] == nil {
		zr, err := zlib.NewReader(buf)
		if err != nil {
			return nil, errors.Trace(err)
		}
		t.streams[stream] = zr.(readCloseResetter)
	}
	// NOTE1: The decoder must reset the zlib streams before
	// decoding the rectangle, if some of the bits 0, 1, 2 and 3 in
	// the compression-control byte are set to 1. Note that the
	// decoder must reset the indicated zlib streams even if the
	// compression type is FillCompression or JpegCompression.
	if t.reset&(1<<stream) != 0 {
		t.streams[stream].Reset(buf, nil)
		t.reset &^= 1 << stream
	}

	return t.streams[stream], nil
}