//----------------------------------------------------------------------------- // FILE NAME : FUMH.C // FUNCTION : MH Compress and MH2 Compress // AUTHER : 1996.08.08 FPL)Y.YUTANI // NOTE : for Windows NT V4.0 // MODIFY : Reduce data size Oct.31,1996 H.Ishida // MODIFY : for NT.50 MiniDriver Sep.3,1997 H.Ishida(FPL) //----------------------------------------------------------------------------- // COPYRIGHT(C) FUJITSU LIMITED 1996-1997 #include #include "fuxl.h" #include "fumhdef.h" const CODETABLE WhiteMakeUpTable[] = { { 0xd800, 5 }, { 0x9000, 5 }, { 0x5c00, 6 }, { 0x6e00, 7 }, { 0x3600, 8 }, { 0x3700, 8 }, { 0x6400, 8 }, { 0x6500, 8 }, { 0x6800, 8 }, { 0x6700, 8 }, { 0x6600, 9 }, { 0x6680, 9 }, { 0x6900, 9 }, { 0x6980, 9 }, { 0x6a00, 9 }, { 0x6a80, 9 }, { 0x6b00, 9 }, { 0x6b80, 9 }, { 0x6c00, 9 }, { 0x6c80, 9 }, { 0x6d00, 9 }, { 0x6d80, 9 }, { 0x4c00, 9 }, { 0x4c80, 9 }, { 0x4d00, 9 }, { 0x6000, 6 }, { 0x4d80, 9 }, { 0x0100, 11 }, { 0x0180, 11 }, { 0x01a0, 11 }, { 0x0120, 12 }, { 0x0130, 12 }, { 0x0140, 12 }, { 0x0150, 12 }, { 0x0160, 12 }, { 0x0170, 12 }, { 0x01c0, 12 }, { 0x01d0, 12 }, { 0x01e0, 12 }, { 0x01f0, 12 }, { 0x3500, 8 }, { 0x1c00, 6 }, { 0x7000, 4 }, { 0x8000, 4 }, { 0xb000, 4 }, { 0xc000, 4 }, { 0xe000, 4 }, { 0xf000, 4 }, { 0x9800, 5 }, { 0xa000, 5 }, { 0x3800, 5 }, { 0x4000, 5 }, { 0x2000, 6 }, { 0x0c00, 6 }, { 0xd000, 6 }, { 0xd400, 6 }, { 0xa800, 6 }, { 0xac00, 6 }, { 0x4e00, 7 }, { 0x1800, 7 }, { 0x1000, 7 }, { 0x2e00, 7 }, { 0x0600, 7 }, { 0x0800, 7 }, }; const CODETABLE WhiteTerminateTable[] = { { 0x3500, 8 }, { 0x1c00, 6 }, { 0x7000, 4 }, { 0x8000, 4 }, { 0xb000, 4 }, { 0xc000, 4 }, { 0xe000, 4 }, { 0xf000, 4 }, { 0x9800, 5 }, { 0xa000, 5 }, { 0x3800, 5 }, { 0x4000, 5 }, { 0x2000, 6 }, { 0x0c00, 6 }, { 0xd000, 6 }, { 0xd400, 6 }, { 0xa800, 6 }, { 0xac00, 6 }, { 0x4e00, 7 }, { 0x1800, 7 }, { 0x1000, 7 }, { 0x2e00, 7 }, { 0x0600, 7 }, { 0x0800, 7 }, { 0x5000, 7 }, { 0x5600, 7 }, { 0x2600, 7 }, { 0x4800, 7 }, { 0x3000, 7 }, { 0x0200, 8 }, { 0x0300, 8 }, { 0x1a00, 8 }, { 0x1b00, 8 }, { 0x1200, 8 }, { 0x1300, 8 }, { 0x1400, 8 }, { 0x1500, 8 }, { 0x1600, 8 }, { 0x1700, 8 }, { 0x2800, 8 }, { 0x2900, 8 }, { 0x2a00, 8 }, { 0x2b00, 8 }, { 0x2c00, 8 }, { 0x2d00, 8 }, { 0x0400, 8 }, { 0x0500, 8 }, { 0x0a00, 8 }, { 0x0b00, 8 }, { 0x5200, 8 }, { 0x5300, 8 }, { 0x5400, 8 }, { 0x5500, 8 }, { 0x2400, 8 }, { 0x2500, 8 }, { 0x5800, 8 }, { 0x5900, 8 }, { 0x5a00, 8 }, { 0x5b00, 8 }, { 0x4a00, 8 }, { 0x4b00, 8 }, { 0x3200, 8 }, { 0x3300, 8 }, { 0x3400, 8 }, }; const CODETABLE BlackMakeUpTable[] = { { 0x03c0, 10 }, { 0x0c80, 12 }, { 0x0c90, 12 }, { 0x05b0, 12 }, { 0x0330, 12 }, { 0x0340, 12 }, { 0x0350, 12 }, { 0x0360, 13 }, { 0x0368, 13 }, { 0x0250, 13 }, { 0x0258, 13 }, { 0x0260, 13 }, { 0x0268, 13 }, { 0x0390, 13 }, { 0x0398, 13 }, { 0x03a0, 13 }, { 0x03a8, 13 }, { 0x03b0, 13 }, { 0x03b8, 13 }, { 0x0290, 13 }, { 0x0298, 13 }, { 0x02a0, 13 }, { 0x02a8, 13 }, { 0x02d0, 13 }, { 0x02d8, 13 }, { 0x0320, 13 }, { 0x0328, 13 }, { 0x0100, 11 }, { 0x0180, 11 }, { 0x01a0, 11 }, { 0x0120, 12 }, { 0x0130, 12 }, { 0x0140, 12 }, { 0x0150, 12 }, { 0x0160, 12 }, { 0x0170, 12 }, { 0x01c0, 12 }, { 0x01d0, 12 }, { 0x01e0, 12 }, { 0x01f0, 12 }, { 0x0dc0, 10 }, { 0x4000, 3 }, { 0xc000, 2 }, { 0x8000, 2 }, { 0x6000, 3 }, { 0x3000, 4 }, { 0x2000, 4 }, { 0x1800, 5 }, { 0x1400, 6 }, { 0x1000, 6 }, { 0x0800, 7 }, { 0x0a00, 7 }, { 0x0e00, 7 }, { 0x0400, 8 }, { 0x0700, 8 }, { 0x0c00, 9 }, { 0x05c0, 10 }, { 0x0600, 10 }, { 0x0200, 10 }, { 0x0ce0, 11 }, { 0x0d00, 11 }, { 0x0d80, 11 }, { 0x06e0, 11 }, { 0x0500, 11 }, }; const CODETABLE BlackTerminateTable[] = { { 0x0dc0, 10 }, { 0x4000, 3 }, { 0xc000, 2 }, { 0x8000, 2 }, { 0x6000, 3 }, { 0x3000, 4 }, { 0x2000, 4 }, { 0x1800, 5 }, { 0x1400, 6 }, { 0x1000, 6 }, { 0x0800, 7 }, { 0x0a00, 7 }, { 0x0e00, 7 }, { 0x0400, 8 }, { 0x0700, 8 }, { 0x0c00, 9 }, { 0x05c0, 10 }, { 0x0600, 10 }, { 0x0200, 10 }, { 0x0ce0, 11 }, { 0x0d00, 11 }, { 0x0d80, 11 }, { 0x06e0, 11 }, { 0x0500, 11 }, { 0x02e0, 11 }, { 0x0300, 11 }, { 0x0ca0, 12 }, { 0x0cb0, 12 }, { 0x0cc0, 12 }, { 0x0cd0, 12 }, { 0x0680, 12 }, { 0x0690, 12 }, { 0x06a0, 12 }, { 0x06b0, 12 }, { 0x0d20, 12 }, { 0x0d30, 12 }, { 0x0d40, 12 }, { 0x0d50, 12 }, { 0x0d60, 12 }, { 0x0d70, 12 }, { 0x06c0, 12 }, { 0x06d0, 12 }, { 0x0da0, 12 }, { 0x0db0, 12 }, { 0x0540, 12 }, { 0x0550, 12 }, { 0x0560, 12 }, { 0x0570, 12 }, { 0x0640, 12 }, { 0x0650, 12 }, { 0x0520, 12 }, { 0x0530, 12 }, { 0x0240, 12 }, { 0x0370, 12 }, { 0x0380, 12 }, { 0x0270, 12 }, { 0x0280, 12 }, { 0x0580, 12 }, { 0x0590, 12 }, { 0x02b0, 12 }, { 0x02c0, 12 }, { 0x05a0, 12 }, { 0x0660, 12 }, { 0x0670, 12 }, }; //----------------------------------------------------------------------------- // DWORD FjCountBits // BYTE *pTmp Pointer of sources area // DWORD cBitstmp Now bit number from top of sources area // DWORD cBitsMax Last bits number in this line // BOOL hWhite color flag // TRUE : counting white bits // FALSE : counting black bits // Return code : Join same color bits number //----------------------------------------------------------------------------- DWORD FjCountBits( BYTE *pTmp, DWORD cBitsTmp, DWORD cBitsMax, BOOL bWhite ) { DWORD cBits, k; pTmp += (cBitsTmp / 8); k = cBitsTmp % 8; for (cBits = 0; cBits < cBitsMax; cBits++) { if (((*pTmp & (1 << (7 - k))) == 0) != bWhite) break; k++; if (k == 8) { k = 0; pTmp++; } } return cBits; } //----------------------------------------------------------------------------- // VOID FjBitsCopy // BYTE *pTmp Pointer of destinaition area // DWORD cBitsTmp Bit number from top of destination area // DWORD dwCode Copy code // INT cCopyBits Copy size(bit) //----------------------------------------------------------------------------- VOID FjBitsCopy( BYTE *pTmp, DWORD cBitsTmp, DWORD dwCode, INT cCopyBits ) { INT k, cBits; DWORD dwMask, dwTmp; pTmp += (cBitsTmp / 8); k = cBitsTmp % 8; cBits = cCopyBits + k; dwTmp = (DWORD)*pTmp << 16; dwTmp &= 0xff000000L >> k; dwTmp |= dwCode << (8 - k); if( cBits <= 8 ) { *pTmp = (BYTE)(dwTmp >> 16); } else if( cBits <= 16 ) { *pTmp = (BYTE)(dwTmp >> 16); *(pTmp + 1) = (BYTE)(dwTmp >> 8); } else { *pTmp = (BYTE)(dwTmp >> 16); *(pTmp + 1) = (BYTE)(dwTmp >> 8); *(pTmp + 2) = (BYTE)dwTmp; } } //----------------------------------------------------------------------------- // DWORD MhCompress // BYTE *pDest Pointer of destinaition area // DWORD cDestN Size of destination area(byte) // BYTE *pSrc Pointer of sources area // DWORD cSrcN Size of sources area(byte) // DWORD cSrcX Sources image x width // DWORD cSrcY Sources image y height // Return code : Writing size to destination area //----------------------------------------------------------------------------- DWORD MhCompress( BYTE *pDest, DWORD cDestN, BYTE *pSrc, DWORD cSrcN, DWORD cSrcX, DWORD cSrcY ) { DWORD cBitsSrc, cBitsSrcMax; DWORD cBitsDest, cBitsDestMax, cBitsDestMark; DWORD cBitsRun; DWORD dwCode, cBits; DWORD i; PATNINFO ptnInfo; cBitsDest = 0; cBitsSrc = 0; cBitsDestMax = cDestN * 8; for (i = 0; i < cSrcY; i++) { // Set initial color ptnInfo.dwNextColor = NEXT_COLOR_WHITE; // Top EOL if (cBitsDest + CBITS_EOL_CODE > cBitsDestMax) return 0; FjBitsCopy(pDest, cBitsDest, EOL_CODE, CBITS_EOL_CODE); cBitsDest += CBITS_EOL_CODE; // vvv Oct.31,1996 H.Ishida cBitsDestMark = cBitsDest; // ^^^ Oct.31,1996 H.Ishida // Encode cBitsSrcMax = cBitsSrc + (cSrcX * 8); // Compress one line image while ( cBitsSrc < cBitsSrcMax ) { // Next run is white if( ptnInfo.dwNextColor == NEXT_COLOR_WHITE ) { // Count white bits cBitsRun = FjCountBits(pSrc, cBitsSrc, (cBitsSrcMax - cBitsSrc), TRUE); cBitsSrc += cBitsRun; // vvv Oct.31,1996 H.Ishida // reduce data size if(cBitsSrc >= cBitsSrcMax){ if(cBitsDest > cBitsDestMark) break; cBitsRun = 2; // Whole white line is convert to white 2 dots:Minimun MH data. } // ^^^ Oct.31,1996 H.Ishida // Careful, white run length over maximam while( cBitsRun > RUNLENGTH_MAX ) { dwCode = WhiteMakeUpTable[MAKEUP_TABLE_MAX - 1].wCode; cBits = WhiteMakeUpTable[MAKEUP_TABLE_MAX - 1].cBits; if (cBitsDest + cBits > cBitsDestMax) return 0; FjBitsCopy(pDest, cBitsDest, dwCode, cBits); cBitsDest += cBits; cBitsRun -= RUNLENGTH_MAX; } if (cBitsRun >= 64) { dwCode = WhiteMakeUpTable[(cBitsRun / TERMINATE_MAX) - 1].wCode; cBits = WhiteMakeUpTable[(cBitsRun / TERMINATE_MAX) - 1].cBits; if (cBitsDest + cBits > cBitsDestMax) return 0; FjBitsCopy(pDest, cBitsDest, dwCode, cBits); cBitsDest += cBits; } dwCode = WhiteTerminateTable[cBitsRun % TERMINATE_MAX].wCode; cBits = WhiteTerminateTable[cBitsRun % TERMINATE_MAX].cBits; if (cBitsDest + cBits > cBitsDestMax) return 0; FjBitsCopy(pDest, cBitsDest, dwCode, cBits); cBitsDest += cBits; ptnInfo.dwNextColor = NEXT_COLOR_BLACK; } else { // Black bits cBitsRun = FjCountBits(pSrc, cBitsSrc, (cBitsSrcMax - cBitsSrc), FALSE); cBitsSrc += cBitsRun; // Careful, black run length over maximam while( cBitsRun > RUNLENGTH_MAX ) { dwCode = BlackMakeUpTable[MAKEUP_TABLE_MAX - 1].wCode; cBits = BlackMakeUpTable[MAKEUP_TABLE_MAX - 1].cBits; if (cBitsDest + cBits > cBitsDestMax) return 0; FjBitsCopy(pDest, cBitsDest, dwCode, cBits); cBitsDest += cBits; cBitsRun -= RUNLENGTH_MAX; } if (cBitsRun >= 64) { dwCode = BlackMakeUpTable[(cBitsRun / TERMINATE_MAX) - 1].wCode; cBits = BlackMakeUpTable[(cBitsRun / TERMINATE_MAX) - 1].cBits; if (cBitsDest + cBits > cBitsDestMax) return 0; FjBitsCopy(pDest, cBitsDest, dwCode, cBits); cBitsDest += cBits; } dwCode = BlackTerminateTable[cBitsRun % TERMINATE_MAX].wCode; cBits = BlackTerminateTable[cBitsRun % TERMINATE_MAX].cBits; if (cBitsDest + cBits > cBitsDestMax) return 0; FjBitsCopy(pDest, cBitsDest, dwCode, cBits); cBitsDest += cBits; ptnInfo.dwNextColor = NEXT_COLOR_WHITE; } } // End of one raster } // Last EOL. if (cBitsDest + CBITS_EOL_CODE > cBitsDestMax) return 0; FjBitsCopy(pDest, cBitsDest, EOL_CODE, CBITS_EOL_CODE); cBitsDest += CBITS_EOL_CODE; // Pad with 0 until byte boundary if ((cBits = (8 - (cBitsDest % 8)) % 8) != 0) { if (cBitsDest + cBits > cBitsDestMax) return 0; FjBitsCopy(pDest, cBitsDest, FILL_CODE, cBits); cBitsDest += cBits; } return cBitsDest / 8; } // end of FUMH.c