/**************************************************************************** CCITT.C $Log: S:\products\msprods\oiwh\display\ccitt.c_v $ * * Rev 1.48 03 Jun 1996 10:33:32 BEG06016 * Made CCITT decompression handle bad data a little better. * * Rev 1.48 03 Jun 1996 10:32:04 BEG06016 * Made CCITT decompression handle bad data a little better. * * Rev 1.47 01 May 1996 08:42:28 BEG06016 * Fixed a typo. * * Rev 1.46 30 Apr 1996 10:37:26 BEG06016 * Deleted all error checking for G3 1D decompression. * This was commented out for Wes at Microsoft who insists on writing bad data * out to the file. * Wes says that if the viewer sees invalid data, then it can either pad with zeros, * or copy the previous line to the bad line, or leave the garbage data in tact. * This decompression engine will leave the data in tact, resulting in the user * either seeing the correct data, or garbage (which will hopefully let them know * that there is a problem). * I realize that this makes us no longer TIFF compliant (Version 6, page 44 paragraph 4), * but there is nothing we can do about that within Wes's limitations. * * Rev 1.45 24 Apr 1996 14:27:24 BEG06016 * Added horizontal differencing. * * Rev 1.44 19 Apr 1996 09:00:44 BEG06016 * Added CheckError2 for error handling. * * Rev 1.43 18 Apr 1996 14:45:02 BEG06016 * Added CheckError2 for error handling. * * Rev 1.42 16 Apr 1996 11:34:26 BEG06016 * Enlarged the allowable EOL size. * * Rev 1.41 14 Mar 1996 10:26:44 BEG06016 * Sped up 2D, G3T4 decompression. * * Rev 1.40 14 Mar 1996 09:49:20 BEG06016 * Sped up 1D decompression. * * Rev 1.39 12 Mar 1996 11:18:52 BEG06016 * Sped up BW decompression. * * Rev 1.38 28 Feb 1996 08:17:40 BEG06016 * Fixed saving of semi-valid compression types. * * Rev 1.37 26 Feb 1996 15:13:28 BEG06016 * Overrode user's flags when overriding their compression type * from G32D to G42D. * * Rev 1.36 26 Feb 1996 10:11:42 BEG06016 * Made a temporary fix for LZW that disables Reverse bits of * expanded data for decompression. * * Rev 1.35 26 Feb 1996 09:19:34 BEG06016 * Fixed some compression problems. * * Rev 1.34 26 Feb 1996 06:45:12 BEG06016 * Reduced safety margin on 'end of buffer' detection to better * allow for bad heights. * * Rev 1.33 26 Feb 1996 06:40:32 BEG06016 * Fixed signed/unsigned mismatch. * ****************************************************************************/ #include "privdisp.h" // CODE_WORD_BITS = the number of bits in uCodeWord that are nsed. // CODE_WORD_SHIFT = ALWAYS 8 less than CODE_WORD_BITS. It is nsed for shifting the data and comparing. #define CODE_WORD_BITS 32 #define CODE_WORD_SHIFT 24 #define CODE_WORD_BIT_MASK 0x80000000 int nWRunLengthToTermCode[64] ={ 0x3500, 0x1c00, 0x7000, 0x8000, 0xb000, 0xc000, 0xe000, 0xf000, 0x9800, 0xa000, 0x3800, 0x4000, 0x2000, 0x0c00, 0xd000, 0xd400, 0xa800, 0xac00, 0x4e00, 0x1800, 0x1000, 0x2e00, 0x0600, 0x0800, 0x5000, 0x5600, 0x2600, 0x4800, 0x3000, 0x0200, 0x0300, 0x1a00, 0x1b00, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, 0x2800, 0x2900, 0x2a00, 0x2b00, 0x2c00, 0x2d00, 0x0400, 0x0500, 0x0a00, 0x0b00, 0x5200, 0x5300, 0x5400, 0x5500, 0x2400, 0x2500, 0x5800, 0x5900, 0x5a00, 0x5b00, 0x4a00, 0x4b00, 0x3200, 0x3300, 0x3400}; /* int nWRunLengthToMakeUpCodeL[41] ={ 0x0000, 0xd800, 0x9000, 0x5c00, 0x6e00, 0x3600, 0x3700, 0x6400, 0x6500, 0x6800, 0x6700, 0x6600, 0x6680, 0x6900, 0x6980, 0x6a00, 0x6a80, 0x6b00, 0x6b80, 0x6c00, 0x6c80, 0x6d00, 0x6d80, 0x4c00, 0x4c80, 0x4d00, 0x6000, 0x4d80, 0x0100, 0x0180, 0x01a0, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x01c0, 0x01d0, 0x01e0, 0x01f0}; */ int nWRunLengthToMakeUpCodeR[41] ={ 0x0000, 0x001b, 0x0012, 0x0017, 0x0037, 0x0036, 0x0037, 0x0064, 0x0065, 0x0068, 0x0067, 0x00cc, 0x00cd, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x0098, 0x0099, 0x009a, 0x0018, 0x009b, 0x0008, 0x000c, 0x000d, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x001c, 0x001d, 0x001e, 0x001f}; int nWRunLengthToMakeUpCodeLength[41] ={ 0, 5, 5, 6, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 6, 9, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}; /* int nBRunLengthToMakeUpCodeL[41] ={ 0x0000, 0x03c0, 0x0c80, 0x0c90, 0x05b0, 0x0330, 0x0340, 0x0350, 0x0360, 0x0368, 0x0250, 0x0258, 0x0260, 0x0268, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8, 0x0290, 0x0298, 0x02a0, 0x02a8, 0x02d0, 0x02d8, 0x0320, 0x0328, 0x0100, 0x0180, 0x01a0, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x01c0, 0x01d0, 0x01e0, 0x01f0}; */ int nBRunLengthToMakeUpCodeR[41] ={ 0x0000, 0x000f, 0x00c8, 0x00c9, 0x005b, 0x0033, 0x0034, 0x0035, 0x006c, 0x006d, 0x004a, 0x004b, 0x004c, 0x004d, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0052, 0x0053, 0x0054, 0x0055, 0x005a, 0x005b, 0x0064, 0x0065, 0x0008, 0x000c, 0x000d, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x001c, 0x001d, 0x001e, 0x001f}; int nBRunLengthToMakeUpCodeLength[41] ={ 0, 10, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}; int nWRunLengthToTermCodeR[64] ={ 0x0035, 0x0007, 0x0007, 0x0008, 0x000b, 0x000c, 0x000e, 0x000f, 0x0013, 0x0014, 0x0007, 0x0008, 0x0008, 0x0003, 0x0034, 0x0035, 0x002a, 0x002b, 0x0027, 0x000c, 0x0008, 0x0017, 0x0003, 0x0004, 0x0028, 0x002b, 0x0013, 0x0024, 0x0018, 0x0002, 0x0003, 0x001a, 0x001b, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x0004, 0x0005, 0x000a, 0x000b, 0x0052, 0x0053, 0x0054, 0x0055, 0x0024, 0x0025, 0x0058, 0x0059, 0x005a, 0x005b, 0x004a, 0x004b, 0x0032, 0x0033, 0x0034}; int nWRunLengthToTermCodeLength[64] ={ 8, 6, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; int nBRunLengthToTermCodeR[64] ={ 0x0037, 0x0002, 0x0003, 0x0002, 0x0003, 0x0003, 0x0002, 0x0003, 0x0005, 0x0004, 0x0004, 0x0005, 0x0007, 0x0004, 0x0007, 0x0018, 0x0017, 0x0018, 0x0008, 0x0067, 0x0068, 0x006c, 0x0037, 0x0028, 0x0017, 0x0018, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x0068, 0x0069, 0x006a, 0x006b, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x006c, 0x006d, 0x00da, 0x00db, 0x0054, 0x0055, 0x0056, 0x0057, 0x0064, 0x0065, 0x0052, 0x0053, 0x0024, 0x0037, 0x0038, 0x0027, 0x0028, 0x0058, 0x0059, 0x002b, 0x002c, 0x005a, 0x0066, 0x0067}; int nBRunLengthToTermCodeLength[64] ={ 10, 3, 2, 2, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}; int nWCodeByte0ToRunLength[256] ={ -4, -4, 29, 30, 45, 46, 22, 22, 23, 23, 47, 48, 13, 13, 13, 13, 20, 20, 33, 34, 35, 36, 37, 38, 19, 19, 31, 32, 1, 1, 1, 1, 12, 12, 12, 12, 53, 54, 26, 26, 39, 40, 41, 42, 43, 44, 21, 21, 28, 28, 61, 62, 63, 0, 320, 384, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 27, 27, 59, 60, -1, -1, 18, 18, 24, 24, 49, 50, 51, 52, 25, 25, 55, 56, 57, 58, 192, 192, 192, 192, 1664,1664,1664,1664, 448, 512, -1, 640, 576, -1, -1, -1, -1, -1, 256, 256, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 128, 128, 128, 128, 128, 128, 128, 128, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 16, 16, 16, 16, 17, 17, 17, 17, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 14, 14, 14, 14, 15, 15, 15, 15, 64, 64, 64, 64, 64, 64, 64, 64, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; int nWCodeByte0ToCodeWordLength[256] ={ 4, 4, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 6, 6, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 7, 7, 8, 8, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 7, 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 8, 8, 1, 1, 7, 7, 7, 7, 8, 8, 8, 8, 7, 7, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 1, 8, 8, 1, 1, 1, 1, 1, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; int nWCodeByte1ToRunLength[256] ={ -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 1472,1536,1600,1728, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 704, 768, -9, -9, -9, -9, 832, 896, 960,1024,1088,1152, 1216,1280,1344,1408, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9}; int nWCodeByte1ToCodeWordLength[256] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int nWCodeByte4ToRunLength[256] ={ -7, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 1792,1792,1984,2048,2112,2176,2240,2304, 1856,1856,1920,1920,2368,2432,2496,2560, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9}; int nWCodeByte4ToCodeWordLength[256] ={ 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int nBCodeByte0ToRunLength[256] ={ -5, -5, -5, -5, 13, -4, -4, 14, 10, 10, 11, 11, -4, -4, 12, 12, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; int nBCodeByte0ToCodeWordLength[256] ={ 5, 5, 5, 5, 8, 4, 4, 8, 7, 7, 7, 7, 4, 4, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; int nBCodeByte4ToRunLength[256] ={ -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 23, 23, 50, 51, 44, 45, 46, 47, 57, 58, 61, 256, 16, 16, 16, 16, 17, 17, 17, 17, 48, 49, 62, 63, 30, 31, 32, 33, 40, 41, 22, 22, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 15, 15, 15, 15, 15, 15, 15, 15, 128, 192, 26, 27, 28, 29, 19, 19, 20, 20, 34, 35, 36, 37, 38, 39, 21, 21, 42, 43, 0, 0, 0, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}; int nBCodeByte4ToCodeWordLength[256] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 7, 7, 8, 8, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int nBCodeByte5ToRunLength[256] ={ -7, -7, -7, -7, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, 1792, 1792, 1792, 1792, 1984, 1984, 2048, 2048, 2112, 2112, 2176, 2176, 2240, 2240, 2304, 2304, 1856, 1856, 1856, 1856, 1920, 1920, 1920, 1920, 2368, 2368, 2432, 2432, 2496, 2496, 2560, 2560, 18, 18, 18, 18, 18, 18, 18, 18, 52, 52, 640, 704, 768, 832, 55, 55, 56, 56, 1280, 1344, 1408, 1472, 59, 59, 60, 60, 1536, 1600, 24, 24, 24, 24, 25, 25, 25, 25, 1664, 1728, 320, 320, 384, 384, 448, 448, 512, 576, 53, 53, 54, 54, 896, 960, 1024, 1088, 1152, 1216, 64, 64, 64, 64, 64, 64, 64, 64, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9}; int nBCodeByte5ToCodeWordLength[256] ={ 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 7, 7, 7, 7, 7, 7, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int nRunLengthTo1Bits[9] ={ 0x000, 0x080, 0x0c0, 0x0e0, 0x0f0, 0x0f8, 0x0fc, 0x0fe, 0x0ff}; int nRunLengthTo0Bits[9] ={ 0x0ff, 0x07f, 0x03f, 0x01f, 0x00f, 0x007, 0x003, 0x001, 0x000}; int nRunLengthTo1BitsR[9] ={ 0x000, 0x001, 0x003, 0x007, 0x00f, 0x01f, 0x03f, 0x07f, 0x0ff}; int nRunLengthTo0BitsR[9] ={ 0x0ff, 0x0fe, 0x0fc, 0x0f8, 0x0f0, 0x0e0, 0x0c0, 0x080, 0x000}; int n2DCodeByteToState[256] ={ 9, -9, -9, -9, 8, 8, 5, 5, 7, 7, 7, 7, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; int nReverseBits[256] ={ 0x000, 0x080, 0x040, 0x0c0, 0x020, 0x0a0, 0x060, 0x0e0, 0x010, 0x090, 0x050, 0x0d0, 0x030, 0x0b0, 0x070, 0x0f0, 0x008, 0x088, 0x048, 0x0c8, 0x028, 0x0a8, 0x068, 0x0e8, 0x018, 0x098, 0x058, 0x0d8, 0x038, 0x0b8, 0x078, 0x0f8, 0x004, 0x084, 0x044, 0x0c4, 0x024, 0x0a4, 0x064, 0x0e4, 0x014, 0x094, 0x054, 0x0d4, 0x034, 0x0b4, 0x074, 0x0f4, 0x00c, 0x08c, 0x04c, 0x0cc, 0x02c, 0x0ac, 0x06c, 0x0ec, 0x01c, 0x09c, 0x05c, 0x0dc, 0x03c, 0x0bc, 0x07c, 0x0fc, 0x002, 0x082, 0x042, 0x0c2, 0x022, 0x0a2, 0x062, 0x0e2, 0x012, 0x092, 0x052, 0x0d2, 0x032, 0x0b2, 0x072, 0x0f2, 0x00a, 0x08a, 0x04a, 0x0ca, 0x02a, 0x0aa, 0x06a, 0x0ea, 0x01a, 0x09a, 0x05a, 0x0da, 0x03a, 0x0ba, 0x07a, 0x0fa, 0x006, 0x086, 0x046, 0x0c6, 0x026, 0x0a6, 0x066, 0x0e6, 0x016, 0x096, 0x056, 0x0d6, 0x036, 0x0b6, 0x076, 0x0f6, 0x00e, 0x08e, 0x04e, 0x0ce, 0x02e, 0x0ae, 0x06e, 0x0ee, 0x01e, 0x09e, 0x05e, 0x0de, 0x03e, 0x0be, 0x07e, 0x0fe, 0x001, 0x081, 0x041, 0x0c1, 0x021, 0x0a1, 0x061, 0x0e1, 0x011, 0x091, 0x051, 0x0d1, 0x031, 0x0b1, 0x071, 0x0f1, 0x009, 0x089, 0x049, 0x0c9, 0x029, 0x0a9, 0x069, 0x0e9, 0x019, 0x099, 0x059, 0x0d9, 0x039, 0x0b9, 0x079, 0x0f9, 0x005, 0x085, 0x045, 0x0c5, 0x025, 0x0a5, 0x065, 0x0e5, 0x015, 0x095, 0x055, 0x0d5, 0x035, 0x0b5, 0x075, 0x0f5, 0x00d, 0x08d, 0x04d, 0x0cd, 0x02d, 0x0ad, 0x06d, 0x0ed, 0x01d, 0x09d, 0x05d, 0x0dd, 0x03d, 0x0bd, 0x07d, 0x0fd, 0x003, 0x083, 0x043, 0x0c3, 0x023, 0x0a3, 0x063, 0x0e3, 0x013, 0x093, 0x053, 0x0d3, 0x033, 0x0b3, 0x073, 0x0f3, 0x00b, 0x08b, 0x04b, 0x0cb, 0x02b, 0x0ab, 0x06b, 0x0eb, 0x01b, 0x09b, 0x05b, 0x0db, 0x03b, 0x0bb, 0x07b, 0x0fb, 0x007, 0x087, 0x047, 0x0c7, 0x027, 0x0a7, 0x067, 0x0e7, 0x017, 0x097, 0x057, 0x0d7, 0x037, 0x0b7, 0x077, 0x0f7, 0x00f, 0x08f, 0x04f, 0x0cf, 0x02f, 0x0af, 0x06f, 0x0ef, 0x01f, 0x09f, 0x05f, 0x0df, 0x03f, 0x0bf, 0x07f, 0x0ff}; int nFirstOneBit[256] ={ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* 0000 0 0000 1 0001 0 0001 1 0010 0 0010 1 0011 0 0011 1 0100 0 0100 1 0101 0 0101 1 0110 0 0110 1 0111 0 0111 1 1000 0 1000 1 1001 0 1001 1 1010 0 1010 1 1011 0 1011 1 1100 0 1100 1 1101 0 1101 1 1110 0 1110 1 1111 0 1111 1 */ /* 00000000 00000001 00000010 00000011 00000100 00000101 00000110 00000111 00001000 00001001 00001010 00001011 00001100 00001101 00001110 00001111 00010000 00010001 00010010 00010011 00010100 00010101 00010110 00010111 00011000 00011001 00011010 00011011 00011100 00011101 00011110 00011111 00100000 00100001 00100010 00100011 00100100 00100101 00100110 00100111 00101000 00101001 00101010 00101011 00101100 00101101 00101110 00101111 00110000 00110001 00110010 00110011 00110100 00110101 00110110 00110111 00111000 00111001 00111010 00111011 00111100 00111101 00111110 00111111 01000000 01000001 01000010 01000011 01000100 01000101 01000110 01000111 01001000 01001001 01001010 01001011 01001100 01001101 01001110 01001111 01010000 01010001 01010010 01010011 01010100 01010101 01010110 01010111 01011000 01011001 01011010 01011011 01011100 01011101 01011110 01011111 01100000 01100001 01100010 01100011 01100100 01100101 01100110 01100111 01101000 01101001 01101010 01101011 01101100 01101101 01101110 01101111 01110000 01110001 01110010 01110011 01110100 01110101 01110110 01110111 01111000 01111001 01111010 01111011 01111100 01111101 01111110 01111111 10000000 10000001 10000010 10000011 10000100 10000101 10000110 10000111 10001000 10001001 10001010 10001011 10001100 10001101 10001110 10001111 10010000 10010001 10010010 10010011 10010100 10010101 10010110 10010111 10011000 10011001 10011010 10011011 10011100 10011101 10011110 10011111 10100000 10100001 10100010 10100011 10100100 10100101 10100110 10100111 10101000 10101001 10101010 10101011 10101100 10101101 10101110 10101111 10110000 10110001 10110010 10110011 10110100 10110101 10110110 10110111 10111000 10111001 10111010 10111011 10111100 10111101 10111110 10111111 11000000 11000001 11000010 11000011 11000100 11000101 11000110 11000111 11001000 11001001 11001010 11001011 11001100 11001101 11001110 11001111 11010000 11010001 11010010 11010011 11010100 11010101 11010110 11010111 11011000 11011001 11011010 11011011 11011100 11011101 11011110 11011111 11100000 11100001 11100010 11100011 11100100 11100101 11100110 11100111 11101000 11101001 11101010 11101011 11101100 11101101 11101110 11101111 11110000 11110001 11110010 11110011 11110100 11110101 11110110 11110111 11111000 11111001 11111010 11111011 11111100 11111101 11111110 11111111 */ /**************************************************************************** FUNCTION: CompressImage PURPOSE: This routine compresses the image. ****************************************************************************/ int WINAPI CompressImage(int nWidthPixels, int nWidthBytes, int nHeight, PBYTE pImageData, int nImageType, PBYTE *ppCompressedBuffer, PINT pnCompressedBufferSize, int nCompressionType, int nFlags){ int nStatus = 0; switch (nCompressionType){ case FIO_0D: /* Uncompressed coding */ CheckError2( Compress0D(nWidthPixels, nHeight, pImageData, ppCompressedBuffer, pnCompressedBufferSize, nFlags)) break; case FIO_1D: /* CCITT Group 3 1d coding */ CheckError2( CompressG31D(nWidthPixels, nHeight, pImageData, ppCompressedBuffer, pnCompressedBufferSize, nFlags)) break; case FIO_2D: /* CCITT Group 4 2d coding */ CheckError2( CompressG42D(nWidthPixels, nHeight, pImageData, ppCompressedBuffer, pnCompressedBufferSize, nFlags)) break; case FIO_PACKED: /* PackBits coding */ CheckError2( CompressPackBits(nWidthPixels, nHeight, pImageData, ppCompressedBuffer, pnCompressedBufferSize, nFlags)) break; case FIO_LZW: /* LZW coding */ CheckError2( CompressLZW(nWidthPixels, nHeight, nWidthBytes, pImageData, nImageType, ppCompressedBuffer, pnCompressedBufferSize, nFlags)) break; case FIO_1D2D: /* CCITT Group 3 2d coding */ default: nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } Exit: return(nStatus); } /**************************************************************************** FUNCTION: DecompressImage PURPOSE: This routine decompresses the image. ****************************************************************************/ int WINAPI DecompressImage(int nWidthPixels, int nWidthBytes, int nHeight, PBYTE pImageData, int nImageType, PBYTE pCompressedBuffer, int nCompressedBufferSize, int nCompressionType, int nFlags){ int nStatus = 0; switch (nCompressionType){ case FIO_0D: /* Uncompressed coding */ CheckError2( Decompress0D(nWidthPixels, nHeight, nWidthBytes, pImageData, pCompressedBuffer, nCompressedBufferSize, nFlags)) break; case FIO_1D: /* CCITT Group 3 1d coding */ CheckError2( DecompressG31D(nWidthPixels, nHeight, nWidthBytes, pImageData, pCompressedBuffer, nCompressedBufferSize, nFlags)) break; case FIO_1D2D: /* CCITT Group 3 2d coding */ CheckError2( DecompressG32D(nWidthPixels, nHeight, nWidthBytes, pImageData, pCompressedBuffer, nCompressedBufferSize, nFlags)) break; case FIO_2D: /* CCITT Group 4 2d coding */ CheckError2( DecompressG42D(nWidthPixels, nHeight, nWidthBytes, pImageData, pCompressedBuffer, nCompressedBufferSize, nFlags)) break; case FIO_PACKED: /* PackBits coding */ if (nStatus = DecompressPackBits(nWidthPixels, nHeight, nWidthBytes, pImageData, pCompressedBuffer, nCompressedBufferSize, nFlags)){ nFlags &= ~COMPRESS_COMPRESSED_IS_LTR; CheckError2( DecompressPackBits(nWidthPixels, nHeight, nWidthBytes, pImageData, pCompressedBuffer, nCompressedBufferSize, nFlags)) } break; case FIO_LZW: /* LZW coding */ CheckError2( DecompressLZW(nWidthPixels, nHeight, nWidthBytes, pImageData, nImageType, pCompressedBuffer, nCompressedBufferSize, nFlags)) break; default: nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } Exit: return(nStatus); } /**************************************************************************** FUNCTION: ReverseBits PURPOSE: This routine reverses the bit orders within the bytes of a buffer. ****************************************************************************/ int WINAPI ReverseBits(PBYTE pBuffer, int nSize){ int nStatus = 0; int nLoop; for (nLoop = nSize >> 4; nLoop; nLoop--){ *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; } for (nLoop = (nSize >> 2) & 3; nLoop; nLoop--){ *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; *(pBuffer++) = nReverseBits[*pBuffer]; } for (nLoop = nSize & 3; nLoop; nLoop--){ *(pBuffer++) = nReverseBits[*pBuffer]; } return(nStatus); } /**************************************************************************** FUNCTION: NegateBits PURPOSE: This routine negates the bits within the bytes of a buffer. ****************************************************************************/ int WINAPI NegateBits(PBYTE pBuffer, int nSize){ int nStatus = 0; int nLoop; PLONG pLong; nLoop = min(nSize, (int)sizeof(LONG) - (((int)pBuffer) & 3 )); nSize -= nLoop; for (; nLoop; nLoop--){ *(pBuffer++) ^= 0x0ff; } pLong = (PLONG) pBuffer; for (nLoop = nSize >> 5; nLoop; nLoop--){ *(pLong++) ^= 0x0ffffffff; *(pLong++) ^= 0x0ffffffff; *(pLong++) ^= 0x0ffffffff; *(pLong++) ^= 0x0ffffffff; *(pLong++) ^= 0x0ffffffff; *(pLong++) ^= 0x0ffffffff; *(pLong++) ^= 0x0ffffffff; *(pLong++) ^= 0x0ffffffff; } for (nLoop = (nSize >> 2) & 7; nLoop; nLoop--){ *(pLong++) ^= 0x0ffffffff; } pBuffer = (PBYTE) pLong; for (nLoop = nSize & 3; nLoop; nLoop--){ *(pBuffer++) ^= 0x0ff; } return(nStatus); } /**************************************************************************** FUNCTION: LineToPackBits PURPOSE: This routine compresses a line of image data using PackBits. ****************************************************************************/ int WINAPI LineToPackBits(PBYTE pImageData, PBYTE *ppCompressedBuffer, int nWidthBytes){ int nStatus = 0; int nLoop; int nByte; PBYTE pCompressedBuffer; int nLoopEnd; pCompressedBuffer = *ppCompressedBuffer; while(nWidthBytes){ nLoopEnd = min(127, nWidthBytes); nByte = pImageData[0]; for (nLoop = 1; nLoop < nLoopEnd; nLoop++){ if (nByte != pImageData[nLoop]){ break; } } if (nLoop > 2){ // We have a run. *(pCompressedBuffer++) = (nLoop - 2) ^ 0x0ff; *(pCompressedBuffer++) = nByte; nWidthBytes -= nLoop; pImageData += nLoop; continue; } // Literal. for (nLoop = 1; nLoop < nLoopEnd; nLoop++){ nByte = pImageData[nLoop]; if ((nByte != pImageData[nLoop + 1]) || (nByte != pImageData[nLoop + 2])){ continue; } break; } nWidthBytes -= nLoop; *(pCompressedBuffer++) = nLoop - 1; for (; nLoop; nLoop--){ *(pCompressedBuffer++) = *(pImageData++); } } *ppCompressedBuffer = pCompressedBuffer; return(nStatus); } /**************************************************************************** FUNCTION: CompressPackBits PURPOSE: This routine compresses the image data using PackBits. ****************************************************************************/ int WINAPI CompressPackBits(int nWidth, int nHeight, PBYTE pImageData, PBYTE *ppCompressedBuffer, PINT pnCompressedBufferSize, int nFlags){ int nStatus = 0; int nLine; int nWidthBytes; PBYTE pCompressedBufferStart; PBYTE pCompressedBuffer; int nCompressedBufferMaxSize; BOOL bReverseImage = FALSE; BOOL bNegateImage = FALSE; nWidthBytes = (nWidth + 7) >> 3; if ((nFlags & COMPRESS_NEGATE_BITS)){ bNegateImage = TRUE; CheckError2( NegateBits(pImageData, nWidthBytes * nHeight)) } if (!(nFlags & COMPRESS_EXPANDED_IS_LTR)){ bReverseImage = TRUE; CheckError2( ReverseBits(pImageData, nWidthBytes * nHeight)) } nCompressedBufferMaxSize = (nHeight * nWidthBytes) << 2; if (!(pCompressedBufferStart = VirtualAlloc(NULL, nCompressedBufferMaxSize, MEM_COMMIT, PAGE_READWRITE))){ nStatus = Error(DISPLAY_CANTALLOC); goto Exit; } pCompressedBuffer = pCompressedBufferStart; for (nLine = 0; nLine < nHeight; nLine++){ CheckError2( LineToPackBits(pImageData + (nLine * nWidthBytes), &pCompressedBuffer, nWidthBytes)) } nCompressedBufferMaxSize = (pCompressedBuffer - pCompressedBufferStart) + 4; // if (nStatus = ReAllocateMemory(nCompressedBufferMaxSize, &pCompressedBufferStart, NO_INIT)){ // goto Exit; // } *ppCompressedBuffer = pCompressedBufferStart; *pnCompressedBufferSize = nCompressedBufferMaxSize - 4; if (!(nFlags & COMPRESS_COMPRESSED_IS_LTR)){ CheckError2( ReverseBits(pCompressedBufferStart, nCompressedBufferMaxSize - 4)) } Exit: if (bReverseImage){ ReverseBits(pImageData, nWidthBytes * nHeight); } if (bNegateImage){ NegateBits(pImageData, nWidthBytes * nHeight); } return(nStatus); } /**************************************************************************** FUNCTION: DecompressPackBits PURPOSE: This routine decompresses the image data using PackBits. ****************************************************************************/ int WINAPI DecompressPackBits(int nWidth, int nHeight, int nWidthBytes, PBYTE pImageData, PBYTE pCompressedBuffer, int nCompressedBufferSize, int nFlags){ int nStatus = 0; int nLine; int nByteIndex; int nCount; int nByte; PBYTE pImageData2; if (!(nFlags & COMPRESS_COMPRESSED_IS_LTR)){ CheckError2( ReverseBits(pCompressedBuffer, nCompressedBufferSize)) } pImageData2 = pImageData; for (nLine = 0; nLine < nHeight; nLine++){ for (nByteIndex = nWidthBytes; nByteIndex > 0;){ nCount = *(pCompressedBuffer++); if (nCount < 128){ // Literal string. nCount++; nByteIndex -= nCount; for (; nCount; nCount--){ *(pImageData2++) = *(pCompressedBuffer++); } }else if (nCount > 128){ // Encoded string. nCount = (nCount ^ 0x0ff) + 2; nByteIndex -= nCount; nByte = *(pCompressedBuffer++); for (; nCount; nCount--){ *(pImageData2++) = nByte; } }else{ // noop. continue; } } if (nByteIndex != 0){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } } if ((nFlags & COMPRESS_NEGATE_BITS)){ CheckError2( NegateBits(pImageData, nWidthBytes * nHeight)) } if (!(nFlags & COMPRESS_EXPANDED_IS_LTR)){ CheckError2( ReverseBits(pImageData, nWidthBytes * nHeight)) } Exit: return(nStatus); } /**************************************************************************** FUNCTION: RunLengthsTo1DLine PURPOSE: This routine compresses the image data using Group 3 1D. ****************************************************************************/ int WINAPI RunLengthsTo1DLine(PINT pnRunLengths, PBYTE *ppCompressedBuffer, PUINT puCodeWord, PINT pnCodeWordBits, int nWidthBytes, int nFlags){ int nStatus = 0; int nRunLengthIndex; int nRunLength; UINT uCodeWord; int nCodeWordBits; int nIndex; PBYTE pCompressedBuffer; uCodeWord = *puCodeWord; nCodeWordBits = *pnCodeWordBits; pCompressedBuffer = *ppCompressedBuffer; // Translate Runlengths into Codewords. // Labels use Prefix = C1D (Compress 1D), Suffix = W or B (White or Black). if (nFlags & COMPRESS_BEGINNING_EOLS){ uCodeWord = (uCodeWord << 12) | 0x01; nCodeWordBits += 12; } if (!pnRunLengths[0]){ uCodeWord = (uCodeWord << 8) | 0x35; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; nRunLengthIndex = 1; goto C1DB; }else{ nRunLengthIndex = 0; } C1DW: while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } if (!(nRunLength = pnRunLengths[nRunLengthIndex++])){ goto C1DDone; } while(nRunLength > 63){ nIndex = min(40, nRunLength >> 6); uCodeWord = (uCodeWord << nWRunLengthToMakeUpCodeLength[nIndex]) | nWRunLengthToMakeUpCodeR[nIndex]; nCodeWordBits += nWRunLengthToMakeUpCodeLength[nIndex]; nRunLength -= nIndex << 6; while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } } uCodeWord = (uCodeWord << nWRunLengthToTermCodeLength[nRunLength]) | nWRunLengthToTermCodeR[nRunLength]; nCodeWordBits += nWRunLengthToTermCodeLength[nRunLength]; C1DB: while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } if (!(nRunLength = pnRunLengths[nRunLengthIndex++])){ goto C1DDone; } while(nRunLength > 63){ nIndex = min(40, nRunLength >> 6); uCodeWord = (uCodeWord << nBRunLengthToMakeUpCodeLength[nIndex]) | nBRunLengthToMakeUpCodeR[nIndex]; nCodeWordBits += nBRunLengthToMakeUpCodeLength[nIndex]; nRunLength -= nIndex << 6; while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } } uCodeWord = (uCodeWord << nBRunLengthToTermCodeLength[nRunLength]) | nBRunLengthToTermCodeR[nRunLength]; nCodeWordBits += nBRunLengthToTermCodeLength[nRunLength]; goto C1DW; C1DDone: if ((nFlags & COMPRESS_BYTE_ALIGN_LINES) && (nFlags & COMPRESS_ENDING_EOLS)){ uCodeWord = (uCodeWord << (24 - nCodeWordBits)) | 0x001; nCodeWordBits = 24; }else if (nFlags & COMPRESS_BYTE_ALIGN_LINES){ // && !bAddEndingEols if (nCodeWordBits){ uCodeWord <<= 8 - nCodeWordBits; nCodeWordBits = 8; } }else if (nFlags & COMPRESS_ENDING_EOLS){ // && !bByteAlignLines uCodeWord = (uCodeWord << 12) | 0x001; nCodeWordBits += 12; } while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } *puCodeWord = uCodeWord; *pnCodeWordBits = nCodeWordBits; *ppCompressedBuffer = pCompressedBuffer; //Exit: return(nStatus); } /**************************************************************************** FUNCTION: RunLengthsTo2DLine PURPOSE: This routine compresses the image data using Group 3 1D. ****************************************************************************/ int WINAPI RunLengthsTo2DLine(PINT pnRunLengths, PINT pnOldRunLengths, PBYTE *ppCompressedBuffer, PUINT puCodeWord, PINT pnCodeWordBits, int nWidthBytes, int nFlags){ int nStatus = 0; UINT uCodeWord; int nCodeWordBits; int nIndex; int nRunLength; int nLoop; PBYTE pCompressedBuffer; int nOldRunLength; int nB1; int nB2; int nOldRunLenthIndex; int nOldRunLenthLastIndex; int nA1; // Run length left till A1. int nA1Index; uCodeWord = *puCodeWord; nCodeWordBits = *pnCodeWordBits; pCompressedBuffer = *ppCompressedBuffer; // Translate Runlengths into Codewords. // Labels use Prefix = C2D (Compress 2D), Suffix = W or B (White or Black). if (nFlags & COMPRESS_BEGINNING_EOLS){ uCodeWord = (uCodeWord << 12) | 0x01; nCodeWordBits += 12; } // Set the Runlength after the last one to 99,999 to force it out of the calculations. // There is no body to this for loop. for (nOldRunLenthLastIndex = 1; pnOldRunLengths[nOldRunLenthLastIndex] && pnOldRunLengths[nOldRunLenthLastIndex] != 99999; nOldRunLenthLastIndex++); pnOldRunLengths[nOldRunLenthLastIndex ] = 99999; pnOldRunLengths[nOldRunLenthLastIndex + 1] = 99999; pnOldRunLengths[nOldRunLenthLastIndex + 2] = 99999; pnOldRunLengths[nOldRunLenthLastIndex + 3] = 99999; nOldRunLength = pnOldRunLengths[0]; nOldRunLenthIndex = 1; nA1 = pnRunLengths[0]; nA1Index = 1; nRunLength = 0; goto C2DStart; C2DNext: while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } if (!nA1){ goto C2DDone; } nOldRunLength -= nRunLength; while(nOldRunLength <= 0){ nOldRunLength += pnOldRunLengths[nOldRunLenthIndex++]; } C2DStart: if ((nOldRunLenthIndex & 1) == (nA1Index & 1)){ nB1 = nOldRunLength; nB2 = nB1 + pnOldRunLengths[nOldRunLenthIndex]; }else{ nB1 = nOldRunLength + pnOldRunLengths[nOldRunLenthIndex]; nB2 = nB1 + pnOldRunLengths[nOldRunLenthIndex + 1]; } switch ((nA1 - nB1) + 3){ case 0: // A1 = B1 - 3. uCodeWord = (uCodeWord << 7) | 0x02; nCodeWordBits += 7; nRunLength = nA1; nA1 = pnRunLengths[nA1Index++]; goto C2DNext; case 1: // A1 = B1 - 2. uCodeWord = (uCodeWord << 6) | 0x02; nCodeWordBits += 6; nRunLength = nA1; nA1 = pnRunLengths[nA1Index++]; goto C2DNext; case 2: // A1 = B1 - 1. uCodeWord = (uCodeWord << 3) | 0x02; nCodeWordBits += 3; nRunLength = nA1; nA1 = pnRunLengths[nA1Index++]; goto C2DNext; case 3: // A1 = B1. uCodeWord = (uCodeWord << 1) | 0x1; nCodeWordBits += 1; nRunLength = nA1; nA1 = pnRunLengths[nA1Index++]; goto C2DNext; case 4: // A1 = B1 + 1. uCodeWord = (uCodeWord << 3) | 0x03; nCodeWordBits += 3; nRunLength = nA1; nA1 = pnRunLengths[nA1Index++]; goto C2DNext; case 5: // A1 = B1 + 2. uCodeWord = (uCodeWord << 6) | 0x03; nCodeWordBits += 6; nRunLength = nA1; nA1 = pnRunLengths[nA1Index++]; goto C2DNext; case 6: // A1 = B1 + 3. uCodeWord = (uCodeWord << 7) | 0x03; nCodeWordBits += 7; nRunLength = nA1; nA1 = pnRunLengths[nA1Index++]; goto C2DNext; default: // Pass or Horz mode. if (nB2 < nA1){ // Check to see if there will be 3 or more passes. if (!(nOldRunLenthIndex & 1)){ nIndex = nOldRunLenthIndex + 1; }else{ nIndex = nOldRunLenthIndex + 2; } nRunLength = nB2; for (nLoop = 0; nLoop < 3 && nRunLength < nA1; nLoop++){ nRunLength += pnOldRunLengths[nIndex++]; nRunLength += pnOldRunLengths[nIndex++]; } if (nLoop < 3){ // Pass mode. uCodeWord = (uCodeWord << 4) | 0x01; nCodeWordBits += 4; nRunLength = nB2; nA1 -= nRunLength; goto C2DNext; } } // Horizontal mode. uCodeWord = (uCodeWord << 3) | 0x001; nCodeWordBits += 3; nRunLength = nA1; if ((nA1Index & 1)){ // nA1 is a white run length; while(nA1 > 63){ nIndex = min(40, nA1 >> 6); uCodeWord = (uCodeWord << nWRunLengthToMakeUpCodeLength[nIndex]) | nWRunLengthToMakeUpCodeR[nIndex]; nCodeWordBits += nWRunLengthToMakeUpCodeLength[nIndex]; nA1 -= nIndex << 6; while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } } uCodeWord = (uCodeWord << nWRunLengthToTermCodeLength[nA1]) | nWRunLengthToTermCodeR[nA1]; nCodeWordBits += nWRunLengthToTermCodeLength[nA1]; while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } nA1 = pnRunLengths[nA1Index++]; nRunLength += nA1; while(nA1 > 63){ nIndex = min(40, nA1 >> 6); uCodeWord = (uCodeWord << nBRunLengthToMakeUpCodeLength[nIndex]) | nBRunLengthToMakeUpCodeR[nIndex]; nCodeWordBits += nBRunLengthToMakeUpCodeLength[nIndex]; nA1 -= nIndex << 6; while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } } uCodeWord = (uCodeWord << nBRunLengthToTermCodeLength[nA1]) | nBRunLengthToTermCodeR[nA1]; nCodeWordBits += nBRunLengthToTermCodeLength[nA1]; nA1 = pnRunLengths[nA1Index++]; goto C2DNext; }else{ // nA1 is a black run length; while(nA1 > 63){ nIndex = min(40, nA1 >> 6); uCodeWord = (uCodeWord << nBRunLengthToMakeUpCodeLength[nIndex]) | nBRunLengthToMakeUpCodeR[nIndex]; nCodeWordBits += nBRunLengthToMakeUpCodeLength[nIndex]; nA1 -= nIndex << 6; while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } } uCodeWord = (uCodeWord << nBRunLengthToTermCodeLength[nA1]) | nBRunLengthToTermCodeR[nA1]; nCodeWordBits += nBRunLengthToTermCodeLength[nA1]; while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } nA1 = pnRunLengths[nA1Index++]; nRunLength += nA1; while(nA1 > 63){ nIndex = min(40, nA1 >> 6); uCodeWord = (uCodeWord << nWRunLengthToMakeUpCodeLength[nIndex]) | nWRunLengthToMakeUpCodeR[nIndex]; nCodeWordBits += nWRunLengthToMakeUpCodeLength[nIndex]; nA1 -= nIndex << 6; while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } } uCodeWord = (uCodeWord << nWRunLengthToTermCodeLength[nA1]) | nWRunLengthToTermCodeR[nA1]; nCodeWordBits += nWRunLengthToTermCodeLength[nA1]; nA1 = pnRunLengths[nA1Index++]; goto C2DNext; } } C2DDone: pnOldRunLengths[nOldRunLenthLastIndex ] = 0; pnOldRunLengths[nOldRunLenthLastIndex + 1] = 0; pnOldRunLengths[nOldRunLenthLastIndex + 2] = 0; pnOldRunLengths[nOldRunLenthLastIndex + 3] = 0; *puCodeWord = uCodeWord; *pnCodeWordBits = nCodeWordBits; *ppCompressedBuffer = pCompressedBuffer; //Exit: return(nStatus); } /**************************************************************************** FUNCTION: Compress0D PURPOSE: This routine compresses the image data using nncompressed data. ****************************************************************************/ int WINAPI Compress0D(int nWidth, int nHeight, PBYTE pImageData, PBYTE *ppCompressedBuffer, PINT pnCompressedBufferSize, int nFlags){ int nStatus = 0; int nWidthBytes; BOOL bReverseImage = FALSE; BOOL bNegateImage = FALSE; nWidthBytes = (nWidth + 7) >> 3; *pnCompressedBufferSize = nWidthBytes * nHeight; if (!(*ppCompressedBuffer = VirtualAlloc(NULL, *pnCompressedBufferSize, MEM_COMMIT, PAGE_READWRITE))){ nStatus = Error(DISPLAY_CANTALLOC); goto Exit; } memcpy(*ppCompressedBuffer, pImageData, *pnCompressedBufferSize); if ((!(nFlags & COMPRESS_EXPANDED_IS_LTR) && (nFlags & COMPRESS_COMPRESSED_IS_LTR)) || ((nFlags & COMPRESS_EXPANDED_IS_LTR) && !(nFlags & COMPRESS_COMPRESSED_IS_LTR))){ CheckError2( ReverseBits(*ppCompressedBuffer, *pnCompressedBufferSize)) } if ((nFlags & COMPRESS_NEGATE_BITS)){ bNegateImage = TRUE; CheckError2( NegateBits(*ppCompressedBuffer, *pnCompressedBufferSize)) } Exit: return(nStatus); } /**************************************************************************** FUNCTION: CompressG31D PURPOSE: This routine compresses the image data using Group 3 1D. ****************************************************************************/ int WINAPI CompressG31D(int nWidth, int nHeight, PBYTE pImageData, PBYTE *ppCompressedBuffer, PINT pnCompressedBufferSize, int nFlags){ int nStatus = 0; int nLine; int nRunLengths[8000]; int nWidthBytes; UINT uCodeWord; int nCodeWordBits; PBYTE pCompressedBufferStart; PBYTE pCompressedBuffer; int nCompressedBufferMaxSize; BOOL bReverseImage = FALSE; BOOL bNegateImage = FALSE; nWidthBytes = (nWidth + 7) >> 3; uCodeWord = 0; nCodeWordBits = 0; if ((nFlags & COMPRESS_NEGATE_BITS)){ bNegateImage = TRUE; CheckError2( NegateBits(pImageData, nWidthBytes * nHeight)) } nCompressedBufferMaxSize = max(10000, (nHeight * nWidthBytes) * 6); if (!(pCompressedBufferStart = VirtualAlloc(NULL, nCompressedBufferMaxSize, MEM_COMMIT, PAGE_READWRITE))){ nStatus = Error(DISPLAY_CANTALLOC); goto Exit; } pCompressedBuffer = pCompressedBufferStart; for (nLine = 0; nLine < nHeight; nLine++){ CheckError2( LineToRunLengths(pImageData + (nLine * nWidthBytes), &nRunLengths[0], nWidth, nWidthBytes, nFlags)) CheckError2( RunLengthsTo1DLine(&nRunLengths[0], &pCompressedBuffer, &uCodeWord, &nCodeWordBits, nWidthBytes, nFlags)) } // Write last piece of data out. while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } if (nCodeWordBits){ *(pCompressedBuffer++) = uCodeWord << (8 - nCodeWordBits); nCodeWordBits = 0; } if ((pCompressedBuffer - pCompressedBufferStart) >= nCompressedBufferMaxSize){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } nCompressedBufferMaxSize = (pCompressedBuffer - pCompressedBufferStart) + 4; // if (nStatus = ReduceMemory(nCompressedBufferMaxSize, &pCompressedBufferStart)){ // goto Exit; // } *ppCompressedBuffer = pCompressedBufferStart; *pnCompressedBufferSize = nCompressedBufferMaxSize - 4; if (!(nFlags & COMPRESS_COMPRESSED_IS_LTR)){ CheckError2( ReverseBits(pCompressedBufferStart, nCompressedBufferMaxSize - 4)) } Exit: if (bNegateImage){ NegateBits(pImageData, nWidthBytes * nHeight); } return(nStatus); } /**************************************************************************** FUNCTION: CompressG42D PURPOSE: This routine compresses the image data using Group 4 2D. ****************************************************************************/ int WINAPI CompressG42D(int nWidth, int nHeight, PBYTE pImageData, PBYTE *ppCompressedBuffer, PINT pnCompressedBufferSize, int nFlags){ int nStatus = 0; int nLine; int nOldRunLengths[8000]; int nRunLengths[8000]; int nWidthBytes; UINT uCodeWord; int nCodeWordBits; int nLoop; PBYTE pCompressedBufferStart; PBYTE pCompressedBuffer; int nCompressedBufferMaxSize; BOOL bReverseImage = FALSE; BOOL bNegateImage = FALSE; nWidthBytes = (nWidth + 7) >> 3; uCodeWord = 0; nCodeWordBits = 0; if ((nFlags & COMPRESS_NEGATE_BITS)){ bNegateImage = TRUE; CheckError2( NegateBits(pImageData, nWidthBytes * nHeight)) } // Init to all white line. nOldRunLengths[0] = nWidth; nOldRunLengths[1] = 0; nCompressedBufferMaxSize = max(10000, (nHeight * nWidthBytes) * 6); if (!(pCompressedBufferStart = VirtualAlloc(NULL, nCompressedBufferMaxSize, MEM_COMMIT, PAGE_READWRITE))){ nStatus = Error(DISPLAY_CANTALLOC); goto Exit; } pCompressedBuffer = pCompressedBufferStart; for (nLine = 0; nLine < nHeight; nLine++){ CheckError2( LineToRunLengths(pImageData + (nLine * nWidthBytes), &nRunLengths[0], nWidth, nWidthBytes, nFlags)) CheckError2( RunLengthsTo2DLine(&nRunLengths[0], &nOldRunLengths[0], &pCompressedBuffer, &uCodeWord, &nCodeWordBits, nWidthBytes, nFlags)) nOldRunLengths[0] = nRunLengths[0]; // The first entry may be 0. for (nLoop = 1; nRunLengths[nLoop]; nLoop++){ nOldRunLengths[nLoop] = nRunLengths[nLoop]; } nOldRunLengths[nLoop++] = 0; nOldRunLengths[nLoop++] = 0; nOldRunLengths[nLoop++] = 0; nOldRunLengths[nLoop] = 0; } uCodeWord = (uCodeWord << 24) | 0x001001; nCodeWordBits += 24; while(nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } if (nCodeWordBits > 0){ *(pCompressedBuffer++) = uCodeWord << (8 - nCodeWordBits); } nCompressedBufferMaxSize = (pCompressedBuffer - pCompressedBufferStart) + 4; // if (nStatus = ReduceMemory(nCompressedBufferMaxSize, &pCompressedBufferStart)){ // goto Exit; // } *ppCompressedBuffer = pCompressedBufferStart; *pnCompressedBufferSize = nCompressedBufferMaxSize - 4; if (!(nFlags & COMPRESS_COMPRESSED_IS_LTR)){ CheckError2( ReverseBits(pCompressedBufferStart, nCompressedBufferMaxSize - 4)) } Exit: if (bNegateImage){ NegateBits(pImageData, nWidthBytes * nHeight); } return(nStatus); } /**************************************************************************** FUNCTION: D1DLineToRunLengths PURPOSE: This routine decompresses the image data using Group 3 1D. ****************************************************************************/ int WINAPI D1DLineToRunLengths(PINT pnRunLengths, PBYTE *ppCompressedBuffer, PUINT puCodeWord, PINT pnCodeWordBits, int nWidth, int nFlags){ int nStatus = 0; int nRunLengthIndex; int nRunLength; UINT uCodeWord; int nCodeWordBits; int nRunLengthTotal; int nCodeWordLength; BOOL bEOLReceived; int nLoop; PBYTE pCompressedBuffer; int nShift; uCodeWord = *puCodeWord; nCodeWordBits = *pnCodeWordBits; nRunLengthTotal = 0; nRunLengthIndex = 0; bEOLReceived = FALSE; pCompressedBuffer = *ppCompressedBuffer; pnRunLengths[0] = 0; // Translate Codewords into Runlengths. // Labels use Prefix = D1D (Decompress 1D), Suffix = W or B (White or Black). while (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } if (!(uCodeWord >> (CODE_WORD_SHIFT - 3))){ // Must have an EOL. // This was commented out for Wes at Microsoft who insists on writing bad data // out to the file. // if (nFlags & COMPRESS_DONT_DELETE_EOLS){ // nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); // goto Exit; // } uCodeWord <<= 11; nCodeWordBits -= 11; uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; for (nLoop = 0; nLoop < 128; nLoop++){ if (!(nShift = nFirstOneBit[uCodeWord >> CODE_WORD_SHIFT])){ break; } uCodeWord <<= nShift; nCodeWordBits -= nShift; if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } } if (!(uCodeWord & CODE_WORD_BIT_MASK)){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } uCodeWord <<= 1; nCodeWordBits -= 1; } while (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } D1DW: do{ nRunLength = nWCodeByte0ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nWCodeByte0ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; if (nRunLength < 0){ if (nRunLength == -1){ nRunLength = nWCodeByte1ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nWCodeByte1ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; // This was commented out for Wes at Microsoft who insists on writing bad data // out to the file. // }else if (nRunLength == -4){ }else{ nRunLength = nWCodeByte4ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nWCodeByte4ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; if (nRunLength < 0){ // This was commented out for Wes at Microsoft who insists on writing bad data // out to the file. // if (nRunLength == -7){ // if (nFlags & COMPRESS_DONT_DELETE_EOLS){ // nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); // goto Exit; // } nRunLength = nWidth - nRunLengthTotal; nRunLengthTotal += nRunLength; pnRunLengths[nRunLengthIndex] += nRunLength; pnRunLengths[++nRunLengthIndex] = 0; nRunLength = 0; bEOLReceived = TRUE; goto D1DDone; } // This was commented out for Wes at Microsoft who insists on writing bad data // out to the file. // }else{ // nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); // goto Exit; } } while (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } nRunLengthTotal += nRunLength; pnRunLengths[nRunLengthIndex] += nRunLength; }while(nRunLength >= 64); pnRunLengths[++nRunLengthIndex] = 0; if (nRunLengthTotal >= nWidth){ goto D1DDone; } //D1DB: do{ nRunLength = nBCodeByte0ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nBCodeByte0ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; if (nRunLength < 0){ if (nRunLength == -4){ nRunLength = nBCodeByte4ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nBCodeByte4ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; // This was commented out for Wes at Microsoft who insists on writing bad data // out to the file. // }else if (nRunLength == -5){ }else{ nRunLength = nBCodeByte5ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nBCodeByte5ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; if (nRunLength < 0){ // This was commented out for Wes at Microsoft who insists on writing bad data // out to the file. // if (nRunLength == -7){ // if (nFlags & COMPRESS_DONT_DELETE_EOLS){ // nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); // goto Exit; // } nRunLength = nWidth - nRunLengthTotal; nRunLengthTotal += nRunLength; pnRunLengths[nRunLengthIndex] += nRunLength; pnRunLengths[++nRunLengthIndex] = 0; nRunLength = 0; bEOLReceived = TRUE; goto D1DDone; } // This was commented out for Wes at Microsoft who insists on writing bad data // out to the file. // }else{ // nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); // goto Exit; } } while (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } nRunLengthTotal += nRunLength; pnRunLengths[nRunLengthIndex] += nRunLength; }while(nRunLength >= 64); pnRunLengths[++nRunLengthIndex] = 0; if (nRunLengthTotal < nWidth){ goto D1DW; } D1DDone: // This was commented out for Wes at Microsoft who insists on writing bad data // out to the file. // Wes says that if the viewer sees invalid data, then it can either pad with zeros, // or copy the previous line to the bad line, or leave the garbage data in tact. // This decompression engine will leave the data in tact, resulting in the user // either seeing the correct data, or garbage (which will hopefully let them know // that there is a problem). // I realize that this makes us no longer TIFF compliant (Version 6, page 44 paragraph 4), // but there is nothing we can do about that within Wes's limitations. // // if (nRunLengthTotal != nWidth){ // nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); // goto Exit; // } if (nFlags & COMPRESS_BYTE_ALIGN_LINES){ nCodeWordLength = nCodeWordBits & 7; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; } pnRunLengths[++nRunLengthIndex] = 0; pnRunLengths[++nRunLengthIndex] = 0; pnRunLengths[++nRunLengthIndex] = 0; pnRunLengths[++nRunLengthIndex] = 0; pnRunLengths[++nRunLengthIndex] = 0; *puCodeWord = uCodeWord; *pnCodeWordBits = nCodeWordBits; *ppCompressedBuffer = pCompressedBuffer; Exit: return(nStatus); } /**************************************************************************** FUNCTION: D2DLineToRunLengths PURPOSE: This routine decompresses the image data using Group 4 2D. ****************************************************************************/ int WINAPI D2DLineToRunLengths(PINT pnRunLengths, PINT pnOldRunLengths, PBYTE *ppCompressedBuffer, PUINT puCodeWord, PINT pnCodeWordBits, int nWidth, int nFlags){ int nStatus = 0; UINT uCodeWord; int nCodeWordBits; BOOL bEOLReceived; int nLoop; int nRunLengthIndex; int nRunLength; int nRunLengthTotal; int nCodeWordLength; int nCodeByte; PBYTE pCompressedBuffer; int nOldRunLength; int nOldRunLenthIndex; int nShift; uCodeWord = *puCodeWord; nCodeWordBits = *pnCodeWordBits; nRunLength = 0; nRunLengthTotal = 0; nRunLengthIndex = 0; bEOLReceived = FALSE; pCompressedBuffer = *ppCompressedBuffer; // Translate Codewords into Runlengths. // Labels use Prefix = D2D (Decompress 2D), Suffix = W or B (White or Black). while (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } if (!(uCodeWord >> (CODE_WORD_SHIFT - 3))){ // Must have an EOL. if (nFlags & COMPRESS_DONT_DELETE_EOLS){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } uCodeWord <<= 11; nCodeWordBits -= 11; uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; for (nLoop = 0; nLoop < 16; nLoop++){ if (!(nShift = nFirstOneBit[uCodeWord >> CODE_WORD_SHIFT])){ break; } uCodeWord <<= nShift; nCodeWordBits -= nShift; if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } } if (!(uCodeWord & CODE_WORD_BIT_MASK)){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } uCodeWord <<= 1; nCodeWordBits -= 1; } nOldRunLength = pnOldRunLengths[0]; nOldRunLenthIndex = 1; pnRunLengths[nRunLengthIndex] = 0; while (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } goto D2DDecodeCodeWord; D2DNextCodeWord: if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } nRunLengthTotal += nRunLength; if (nRunLengthTotal >= nWidth){ if (nRunLengthTotal > nWidth){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } goto D2DDone; } nOldRunLength -= nRunLength; while(nOldRunLength <= 0){ nOldRunLength += pnOldRunLengths[nOldRunLenthIndex++]; } D2DDecodeCodeWord: switch (n2DCodeByteToState[uCodeWord >> CODE_WORD_SHIFT]){ case 0: // Pass. uCodeWord <<= 4; nCodeWordBits -= 4; nRunLength = nOldRunLength + pnOldRunLengths[nOldRunLenthIndex]; if ((nOldRunLenthIndex & 1) == (nRunLengthIndex & 1)){ nRunLength += pnOldRunLengths[nOldRunLenthIndex + 1]; } pnRunLengths[nRunLengthIndex] += nRunLength; goto D2DNextCodeWord; case 1: // Horizontal. uCodeWord <<= 3; nCodeWordBits -= 3; if (!(nRunLengthIndex & 1)){ // White run length. do{ if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } nRunLength = nWCodeByte0ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nWCodeByte0ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; if (nRunLength < 0){ if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } if (nRunLength == -1){ nRunLength = nWCodeByte1ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nWCodeByte1ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; }else if (nRunLength == -4){ nRunLength = nWCodeByte4ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nWCodeByte4ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; }else{ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } if (nRunLength < 0){ if (nRunLength == -7){ if (nFlags & COMPRESS_DONT_DELETE_EOLS){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } pnRunLengths[nRunLengthIndex++] += nWidth - nRunLengthTotal; pnRunLengths[nRunLengthIndex] = 0; goto D2DEOL2; }else{ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } } } pnRunLengths[nRunLengthIndex] += nRunLength; nRunLengthTotal += nRunLength; nOldRunLength -= nRunLength; while(nOldRunLength <= 0){ nOldRunLength += pnOldRunLengths[nOldRunLenthIndex++]; } }while(nRunLength >= 64); nRunLengthIndex++; pnRunLengths[nRunLengthIndex] = 0; // Black run length. do{ if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } nRunLength = nBCodeByte0ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nBCodeByte0ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; if (nRunLength < 0){ if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } if (nRunLength == -4){ nRunLength = nBCodeByte4ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nBCodeByte4ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; }else if (nRunLength == -5){ nRunLength = nBCodeByte5ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nBCodeByte5ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; }else{ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } if (nRunLength < 0){ if (nRunLength == -7){ if (nFlags & COMPRESS_DONT_DELETE_EOLS){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } pnRunLengths[nRunLengthIndex++] += nWidth - nRunLengthTotal; pnRunLengths[nRunLengthIndex] = 0; goto D2DEOL2; }else{ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } } } pnRunLengths[nRunLengthIndex] += nRunLength; nRunLengthTotal += nRunLength; nOldRunLength -= nRunLength; while(nOldRunLength <= 0){ nOldRunLength += pnOldRunLengths[nOldRunLenthIndex++]; } }while(nRunLength >= 64); }else{ // Black run length. do{ if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } nRunLength = nBCodeByte0ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nBCodeByte0ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; if (nRunLength < 0){ if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } if (nRunLength == -4){ nRunLength = nBCodeByte4ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nBCodeByte4ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; }else if (nRunLength == -5){ nRunLength = nBCodeByte5ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nBCodeByte5ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; }else{ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } if (nRunLength < 0){ if (nRunLength == -7){ if (nFlags & COMPRESS_DONT_DELETE_EOLS){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } pnRunLengths[nRunLengthIndex++] += nWidth - nRunLengthTotal; pnRunLengths[nRunLengthIndex] = 0; goto D2DEOL2; }else{ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } } } pnRunLengths[nRunLengthIndex] += nRunLength; nRunLengthTotal += nRunLength; nOldRunLength -= nRunLength; while(nOldRunLength <= 0){ nOldRunLength += pnOldRunLengths[nOldRunLenthIndex++]; } }while(nRunLength >= 64); nRunLengthIndex++; pnRunLengths[nRunLengthIndex] = 0; // White run length. do{ if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } nRunLength = nWCodeByte0ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nWCodeByte0ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; if (nRunLength < 0){ if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } if (nRunLength == -1){ nRunLength = nWCodeByte1ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nWCodeByte1ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; }else if (nRunLength == -4){ nRunLength = nWCodeByte4ToRunLength[uCodeWord >> CODE_WORD_SHIFT]; nCodeWordLength = nWCodeByte4ToCodeWordLength[uCodeWord >> CODE_WORD_SHIFT]; uCodeWord <<= nCodeWordLength; nCodeWordBits -= nCodeWordLength; }else{ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } if (nRunLength < 0){ if (nRunLength == -7){ if (nFlags & COMPRESS_DONT_DELETE_EOLS){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } pnRunLengths[nRunLengthIndex++] += nWidth - nRunLengthTotal; pnRunLengths[nRunLengthIndex] = 0; goto D2DEOL2; }else{ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } } } pnRunLengths[nRunLengthIndex] += nRunLength; nRunLengthTotal += nRunLength; nOldRunLength -= nRunLength; while(nOldRunLength <= 0){ nOldRunLength += pnOldRunLengths[nOldRunLenthIndex++]; } }while(nRunLength >= 64); } nRunLengthIndex++; pnRunLengths[nRunLengthIndex] = 0; nRunLength = 0; goto D2DNextCodeWord; case 2: // A1 = B1. uCodeWord <<= 1; nCodeWordBits -= 1; nRunLength = nOldRunLength; if ((nOldRunLenthIndex & 1) == (nRunLengthIndex & 1)){ nRunLength += pnOldRunLengths[nOldRunLenthIndex]; } pnRunLengths[nRunLengthIndex++] += nRunLength; pnRunLengths[nRunLengthIndex] = 0; goto D2DNextCodeWord; case 3: // A1 = B1 + 1. uCodeWord <<= 3; nCodeWordBits -= 3; nRunLength = nOldRunLength + 1; if ((nOldRunLenthIndex & 1) == (nRunLengthIndex & 1)){ nRunLength += pnOldRunLengths[nOldRunLenthIndex]; } pnRunLengths[nRunLengthIndex++] += nRunLength; pnRunLengths[nRunLengthIndex] = 0; goto D2DNextCodeWord; case 4: // A1 = B1 + 2. uCodeWord <<= 6; nCodeWordBits -= 6; nRunLength = nOldRunLength + 2; if ((nOldRunLenthIndex & 1) == (nRunLengthIndex & 1)){ nRunLength += pnOldRunLengths[nOldRunLenthIndex]; } pnRunLengths[nRunLengthIndex++] += nRunLength; pnRunLengths[nRunLengthIndex] = 0; goto D2DNextCodeWord; case 5: // A1 = B1 + 3. uCodeWord <<= 7; nCodeWordBits -= 7; nRunLength = nOldRunLength + 3; if ((nOldRunLenthIndex & 1) == (nRunLengthIndex & 1)){ nRunLength += pnOldRunLengths[nOldRunLenthIndex]; } pnRunLengths[nRunLengthIndex++] += nRunLength; pnRunLengths[nRunLengthIndex] = 0; goto D2DNextCodeWord; case 6: // A1 = B1 - 1. uCodeWord <<= 3; nCodeWordBits -= 3; nRunLength = nOldRunLength - 1; if ((nOldRunLenthIndex & 1) == (nRunLengthIndex & 1)){ nRunLength += pnOldRunLengths[nOldRunLenthIndex]; } pnRunLengths[nRunLengthIndex++] += nRunLength; pnRunLengths[nRunLengthIndex] = 0; goto D2DNextCodeWord; case 7: // A1 = B1 - 2. uCodeWord <<= 6; nCodeWordBits -= 6; nRunLength = nOldRunLength - 2; if ((nOldRunLenthIndex & 1) == (nRunLengthIndex & 1)){ nRunLength += pnOldRunLengths[nOldRunLenthIndex]; } pnRunLengths[nRunLengthIndex++] += nRunLength; pnRunLengths[nRunLengthIndex] = 0; goto D2DNextCodeWord; case 8: // A1 = B1 - 3. uCodeWord <<= 7; nCodeWordBits -= 7; nRunLength = nOldRunLength - 3; if ((nOldRunLenthIndex & 1) == (nRunLengthIndex & 1)){ nRunLength += pnOldRunLengths[nOldRunLenthIndex]; } pnRunLengths[nRunLengthIndex++] += nRunLength; pnRunLengths[nRunLengthIndex] = 0; goto D2DNextCodeWord; case 9: // EOL uCodeWord <<= 8; nCodeWordBits -= 8; goto D2DEOL; default: // Error. nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } D2DEOL: // The first 8 bits of an EOL have been found. uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; nCodeByte = uCodeWord >> CODE_WORD_SHIFT; if (!((uCodeWord >> (CODE_WORD_SHIFT + 5)))){ // Not enough zeros for an EOL. nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } uCodeWord <<= 3; nCodeWordBits -= 3; D2DEOL2: while (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } for (nLoop = 0; nLoop < 16; nLoop++){ if (!(nShift = nFirstOneBit[uCodeWord >> CODE_WORD_SHIFT])){ break; } uCodeWord <<= nShift; nCodeWordBits -= nShift; if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } } if (!(uCodeWord & CODE_WORD_BIT_MASK)){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } uCodeWord <<= 1; nCodeWordBits -= 1; if (nRunLengthTotal != nWidth){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } bEOLReceived = TRUE; goto D2DDone; D2DDone: pnRunLengths[nRunLengthIndex++] = 0; if (!bEOLReceived && !(nFlags & COMPRESS_DONT_DELETE_EOLS) && !(uCodeWord >> (CODE_WORD_SHIFT - 3))){ // Must have an EOL. uCodeWord <<= 11; nCodeWordBits -= 11; uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; for (nLoop = 0; nLoop < 16; nLoop++){ if (!(nShift = nFirstOneBit[uCodeWord >> CODE_WORD_SHIFT])){ break; } uCodeWord <<= nShift; nCodeWordBits -= nShift; if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } } if (!(uCodeWord & CODE_WORD_BIT_MASK)){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } uCodeWord <<= 1; nCodeWordBits -= 1; } pnRunLengths[++nRunLengthIndex] = 0; pnRunLengths[++nRunLengthIndex] = 0; pnRunLengths[++nRunLengthIndex] = 0; pnRunLengths[++nRunLengthIndex] = 0; pnRunLengths[++nRunLengthIndex] = 0; *puCodeWord = uCodeWord; *pnCodeWordBits = nCodeWordBits; *ppCompressedBuffer = pCompressedBuffer; Exit: return(nStatus); } /**************************************************************************** FUNCTION: RunLengthsToLine PURPOSE: This routine calculates the line of image data from run lengths. ****************************************************************************/ int WINAPI RunLengthsToLine(PBYTE pImageData, PINT pnRunLengths, int nWidthPixels, int nWidthBytes, int nFlags){ int nStatus = 0; int nRunLengthIndex; int nRunLength; int nRLTotal; PBYTE pImageData2; int nBit; nRLTotal = 0; nRunLengthIndex = 0; if (nFlags & COMPRESS_NEGATE_BITS){ // White = 0, Black = 1. if (nFlags & COMPRESS_EXPANDED_IS_LTR){ // Don't reverse the bits. while(nRLTotal < nWidthPixels){ // Ignor white runlengths. nRLTotal += pnRunLengths[nRunLengthIndex++]; // Set black pixels. nRunLength = pnRunLengths[nRunLengthIndex++]; pImageData2 = pImageData + (nRLTotal >> 3); // Do first byte. nBit = nRLTotal & 7; nRLTotal += nRunLength; if (nRunLength <= (8 - nBit)){ *pImageData2 ^= nRunLengthTo1Bits[nRunLength] >> nBit; continue; }else{ *(pImageData2++) ^= 0x0ff >> nBit; nRunLength -= 8 - nBit; } // Do middle bytes. while(nRunLength >= 8){ *(pImageData2++) = 0x0ff; nRunLength -= 8; } // Do last byte. *pImageData2 = nRunLengthTo1Bits[nRunLength]; } }else{ // Reverse the bits. while(nRLTotal < nWidthPixels){ // Ignor white runlengths. nRLTotal += pnRunLengths[nRunLengthIndex++]; // Set black pixels. nRunLength = pnRunLengths[nRunLengthIndex++]; pImageData2 = pImageData + (nRLTotal >> 3); // Do first byte. nBit = nRLTotal & 7; nRLTotal += nRunLength; if (nRunLength <= (8 - nBit)){ *pImageData2 ^= (nRunLengthTo1BitsR[nRunLength] << nBit) & 0x0ff; continue; }else{ *(pImageData2++) ^= 0x0ff >> nBit; nRunLength -= 8 - nBit; } // Do middle bytes. while(nRunLength >= 8){ *(pImageData2++) = 0x0ff; nRunLength -= 8; } // Do last byte. *pImageData2 = nRunLengthTo1BitsR[nRunLength]; } } }else{ // White = 1, Black = 0. if (nFlags & COMPRESS_EXPANDED_IS_LTR){ // Don't reverse the bits. while(nRLTotal < nWidthPixels){ // Ignor white runlengths. nRLTotal += pnRunLengths[nRunLengthIndex++]; // Set black pixels. nRunLength = pnRunLengths[nRunLengthIndex++]; pImageData2 = pImageData + (nRLTotal >> 3); // Do first byte. nBit = nRLTotal & 7; nRLTotal += nRunLength; if (nRunLength <= (8 - nBit)){ *pImageData2 ^= nRunLengthTo1Bits[nRunLength] >> nBit; continue; }else{ *(pImageData2++) ^= 0x0ff >> nBit; nRunLength -= 8 - nBit; } // Do middle bytes. while(nRunLength >= 8){ *(pImageData2++) = 0; nRunLength -= 8; } // Do last byte. *pImageData2 = nRunLengthTo0Bits[nRunLength]; } }else{ // Reverse the bits. while(nRLTotal < nWidthPixels){ // Ignor white runlengths. nRLTotal += pnRunLengths[nRunLengthIndex++]; // Set black pixels. nRunLength = pnRunLengths[nRunLengthIndex++]; pImageData2 = pImageData + (nRLTotal >> 3); // Do first byte. nBit = nRLTotal & 7; nRLTotal += nRunLength; if (nRunLength <= (8 - nBit)){ *pImageData2 ^= (nRunLengthTo1BitsR[nRunLength] << nBit) & 0x0ff; continue; }else{ *(pImageData2++) ^= 0x0ff >> nBit; nRunLength -= 8 - nBit; } // Do middle bytes. while(nRunLength >= 8){ *(pImageData2++) = 0; nRunLength -= 8; } // Do last byte. *pImageData2 = nRunLengthTo0BitsR[nRunLength]; } } } return(nStatus); } /**************************************************************************** FUNCTION: Decompress0D PURPOSE: This routine decompresses the image data using nncompressed data. ****************************************************************************/ int WINAPI Decompress0D(int nWidth, int nHeight, int nWidthBytes, PBYTE pImageData, PBYTE pCompressedBuffer, int nCompressedBufferSize, int nFlags){ int nStatus = 0; if ((!(nFlags & COMPRESS_COMPRESSED_IS_LTR) && (nFlags & COMPRESS_EXPANDED_IS_LTR)) || ((nFlags & COMPRESS_COMPRESSED_IS_LTR) && !(nFlags & COMPRESS_EXPANDED_IS_LTR))){ CheckError2( ReverseBits(pCompressedBuffer, nCompressedBufferSize)) } memcpy(pImageData, pCompressedBuffer, nCompressedBufferSize); if ((nFlags & COMPRESS_NEGATE_BITS)){ CheckError2( NegateBits(pImageData, nWidthBytes * nHeight)) } Exit: return(nStatus); } /**************************************************************************** FUNCTION: DecompressG31D PURPOSE: This routine decompresses the image data using Group 3 1D. ****************************************************************************/ int WINAPI DecompressG31D(int nWidth, int nHeight, int nWidthBytes, PBYTE pImageData, PBYTE pCompressedBuffer, int nCompressedBufferSize, int nFlags){ int nStatus = 0; int nLine; int nRunLengths[20000]; UINT uCodeWord; int nCodeWordBits; PBYTE pCompressedBufferEnd; if (!(nFlags & COMPRESS_COMPRESSED_IS_LTR)){ CheckError2( ReverseBits(pCompressedBuffer, nCompressedBufferSize)) } if (nFlags & COMPRESS_NEGATE_BITS){ memset(pImageData, 0x00, nHeight * nWidthBytes); }else{ memset(pImageData, 0xff, nHeight * nWidthBytes); } pCompressedBufferEnd = pCompressedBuffer + nCompressedBufferSize; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x01; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x01; uCodeWord = 0; nCodeWordBits = 0; for (nLine = 0; nLine < nHeight; nLine++){ if (pCompressedBuffer >= pCompressedBufferEnd){ nRunLengths[0] = nWidth; nRunLengths[1] = 0; }else{ CheckError2( D1DLineToRunLengths(&nRunLengths[0], &pCompressedBuffer, &uCodeWord, &nCodeWordBits, nWidth, nFlags)) } if (nRunLengths[1]){ CheckError2( RunLengthsToLine(pImageData + (nLine * nWidthBytes), &nRunLengths[0], nWidth, nWidthBytes, nFlags)) } } Exit: return(nStatus); } /**************************************************************************** FUNCTION: DecompressG32D PURPOSE: This routine decompresses the image data using Group 3 2D. ****************************************************************************/ int WINAPI DecompressG32D(int nWidth, int nHeight, int nWidthBytes, PBYTE pImageData, PBYTE pCompressedBuffer, int nCompressedBufferSize, int nFlags){ int nStatus = 0; int nLine; int nRunLengths1[20000]; int nRunLengths2[20000]; PINT pnRunLengths; PINT pnOldRunLengths; UINT uCodeWord; int nCodeWordBits; PBYTE pCompressedBufferEnd; BOOL b1D; int nLoop; int nShift; if (!(nFlags & COMPRESS_COMPRESSED_IS_LTR)){ CheckError2( ReverseBits(pCompressedBuffer, nCompressedBufferSize)) } if (nFlags & COMPRESS_NEGATE_BITS){ memset(pImageData, 0x00, nHeight * nWidthBytes); }else{ memset(pImageData, 0xff, nHeight * nWidthBytes); } pCompressedBufferEnd = pCompressedBuffer + nCompressedBufferSize; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x01; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x01; uCodeWord = 0; nCodeWordBits = 0; while (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } nFlags |= COMPRESS_DONT_DELETE_EOLS; b1D = TRUE; for (nLine = 0; nLine < nHeight; nLine++){ if (nLine & 1){ pnRunLengths = &nRunLengths1[0]; pnOldRunLengths = &nRunLengths2[0]; }else{ pnRunLengths = &nRunLengths2[0]; pnOldRunLengths = &nRunLengths1[0]; } if (!(uCodeWord >> (CODE_WORD_SHIFT - 3))){ // Must have an EOL. uCodeWord <<= 11; nCodeWordBits -= 11; uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; for (nLoop = 0; nLoop < 16; nLoop++){ if (!(nShift = nFirstOneBit[uCodeWord >> CODE_WORD_SHIFT])){ break; } uCodeWord <<= nShift; nCodeWordBits -= nShift; if (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } } if (!(uCodeWord & CODE_WORD_BIT_MASK)){ nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } uCodeWord <<= 1; nCodeWordBits -= 1; if (!(uCodeWord & CODE_WORD_BIT_MASK)){ b1D = FALSE; }else{ b1D = TRUE; } uCodeWord <<= 1; nCodeWordBits -= 1; } if (pCompressedBuffer >= pCompressedBufferEnd){ pnRunLengths[0] = nWidth; pnRunLengths[1] = 0; }else{ if (b1D){ CheckError2( D1DLineToRunLengths(pnRunLengths, &pCompressedBuffer, &uCodeWord, &nCodeWordBits, nWidth, nFlags)) }else{ CheckError2( D2DLineToRunLengths(pnRunLengths, pnOldRunLengths, &pCompressedBuffer, &uCodeWord, &nCodeWordBits, nWidth, nFlags)) } } if (pnRunLengths[1]){ CheckError2( RunLengthsToLine(pImageData + (nLine * nWidthBytes), pnRunLengths, nWidth, nWidthBytes, nFlags)) } } Exit: return(nStatus); } /**************************************************************************** FUNCTION: DecompressG42D PURPOSE: This routine decompresses the image data using Group 4 2D. ****************************************************************************/ int WINAPI DecompressG42D(int nWidth, int nHeight, int nWidthBytes, PBYTE pImageData, PBYTE pCompressedBuffer, int nCompressedBufferSize, int nFlags){ int nStatus = 0; int nLine; int nRunLengths1[20000]; int nRunLengths2[20000]; PINT pnRunLengths; PINT pnOldRunLengths; UINT uCodeWord; int nCodeWordBits; PBYTE pCompressedBufferEnd; if (!(nFlags & COMPRESS_COMPRESSED_IS_LTR)){ CheckError2( ReverseBits(pCompressedBuffer, nCompressedBufferSize)) } if (nFlags & COMPRESS_NEGATE_BITS){ memset(pImageData, 0x00, nHeight * nWidthBytes); }else{ memset(pImageData, 0xff, nHeight * nWidthBytes); } pCompressedBufferEnd = pCompressedBuffer + nCompressedBufferSize; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x01; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x01; // Init to all white line. nRunLengths1[0] = nWidth; nRunLengths1[1] = 0; nRunLengths1[2] = 0; nRunLengths1[3] = 0; nRunLengths1[4] = 0; nRunLengths1[5] = 0; uCodeWord = 0; nCodeWordBits = 0; while (nCodeWordBits <= CODE_WORD_SHIFT){ uCodeWord |= *(pCompressedBuffer++) << (CODE_WORD_SHIFT - nCodeWordBits); nCodeWordBits += 8; } for (nLine = 0; nLine < nHeight; nLine++){ if (nLine & 1){ pnRunLengths = &nRunLengths1[0]; pnOldRunLengths = &nRunLengths2[0]; }else{ pnRunLengths = &nRunLengths2[0]; pnOldRunLengths = &nRunLengths1[0]; } if (!(uCodeWord >> (CODE_WORD_SHIFT - 3))){ // EOFB. Fill image with white lines. pnRunLengths[0] = nWidth; pnRunLengths[1] = 0; pnRunLengths[2] = 0; pnRunLengths[3] = 0; pnRunLengths[4] = 0; pnRunLengths[5] = 0; }else{ CheckError2( D2DLineToRunLengths(pnRunLengths, pnOldRunLengths, &pCompressedBuffer, &uCodeWord, &nCodeWordBits, nWidth, nFlags)) } if (pnRunLengths[1]){ CheckError2( RunLengthsToLine(pImageData + (nLine * nWidthBytes), pnRunLengths, nWidth, nWidthBytes, nFlags)) } } // Don't look for EOFB. Some images such as the Teranet images include // extra lines of image data. Exit: return(nStatus); } /**************************************************************************** FUNCTION: CompressLZW PURPOSE: This routine compresses the image data using LZW. ****************************************************************************/ int WINAPI CompressLZW(int nWidth, int nHeight, int nWidthBytes, PBYTE pImageData, int nImageType, PBYTE *ppCompressedBuffer, PINT pnCompressedBufferSize, int nFlags){ int nStatus = 0; typedef struct tagLZWCodeTable{ int nBytePlusCode; // Byte = bits 23-16, Code = bits 11-0 int nNextCode; } LZWCODETABLE; LZWCODETABLE LZWCodeTable[4100]; int nCode; UINT uCodeWord; int nCodeWordBits; PBYTE pCompressedBufferStart; PBYTE pCompressedBuffer; int nCompressedBufferMaxSize; int nTotalBytes; int nCodeSize; int nLastCodeIndex; int nIndex; int nLoop; BOOL bReverseImage = FALSE; BOOL bNegateImage = FALSE; BOOL bHorzPredictImage = FALSE; PBYTE pImageData2; int nLine; int nPixel1; int nPixel2; int nPixel3; int nPrevPixel1; int nPrevPixel2; int nPrevPixel3; if (nFlags & COMPRESS_HORZ_PREDICTOR){ bHorzPredictImage = TRUE; pImageData2 = pImageData; switch (nImageType){ case ITYPE_GRAY4: for (nLine = nHeight; nLine; nLine--){ nPrevPixel1 = 0; for (nLoop = nWidthBytes; nLoop; nLoop--){ nPixel1 = nPrevPixel1 - ((*pImageData2 >> 4) & 0x0f); nPrevPixel1 = ((*pImageData2 >> 4) & 0x0f); nPixel2 = nPrevPixel1 - (*pImageData2 & 0x0f); nPrevPixel1 = (*pImageData2 & 0x0f); *(pImageData2++) = (nPixel1 << 4) | (nPixel2 & 0x0f); } } break; case ITYPE_GRAY8: for (nLine = nHeight; nLine; nLine--){ nPrevPixel1 = 0; for (nLoop = nWidthBytes; nLoop; nLoop--){ nPixel1 = nPrevPixel1 - *pImageData2; nPrevPixel1 = *pImageData2; *(pImageData2++) = nPixel1; } } break; case ITYPE_RGB24: case ITYPE_BGR24: for (nLine = nHeight; nLine; nLine--){ nPrevPixel1 = 0; nPrevPixel2 = 0; nPrevPixel3 = 0; for (nLoop = nWidth; nLoop; nLoop--){ nPixel1 = nPrevPixel1 - *pImageData2; nPrevPixel1 = *pImageData2; *(pImageData2++) = nPixel1; nPixel2 = nPrevPixel2 - *pImageData2; nPrevPixel2 = *pImageData2; *(pImageData2++) = nPixel2; nPixel3 = nPrevPixel3 - *pImageData2; nPrevPixel3 = *pImageData2; *(pImageData2++) = nPixel3; } } break; case ITYPE_BI_LEVEL: case ITYPE_PAL4: case ITYPE_CUSPAL8: case ITYPE_COMPAL8: default: // We can not do horizontal prediction on non-linear data. nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; break; } } // pImageData++; if ((nFlags & COMPRESS_NEGATE_BITS)){ bNegateImage = TRUE; CheckError2( NegateBits(pImageData, nWidthBytes * nHeight)) } if (!(nFlags & COMPRESS_EXPANDED_IS_LTR)){ bReverseImage = TRUE; CheckError2( ReverseBits(pImageData, nWidthBytes * nHeight)) } pImageData2 = pImageData; uCodeWord = 0; nCodeWordBits = 0; nCompressedBufferMaxSize = max(10, (nHeight * nWidthBytes) << 2); if (!(pCompressedBufferStart = VirtualAlloc(NULL, nCompressedBufferMaxSize, MEM_COMMIT, PAGE_READWRITE))){ nStatus = Error(DISPLAY_CANTALLOC); goto Exit; } pCompressedBuffer = pCompressedBufferStart; memset(LZWCodeTable, 0, sizeof(LZWCODETABLE) * 4100); for (nLoop = 0; nLoop < 256; nLoop++){ LZWCodeTable[nLoop].nBytePlusCode = nLoop; } nLastCodeIndex = 258; nCodeSize = 9; nCode = *(pImageData2++); for (nTotalBytes = (nHeight * nWidthBytes) - 1; nTotalBytes; nTotalBytes--){ nCode |= *(pImageData2++) << 16; if ((nIndex = LZWCodeTable[nCode & 0x0ffff].nNextCode)){ for (; nIndex < nLastCodeIndex; nIndex++){ if (LZWCodeTable[nIndex].nBytePlusCode == nCode){ break; } } if (nIndex < nLastCodeIndex){ // Code found. nCode = nIndex; continue; } } // Code not found in table. uCodeWord = (uCodeWord << nCodeSize) | (nCode & 0x0ffff); nCodeWordBits += nCodeSize - 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; if (nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } if (!LZWCodeTable[nCode & 0x0ffff].nNextCode){ LZWCodeTable[nCode & 0x0ffff].nNextCode = nLastCodeIndex; } LZWCodeTable[nLastCodeIndex++].nBytePlusCode = nCode; nCode >>= 16; if (nLastCodeIndex > 511){ if (nLastCodeIndex > 1023){ if (nLastCodeIndex > 2047){ if (nLastCodeIndex > 4093){ if (nTotalBytes > 1){ // Write out last code. uCodeWord = (uCodeWord << 12) | nCode; nCodeWordBits += 4; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; // Write out clear code. uCodeWord = (uCodeWord << 12) | 256; nCodeWordBits += 4; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; if (nCodeWordBits >= 8){ nCodeWordBits -= 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; } // Reset table. memset(&LZWCodeTable[258], 0, sizeof(LZWCODETABLE) * 3842); nLastCodeIndex = 258; nCodeSize = 9; } continue; }else{ nCodeSize = 12; continue; } }else{ nCodeSize = 11; continue; } }else{ nCodeSize = 10; continue; } } continue; } // Write out last code. uCodeWord = (uCodeWord << nCodeSize) | nCode; nCodeWordBits += nCodeSize - 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; if (nLastCodeIndex > 509){ if (nLastCodeIndex > 1021){ if (nLastCodeIndex > 2045){ nCodeSize = 12; }else{ nCodeSize = 11; } }else{ nCodeSize = 10; } } // Write out clear code. uCodeWord = (uCodeWord << nCodeSize) | 256; nCodeWordBits += nCodeSize - 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; if (nLastCodeIndex > 509){ if (nLastCodeIndex > 1021){ if (nLastCodeIndex > 2045){ nCodeSize = 12; }else{ nCodeSize = 11; } }else{ nCodeSize = 10; } } // Write out end of information code. uCodeWord = (uCodeWord << nCodeSize) | 257; nCodeWordBits += nCodeSize - 8; *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; // Write last piece of data out. while(nCodeWordBits > 0){ nCodeWordBits -= 8; if (nCodeWordBits >= 0){ *(pCompressedBuffer++) = uCodeWord >> nCodeWordBits; }else{ *(pCompressedBuffer++) = uCodeWord << -nCodeWordBits; } } nCompressedBufferMaxSize = (pCompressedBuffer - pCompressedBufferStart) + 4; // if (nStatus = ReAllocateMemory(nCompressedBufferMaxSize, &pCompressedBufferStart, NO_INIT)){ // goto Exit; // } *ppCompressedBuffer = pCompressedBufferStart; *pnCompressedBufferSize = nCompressedBufferMaxSize - 4; if (!(nFlags & COMPRESS_COMPRESSED_IS_LTR)){ CheckError2( ReverseBits(pCompressedBufferStart, nCompressedBufferMaxSize - 4)) } Exit: if (bReverseImage){ ReverseBits(pImageData, nWidthBytes * nHeight); } if (bNegateImage){ NegateBits(pImageData, nWidthBytes * nHeight); } if (bHorzPredictImage){ pImageData2 = pImageData; switch (nImageType){ case ITYPE_GRAY4: for (nLine = nHeight; nLine; nLine--){ nPixel2 = 0; for (nLoop = nWidthBytes; nLoop; nLoop--){ nPixel1 = (nPixel2 + ((*pImageData2 >> 4) & 0x0f)) & 0x0f; nPixel2 = (nPixel1 + (*pImageData2 & 0x0f)) & 0x0f; *(pImageData2++) = (nPixel1 << 4) | (nPixel2 & 0x0f); } } break; case ITYPE_GRAY8: for (nLine = nHeight; nLine; nLine--){ nPixel1 = 0; for (nLoop = nWidthBytes; nLoop; nLoop--){ nPixel1 = (nPixel1 + *pImageData2) & 0x0ff; *(pImageData2++) = nPixel1; } } break; case ITYPE_RGB24: case ITYPE_BGR24: for (nLine = nHeight; nLine; nLine--){ nPixel1 = 0; nPixel2 = 0; nPixel3 = 0; for (nLoop = nWidth; nLoop; nLoop--){ nPixel1 = (nPixel1 + *pImageData2) & 0x0ff; *(pImageData2++) = nPixel1; nPixel2 = (nPixel2 + *pImageData2) & 0x0ff; *(pImageData2++) = nPixel2; nPixel3 = (nPixel3 + *pImageData2) & 0x0ff; *(pImageData2++) = nPixel3; } } break; case ITYPE_BI_LEVEL: case ITYPE_PAL4: case ITYPE_CUSPAL8: case ITYPE_COMPAL8: default: // We can not do horizontal prediction on non-linear data. break; } } return(nStatus); } /**************************************************************************** FUNCTION: DecompressLZW PURPOSE: This routine decompresses the image data using LZW. ****************************************************************************/ int WINAPI DecompressLZW(int nWidth, int nHeight, int nWidthBytes, PBYTE pImageData, int nImageType, PBYTE pCompressedBuffer, int nCompressedBufferSize, int nFlags){ int nStatus = 0; typedef struct tagLZWDecodeTable{ int nByte; int nNextCode; } LZWDECODETABLE; LZWDECODETABLE LZWDecodeTable[4100]; int nCode; int nOrginalCode; UINT uCodeWord; int nCodeWordBits; int nTotalBytes; int nCodeSize; int nLastCodeIndex; int nStringIndex; int nLoop; uchar cString[4100]; PBYTE pImageData2; PBYTE pCompressedBufferEnd; int nLine; int nPixel1; int nPixel2; int nPixel3; if (!(nFlags & COMPRESS_COMPRESSED_IS_LTR)){ CheckError2( ReverseBits(pCompressedBuffer, nCompressedBufferSize)) } pCompressedBufferEnd = pCompressedBuffer + nCompressedBufferSize; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x00; *(pCompressedBufferEnd++) = 0x01; pImageData2 = pImageData; for (nLoop = 0; nLoop < 256; nLoop++){ LZWDecodeTable[nLoop].nByte = nLoop; } nLastCodeIndex = 257; nCodeSize = 9; uCodeWord = *(pCompressedBuffer++) << 24; uCodeWord |= *(pCompressedBuffer++) << 16; uCodeWord |= *(pCompressedBuffer++) << 8; uCodeWord |= *(pCompressedBuffer++); nCodeWordBits = 32; nTotalBytes = (nHeight * nWidthBytes) - 1; while(nTotalBytes > 0){ nCode = uCodeWord >> (32 - nCodeSize); nOrginalCode = nCode; nCodeWordBits -= nCodeSize - 8; uCodeWord = (uCodeWord << nCodeSize) | (*(pCompressedBuffer++) << (32 - nCodeWordBits)); if (pCompressedBuffer >= pCompressedBufferEnd){ // We have read too much data. Abort. nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } if (nCodeWordBits <= 24){ nCodeWordBits += 8; uCodeWord |= *(pCompressedBuffer++) << (32 - nCodeWordBits); } if (nCode < 258){ if (nCode > 255){ // Clear code or end of information code. if (nCode = 256){ // Clear code. nLastCodeIndex = 257; nCodeSize = 9; continue; } // End of information. // Since we are still in this loop we haven't gotten all of // our information yet. Therefore this is an error. nStatus = Error(DISPLAY_COMPRESS_BAD_DATA); goto Exit; } } // Normal code. LZWDecodeTable[nLastCodeIndex + 1].nNextCode = nCode; nStringIndex = 0; while(1){ cString[nStringIndex++] = LZWDecodeTable[nCode].nByte; if (nCode < 256){ break; } nCode = LZWDecodeTable[nCode].nNextCode; } nTotalBytes -= nStringIndex; LZWDecodeTable[nLastCodeIndex++].nByte = cString[nStringIndex - 1]; cString[0] = LZWDecodeTable[nOrginalCode].nByte; // Just in case we just changed it. // Reverse the string into the image data. while(nStringIndex){ *(pImageData2++) = cString[--nStringIndex]; } if (nLastCodeIndex > 510){ if (nLastCodeIndex > 1022){ if (nLastCodeIndex > 2046){ nCodeSize = 12; }else{ nCodeSize = 11; } }else{ nCodeSize = 10; } } } if ((nFlags & COMPRESS_NEGATE_BITS)){ CheckError2( NegateBits(pImageData, nWidthBytes * nHeight)) } // if (!(nFlags & COMPRESS_EXPANDED_IS_LTR)){ // if (nStatus = ReverseBits(pImageData, nWidthBytes * nHeight)){ // goto Exit; // } // } if (nFlags & COMPRESS_HORZ_PREDICTOR){ pImageData2 = pImageData; switch (nImageType){ case ITYPE_GRAY4: for (nLine = nHeight; nLine; nLine--){ nPixel2 = 0; for (nLoop = nWidthBytes; nLoop; nLoop--){ nPixel1 = (nPixel2 + ((*pImageData2 >> 4) & 0x0f)) & 0x0f; nPixel2 = (nPixel1 + (*pImageData2 & 0x0f)) & 0x0f; *(pImageData2++) = (nPixel1 << 4) | (nPixel2 & 0x0f); } } break; case ITYPE_GRAY8: for (nLine = nHeight; nLine; nLine--){ nPixel1 = 0; for (nLoop = nWidthBytes; nLoop; nLoop--){ nPixel1 = (nPixel1 + *pImageData2) & 0x0ff; *(pImageData2++) = nPixel1; } } break; case ITYPE_RGB24: case ITYPE_BGR24: for (nLine = nHeight; nLine; nLine--){ nPixel1 = 0; nPixel2 = 0; nPixel3 = 0; for (nLoop = nWidth; nLoop; nLoop--){ nPixel1 = (nPixel1 + *pImageData2) & 0x0ff; *(pImageData2++) = nPixel1; nPixel2 = (nPixel2 + *pImageData2) & 0x0ff; *(pImageData2++) = nPixel2; nPixel3 = (nPixel3 + *pImageData2) & 0x0ff; *(pImageData2++) = nPixel3; } } break; case ITYPE_BI_LEVEL: case ITYPE_PAL4: case ITYPE_CUSPAL8: case ITYPE_COMPAL8: default: // We can not do horizontal prediction on non-linear data. break; } } Exit: return(nStatus); }