/* * dib2eps.c * Copyright (C) 2000-2003 A.J. van Os; Released under GPL * * Description: * Functions to translate dib pictures into eps * *================================================================ * This part of the software is based on: * The Windows Bitmap Decoder Class part of paintlib * Paintlib is copyright (c) 1996-2000 Ulrich von Zadow *================================================================ * The credit should go to him, but all the bugs are mine. */ #include #include "antiword.h" /* * vDecode1bpp - decode an uncompressed 1 bit per pixel image */ static void vDecode1bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg) { size_t tPadding; int iX, iY, iN, iByte, iTmp, iEighthWidth, iUse; DBG_MSG("vDecode1bpp"); fail(pOutFile == NULL); fail(pImg == NULL); fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 2); DBG_DEC(pImg->iWidth); DBG_DEC(pImg->iHeight); iEighthWidth = (pImg->iWidth + 7) / 8; tPadding = (size_t)(ROUND4(iEighthWidth) - iEighthWidth); for (iY = 0; iY < pImg->iHeight; iY++) { for (iX = 0; iX < iEighthWidth; iX++) { iByte = iNextByte(pInFile); if (iByte == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } if (iX == iEighthWidth - 1 && pImg->iWidth % 8 != 0) { iUse = pImg->iWidth % 8; } else { iUse = 8; } for (iN = 0; iN < iUse; iN++) { switch (iN) { case 0: iTmp = (iByte & 0x80) / 128; break; case 1: iTmp = (iByte & 0x40) / 64; break; case 2: iTmp = (iByte & 0x20) / 32; break; case 3: iTmp = (iByte & 0x10) / 16; break; case 4: iTmp = (iByte & 0x08) / 8; break; case 5: iTmp = (iByte & 0x04) / 4; break; case 6: iTmp = (iByte & 0x02) / 2; break; case 7: iTmp = (iByte & 0x01); break; default: iTmp = 0; break; } vASCII85EncodeByte(pOutFile, iTmp); } } (void)tSkipBytes(pInFile, tPadding); } vASCII85EncodeByte(pOutFile, EOF); } /* end of vDecode1bpp */ /* * vDecode4bpp - decode an uncompressed 4 bits per pixel image */ static void vDecode4bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg) { size_t tPadding; int iX, iY, iN, iByte, iTmp, iHalfWidth, iUse; DBG_MSG("vDecode4bpp"); fail(pInFile == NULL); fail(pOutFile == NULL); fail(pImg == NULL); fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16); DBG_DEC(pImg->iWidth); DBG_DEC(pImg->iHeight); iHalfWidth = (pImg->iWidth + 1) / 2; tPadding = (size_t)(ROUND4(iHalfWidth) - iHalfWidth); for (iY = 0; iY < pImg->iHeight; iY++) { for (iX = 0; iX < iHalfWidth; iX++) { iByte = iNextByte(pInFile); if (iByte == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } if (iX == iHalfWidth - 1 && odd(pImg->iWidth)) { iUse = 1; } else { iUse = 2; } for (iN = 0; iN < iUse; iN++) { if (odd(iN)) { iTmp = iByte & 0x0f; } else { iTmp = (iByte & 0xf0) / 16; } vASCII85EncodeByte(pOutFile, iTmp); } } (void)tSkipBytes(pInFile, tPadding); } vASCII85EncodeByte(pOutFile, EOF); } /* end of vDecode4bpp */ /* * vDecode8bpp - decode an uncompressed 8 bits per pixel image */ static void vDecode8bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg) { size_t tPadding; int iX, iY, iByte; DBG_MSG("vDecode8bpp"); fail(pInFile == NULL); fail(pOutFile == NULL); fail(pImg == NULL); fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256); DBG_DEC(pImg->iWidth); DBG_DEC(pImg->iHeight); tPadding = (size_t)(ROUND4(pImg->iWidth) - pImg->iWidth); for (iY = 0; iY < pImg->iHeight; iY++) { for (iX = 0; iX < pImg->iWidth; iX++) { iByte = iNextByte(pInFile); if (iByte == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } vASCII85EncodeByte(pOutFile, iByte); } (void)tSkipBytes(pInFile, tPadding); } vASCII85EncodeByte(pOutFile, EOF); } /* end of vDecode8bpp */ /* * vDecode24bpp - decode an uncompressed 24 bits per pixel image */ static void vDecode24bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg) { size_t tPadding; int iX, iY, iBlue, iGreen, iRed, iTripleWidth; DBG_MSG("vDecode24bpp"); fail(pInFile == NULL); fail(pOutFile == NULL); fail(pImg == NULL); fail(!pImg->bColorImage); DBG_DEC(pImg->iWidth); DBG_DEC(pImg->iHeight); iTripleWidth = pImg->iWidth * 3; tPadding = (size_t)(ROUND4(iTripleWidth) - iTripleWidth); for (iY = 0; iY < pImg->iHeight; iY++) { for (iX = 0; iX < pImg->iWidth; iX++) { /* Change from BGR order to RGB order */ iBlue = iNextByte(pInFile); if (iBlue == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } iGreen = iNextByte(pInFile); if (iGreen == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } iRed = iNextByte(pInFile); if (iRed == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } vASCII85EncodeByte(pOutFile, iRed); vASCII85EncodeByte(pOutFile, iGreen); vASCII85EncodeByte(pOutFile, iBlue); } (void)tSkipBytes(pInFile, tPadding); } vASCII85EncodeByte(pOutFile, EOF); } /* end of vDecode24bpp */ /* * vDecodeRle4 - decode a RLE compressed 4 bits per pixel image */ static void vDecodeRle4(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg) { int iX, iY, iByte, iTmp, iRunLength, iRun; BOOL bEOF, bEOL; DBG_MSG("vDecodeRle4"); fail(pInFile == NULL); fail(pOutFile == NULL); fail(pImg == NULL); fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16); DBG_DEC(pImg->iWidth); DBG_DEC(pImg->iHeight); bEOF = FALSE; for (iY = 0; iY < pImg->iHeight && !bEOF; iY++) { bEOL = FALSE; iX = 0; while (!bEOL) { iRunLength = iNextByte(pInFile); if (iRunLength == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } if (iRunLength != 0) { /* * Encoded packet: * RunLength pixels, all the "same" value */ iByte = iNextByte(pInFile); if (iByte == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } for (iRun = 0; iRun < iRunLength; iRun++) { if (odd(iRun)) { iTmp = iByte & 0x0f; } else { iTmp = (iByte & 0xf0) / 16; } if (iX < pImg->iWidth) { vASCII85EncodeByte(pOutFile, iTmp); } iX++; } continue; } /* Literal or escape */ iRunLength = iNextByte(pInFile); if (iRunLength == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } if (iRunLength == 0) { /* End of line escape */ bEOL = TRUE; } else if (iRunLength == 1) { /* End of file escape */ bEOF = TRUE; bEOL = TRUE; } else if (iRunLength == 2) { /* Delta escape */ DBG_MSG("RLE4: encountered delta escape"); bEOF = TRUE; bEOL = TRUE; } else { /* Literal packet */ iByte = 0; for (iRun = 0; iRun < iRunLength; iRun++) { if (odd(iRun)) { iTmp = iByte & 0x0f; } else { iByte = iNextByte(pInFile); if (iByte == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } iTmp = (iByte & 0xf0) / 16; } if (iX < pImg->iWidth) { vASCII85EncodeByte(pOutFile, iTmp); } iX++; } /* Padding if the number of bytes is odd */ if (odd((iRunLength + 1) / 2)) { (void)tSkipBytes(pInFile, 1); } } } DBG_DEC_C(iX != pImg->iWidth, iX); } vASCII85EncodeByte(pOutFile, EOF); } /* end of vDecodeRle4 */ /* * vDecodeRle8 - decode a RLE compressed 8 bits per pixel image */ static void vDecodeRle8(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg) { int iX, iY, iByte, iRunLength, iRun; BOOL bEOF, bEOL; DBG_MSG("vDecodeRle8"); fail(pInFile == NULL); fail(pOutFile == NULL); fail(pImg == NULL); fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256); DBG_DEC(pImg->iWidth); DBG_DEC(pImg->iHeight); bEOF = FALSE; for (iY = 0; iY < pImg->iHeight && !bEOF; iY++) { bEOL = FALSE; iX = 0; while (!bEOL) { iRunLength = iNextByte(pInFile); if (iRunLength == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } if (iRunLength != 0) { /* * Encoded packet: * RunLength pixels, all the same value */ iByte = iNextByte(pInFile); if (iByte == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } for (iRun = 0; iRun < iRunLength; iRun++) { if (iX < pImg->iWidth) { vASCII85EncodeByte(pOutFile, iByte); } iX++; } continue; } /* Literal or escape */ iRunLength = iNextByte(pInFile); if (iRunLength == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } if (iRunLength == 0) { /* End of line escape */ bEOL = TRUE; } else if (iRunLength == 1) { /* End of file escape */ bEOF = TRUE; bEOL = TRUE; } else if (iRunLength == 2) { /* Delta escape */ DBG_MSG("RLE8: encountered delta escape"); bEOF = TRUE; bEOL = TRUE; } else { /* Literal packet */ for (iRun = 0; iRun < iRunLength; iRun++) { iByte = iNextByte(pInFile); if (iByte == EOF) { vASCII85EncodeByte(pOutFile, EOF); return; } if (iX < pImg->iWidth) { vASCII85EncodeByte(pOutFile, iByte); } iX++; } /* Padding if the number of bytes is odd */ if (odd(iRunLength)) { (void)tSkipBytes(pInFile, 1); } } } DBG_DEC_C(iX != pImg->iWidth, iX); } vASCII85EncodeByte(pOutFile, EOF); } /* end of vDecodeRle8 */ /* * vDecodeDIB - decode a dib picture */ static void vDecodeDIB(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg) { size_t tHeaderSize; fail(pInFile == NULL); fail(pOutFile == NULL); fail(pImg == NULL); /* Skip the bitmap info header */ tHeaderSize = (size_t)ulNextLong(pInFile); (void)tSkipBytes(pInFile, tHeaderSize - 4); /* Skip the colortable */ if (pImg->uiBitsPerComponent <= 8) { (void)tSkipBytes(pInFile, (size_t)(pImg->iColorsUsed * ((tHeaderSize > 12) ? 4 : 3))); } switch (pImg->uiBitsPerComponent) { case 1: fail(pImg->eCompression != compression_none); vDecode1bpp(pInFile, pOutFile, pImg); break; case 4: fail(pImg->eCompression != compression_none && pImg->eCompression != compression_rle4); if (pImg->eCompression == compression_rle4) { vDecodeRle4(pInFile, pOutFile, pImg); } else { vDecode4bpp(pInFile, pOutFile, pImg); } break; case 8: fail(pImg->eCompression != compression_none && pImg->eCompression != compression_rle8); if (pImg->eCompression == compression_rle8) { vDecodeRle8(pInFile, pOutFile, pImg); } else { vDecode8bpp(pInFile, pOutFile, pImg); } break; case 24: fail(pImg->eCompression != compression_none); vDecode24bpp(pInFile, pOutFile, pImg); break; default: DBG_DEC(pImg->uiBitsPerComponent); break; } } /* end of vDecodeDIB */ #if defined(DEBUG) /* * vCopy2File */ static void vCopy2File(FILE *pInFile, ULONG ulFileOffset, size_t tPictureLen) { static int iPicCounter = 0; FILE *pOutFile; size_t tIndex; int iTmp; char szFilename[30]; if (!bSetDataOffset(pInFile, ulFileOffset)) { return; } sprintf(szFilename, "/tmp/pic/pic%04d.bmp", ++iPicCounter); pOutFile = fopen(szFilename, "wb"); if (pOutFile == NULL) { return; } /* Turn a dib into a bmp by adding a fake 14 byte header */ (void)putc('B', pOutFile); (void)putc('M', pOutFile); for (iTmp = 0; iTmp < 12; iTmp++) { if (putc(0, pOutFile) == EOF) { break; } } for (tIndex = 0; tIndex < tPictureLen; tIndex++) { iTmp = iNextByte(pInFile); if (putc(iTmp, pOutFile) == EOF) { break; } } (void)fclose(pOutFile); } /* end of vCopy2File */ #endif /* DEBUG */ /* * bTranslateDIB - translate a DIB picture * * This function translates a picture from dib to eps * * return TRUE when sucessful, otherwise FALSE */ BOOL bTranslateDIB(diagram_type *pDiag, FILE *pInFile, ULONG ulFileOffset, const imagedata_type *pImg) { #if defined(DEBUG) fail(pImg->tPosition > pImg->tLength); vCopy2File(pInFile, ulFileOffset, pImg->tLength - pImg->tPosition); #endif /* DEBUG */ /* Seek to start position of DIB data */ if (!bSetDataOffset(pInFile, ulFileOffset)) { return FALSE; } vImagePrologue(pDiag, pImg); vDecodeDIB(pInFile, pDiag->pOutFile, pImg); vImageEpilogue(pDiag); return TRUE; } /* end of bTranslateDIB */