Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

/*
 * 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 */