mirror of
https://github.com/simon987/antiword.git
synced 2025-04-10 13:06:41 +00:00
510 lines
12 KiB
C
510 lines
12 KiB
C
/*
|
|
* 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 <stdio.h>
|
|
#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 */
|