windows-nt/Source/XPSP1/NT/termsrv/remdsk/rds/as/h/bcd.h
2020-09-26 16:20:57 +08:00

416 lines
12 KiB
C

//
// BCD.H
// Bitmap Compression & Decompression
//
// Copyright (c) Microsoft 1997-
//
#ifndef _H_BCD
#define _H_BCD
#define BCD_MATCHCOUNT 8192
#define BCD_NORMALSIZE 65000
#define BCD_XORSIZE 65000
//
// VERSION 2 RLE codes
//
//
// The following codes fill a full single byte address space. The approach
// is to use the high order bits to identify the code type and the low
// order bits to encode the length of the associated run. There are two
// forms of order
// - regular orders which have a 5 bit length field (31 bytes of data)
// - "lite" orders with a 4 bit length
//
// A value of 0 in the length field indicates an extended length, where
// the following byte contains the length of the data. There is also a
// "mega mega" form which has a two byte length field. (See end of
// codespace of the codes that define the megamega form).
//
// A set of codes at the high end of the address space is used to encode
// commonly occuring short sequences, in particular
// - certain single byte FGBG codings
// - single bytes of BLACK and WHITE
//
//
// SUMMARY
// *******
// 7 6 5 4 3 2 1 0 76543210 76543210 76543210
//
// MEGA_BG_RUN 0 0 0 0 0 0 0 0 <length>
//
// BG_RUN 0 0 0 <length->
//
// MEGA_FG_RUN 0 0 1 0 0 0 0 0 <length>
//
// FG_RUN 0 0 1 <length->
//
// MEGA_FG_BG_IMAGE 0 1 0 0 0 0 0 0 <length> <-data-> ...
//
// FG_BG_IMAGE 0 1 0 <length-> <-data-> ...
//
// MEGA_COLOR_RUN 0 1 1 0 0 0 0 0 <length> <-color>
//
// COLOR_RUN 0 1 1 <length-> <color->
//
// MEGA_COLOR_IMAGE 1 0 0 0 0 0 0 0 <length> <-data-> ...
//
// COLOR_IMAGE 1 0 0 <length-> <-data-> ...
//
// MEGA_PACKED_CLR_IMG 1 0 1 0 0 0 0 0 <length> <-data-> ...
//
// PACKED COLOR IMAGE 1 0 1 <length-> <-data-> ...
//
// SET_FG_MEGA_FG_RUN 1 1 0 0 0 0 0 0 <length> <-color>
//
// SET_FG_FG_RUN 1 1 0 0 <-len-> <color->
//
// SET_FG_MEGA_FG_BG 1 1 0 1 0 0 0 0 <length> <-color> <-data-> ...
//
// SET_FG_FG_BG 1 1 0 1 <-len-> <color-> <-data-> ...
//
// MEGA_DITHERED_RUN 1 1 1 0 0 0 0 0 <length> <-data-> <-data->
//
// DITHERED_RUN 1 1 1 0 <-len-> <-data-> <-data->
//
// MEGA_MEGA_BG_RUN 1 1 1 1 0 0 0 0
//
// MEGA_MEGA_FG_RUN 1 1 1 1 0 0 0 1
//
// MEGA_MEGA_FGBG 1 1 1 1 0 0 1 0
//
// MEGA_MEGA_COLOR_RUN 1 1 1 1 0 0 1 1
//
// MEGA_MEGA_CLR_IMG 1 1 1 1 0 1 0 0
//
// MEGA_MEGA_PACKED_CLR 1 1 1 1 0 1 0 1
//
// MEGA_MEGA_SET_FG_RUN 1 1 1 1 0 1 1 0
//
// MEGA_MEGA_SET_FGBG 1 1 1 1 0 1 1 1
//
// MEGA_MEGA_DITHER 1 1 1 1 1 0 0 0
//
// Special FGBG code 1 1 1 1 1 1 0 0 1 FGBG code 0x03 = 11000000
// (Note that 0x01 will generally handled by the single pel insertion code)
//
// Special FBBG code 2 1 1 1 1 1 0 1 0 FGBG code 0x05 = 10100000
//
// Special FBBG code 3 1 1 1 1 1 0 1 1 FGBG code 0x07 = 11100000
//
// Special FBBG code 4 1 1 1 1 1 1 0 0 FGBG code 0x0F = 11110000
//
// BLACK 1 1 1 1 1 1 0 1
//
// WHITE 1 1 1 1 1 1 1 0
//
// START_LOSSY 1 1 1 1 1 1 1 1
//
//
//
// GENERAL NOTES
//
//
// - For MEGA runs the length encoded is the length of the run minus the
// maximum length of the non-mega form.
// In the mega-mega form we encode the plain 16 bit length, to keep
// encoding/deconding simple.
//
// - The sequence BG_RUN,BG_RUN is not exactly what it appears. We
// use the fact that this is not generated in normal encoding to
// encode <n background><1 foreground><n background>. The same pel
// insertion convention applies to any combination of MEGA_BG run and
// BG_RUN
//
// - A packed image is encoded when we find that all the color fields in a
// run have 0 in the high order nibble. We do not currently use this code
// for 8 bit compression, but it is supported by the V2 decoder.
//
// - The set fg color code (Used to exist in V1) has been retired in favor
// of separate commands for those codes that may embed a color. Generally
// This saves one byte for every foreground color transition for 8bpp.
//
// - The color run code is new for V2. It indicates a color run where the
// XOR is not performed. This applies to, for example, the line of bits
// immediately below a text line. (There is no special case for runs of
// the bg color - these are treated as any other color run.)
//
// - Observation shows a high occurrence of BG runs split by single FGBG
// codes. In decreasing probability these are 3,5,7,9,f,11,1f,3f (1 is
// handled by the implicit BG run break). Save 1 byte by encoding as
// single codes
//
// - There is a relatively high occurrence of single pel color codes ff and
// 00. Save 1 byte by encoding as special characters
//
// - The length in a FGBG run is slightly strange. Because they generally
// occur in multiples of 8 bytes we get a big saving if we encode the
// length of a short run as length/8. However, for those special
// cases where the length is not a multiple of 8 we encode a long run.
// Therefore the long form can only cover the range 1-256 bytes.
// beyond that we use the mega-mega form.
//
//
// DETAILS OF COMPRESSION CODES
//
//
// BG_RUN
//
// Represents a background run (black:0) of the specified length.
//
//
//
// FG_BG_IMAGE/SET_FG_FG_BG_IMAGE
//
// Represents a binary image containing only the current foreground(1) and
// background(0) colors.
//
//
//
// FG_RUN/SET_FG_FG_RUN
//
// Represents a continuous foreground run of the specified length.
// The foreground color is white by default, and is changed by the
// SET_FG_FG_RUN version of this code.
//
//
//
// DITHERED_RUN
//
// Represents a run of alternating colors of the specified length.
//
//
//
// COLOR_IMAGE
//
// Represents a color image of the specified length. No XOR is performed.
// This data is uncompressed, so we hope that we won't see
// many of these codes!
//
//
//
// COLOR_RUN
//
// Represents a color run of the specified length. No XOR is performed.
// Since the color is not XORed, it is unlikely to match the running
// foreground color information. Therefore this code always carries a
// color byte and there is no SET_FG_COLOR_RUN form of the code.
//
//
//
// PACKED_COLOR_IMAGE
//
// Represents a color image of the specified length, with pairs of colors
// packed into a single byte. (This can only be done when the color info
// is zero in the high order nibble.)
//
//
//
// START_LOSSY
//
// Informs the decoder that lossy mode has been established and any of the
// following color runs will need pixel doubling performing.
// RLE decoding will remain in this mode until the end of this block
//
//
#define CODE_MASK 0xE0
#define CODE_MASK_LITE 0xF0
#define CODE_BG_RUN 0x00 // 20
#define CODE_FG_RUN 0x20 // 20
#define CODE_FG_BG_IMAGE 0x40 // 20
#define CODE_COLOR_RUN 0x60 // 20
#define CODE_COLOR_IMAGE 0x80 // 20
#define CODE_PACKED_COLOR_IMAGE 0xA0 // 20
#define CODE_SET_FG_FG_RUN 0xC0 // 10
#define CODE_SET_FG_FG_BG 0xD0 // 10
#define CODE_DITHERED_RUN 0xE0 // 10
#define CODE_MEGA_MEGA_BG_RUN 0xF0
#define CODE_MEGA_MEGA_FG_RUN 0xF1
#define CODE_MEGA_MEGA_FGBG 0xF2
#define CODE_MEGA_MEGA_COLOR_RUN 0xF3
#define CODE_MEGA_MEGA_CLR_IMG 0xF4
#define CODE_MEGA_MEGA_PACKED_CLR 0xF5
#define CODE_MEGA_MEGA_SET_FG_RUN 0xF6
#define CODE_MEGA_MEGA_SET_FGBG 0xF7
#define CODE_MEGA_MEGA_DITHER 0xF8
#define CODE_SPECIAL_FGBG_1 0xF9
#define CODE_SPECIAL_FGBG_2 0xFA
#define CODE_SPECIAL_FGBG_3 0xFB
#define CODE_SPECIAL_FGBG_4 0xFC
#define CODE_WHITE 0xFD
#define CODE_BLACK 0xFE
#define CODE_START_LOSSY 0xFF
#define MAX_LENGTH_ORDER 31
#define MAX_LENGTH_LONG_ORDER 287
#define MAX_LENGTH_ORDER_LITE 15
#define MAX_LENGTH_LONG_ORDER_LITE 271
#define MAX_LENGTH_FGBG_ORDER (31*8)
#define MAX_LENGTH_FGBG_ORDER_LITE (15*8)
#define MAX_LENGTH_LONG_FGBG_ORDER 255
//
// The special FGBG codes that correspond to codes F0-F7
//
#define SPECIAL_FGBG_CODE_1 0x03
#define SPECIAL_FGBG_CODE_2 0x05
#define SPECIAL_FGBG_CODE_3 0x07
#define SPECIAL_FGBG_CODE_4 0x0F
//
// Run types as stored in the run index array
//
#define RUN_BG 1
#define RUN_BG_PEL 2
#define RUN_FG 3
#define RUN_COLOR 4
#define RUN_DITHER 5
#define IMAGE_FGBG 6
#define IMAGE_COLOR 7
#define IMAGE_LOSSY_ODD 8
//
// The following structure contains the results of our intermediate scan of
// the buffer. The offset field contains the expected offset into the
// target buffer following decompression of the associated order and is
// used for self-diagnosis.
//
typedef struct
{
WORD length;
BYTE type;
BYTE fgChar;
}
MATCH;
//
// Function Prototypes
//
// Note that the function compresses the whole bitmap in one call. However
// it performs two cycles internally, once for the first line and once for
// all subsequent lines. pelsPerLine (the number of pels on a row) MUST be
// supplied.
//
// The paremeters should be obvious, save
//
// pLossy = pointer to flag indicating we maydiscard part of incompressible
// data
//
// When lossy compression is enabled any color run carries only half the
// pels and they must be doubled up. (Also the encoder replaces color on
// alternate lines with BG_RUN thus giving a fourfold reduction in the
// data, but the decoder does not need any special code to handle this).
//
// The encoder may decide not to honor the lossy request because the data
// is highly compressible anyway. If it determines this then the lossy
// flag is reset so that the caller may determine whether a subsequent
// non-lossy transmission is required or not.
//
//
//
// Unpack4bpp
//
// Convert a 4bpp bitmap into an 8bpp one
//
void Unpack4bpp(LPBYTE destbuf,
LPBYTE srcbuf,
UINT srclen);
//
// Pack4bpp
//
// Convert an 8bpp bitmap back to 4bpp
//
void Pack4bpp(LPBYTE destbuf,
LPBYTE srcbuf,
UINT srclen);
//
// XORBuffer
//
// Create an XOR image of the input bitmap
//
void XORBuffer(LPBYTE destbuf, LPBYTE srcbuf, UINT srclen, int rowDelta);
//
// CompressV2Int
//
// Internal compresssion function
//
// The work buffer addresses are moved onto the stack, thus eliminating any
// need to use DS to address the default data segment. This allows the
// compiler to perform more general optimizations.
//
UINT CompressV2Int(LPBYTE pSrc,
LPBYTE pDst,
UINT numPels,
UINT bpp,
UINT rowDelta,
UINT dstBufferSize,
LPBOOL pLossy,
LPBYTE nrmbuf,
LPBYTE xorbuf,
MATCH FAR *match);
UINT DecompressV2Int(LPBYTE pSrc,
LPBYTE pDst,
UINT bytes,
UINT bpp,
UINT rowDelta,
LPBYTE nrmbuf);
//
// The Compressed Data header structure.
//
// Rather than add a field to indicate V1 vs V2 compression we use the
// fact that V2 compression treats all the bitmap as main body and sets
// the first row size to zero to distinguish them. I hesitate to do this
// but any bandwidth saving is important.
//
typedef struct _CD_HEADER
{
TSHR_UINT16 cbCompFirstRowSize;
TSHR_UINT16 cbCompMainBodySize;
TSHR_UINT16 cbScanWidth;
TSHR_UINT16 cbUncompressedSize;
} CD_HEADER;
typedef CD_HEADER *PCD_HEADER;
#define IsV2CompressedDataHeader(p) ((p)->cbCompFirstRowSize == 0)
#define SetV2CompressedDataHeader(p) ((p)->cbCompFirstRowSize = 0)
//
// Types of bitmap compression.
//
#ifdef _DEBUG // for assertion
#define RLE_V1 1
#endif
#define RLE_V2 2
//
//
// PROTOTYPES
//
//
#endif // _H_BCD