examples/PIPS/antiword/src/dib2sprt.c

00001 /*
00002  * dib2sprt.c
00003  * Copyright (C) 2000-2003 A.J. van Os; Released under GPL
00004  *
00005  * Description:
00006  * Functions to translate dib pictures into sprites
00007  */
00008 
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include "DeskLib:Error.h"
00012 #include "DeskLib:Sprite.h"
00013 #include "antiword.h"
00014 
00015 #if 0 /* defined(DEBUG) */
00016 static int iPicCounter = 0;
00017 #endif /* DEBUG */
00018 
00019 
00020 /*
00021  * iGetByteWidth - compute the number of bytes needed for a row of pixels
00022  */
00023 static int
00024 iGetByteWidth(const imagedata_type *pImg)
00025 {
00026         switch (pImg->uiBitsPerComponent) {
00027         case  1:
00028                 return (pImg->iWidth + 31) / 32 * sizeof(int);
00029         case  4:
00030                 return (pImg->iWidth + 7) / 8 * sizeof(int);
00031         case  8:
00032         case 24:
00033                 return (pImg->iWidth + 3) / 4 * sizeof(int);
00034         default:
00035                 DBG_DEC(pImg->uiBitsPerComponent);
00036                 return 0;
00037         }
00038 } /* end of iGetByteWidth */
00039 
00040 /*
00041  * pCreateBlankSprite - Create a blank sprite.
00042  *
00043  * Create a blank sprite and add a palette if needed
00044  *
00045  * returns a pointer to the sprite when successful, otherwise NULL
00046  */
00047 static sprite_areainfo *
00048 pCreateBlankSprite(const imagedata_type *pImg, size_t *pSize)
00049 {
00050         sprite_areainfo *pArea;
00051         UCHAR   *pucTmp;
00052         size_t  tSize;
00053         screen_modeval  uMode;
00054         int     iIndex, iPaletteEntries;
00055 
00056         TRACE_MSG("pCreateBlankSprite");
00057 
00058         fail(pImg == NULL);
00059         fail(pSize == NULL);
00060 
00061         switch (pImg->uiBitsPerComponent) {
00062         case  1:
00063                 uMode.screen_mode = 18;
00064                 iPaletteEntries = 2;
00065                 break;
00066         case  4:
00067                 uMode.screen_mode = 20;
00068                 iPaletteEntries = 16;
00069                 break;
00070         case  8:
00071         case 24:
00072                 uMode.screen_mode = 21;
00073                 iPaletteEntries = 0;
00074                 break;
00075         default:
00076                 DBG_DEC(pImg->uiBitsPerComponent);
00077                 return NULL;
00078         }
00079         fail(iPaletteEntries < 0 || iPaletteEntries > 16);
00080 
00081         /* Get memory for the sprite */
00082         tSize = sizeof(sprite_areainfo) +
00083                 Sprite_MemorySize(pImg->iWidth, pImg->iHeight, uMode,
00084                 iPaletteEntries > 0 ? sprite_HASPAL : sprite_HASNOMASKPAL);
00085         DBG_DEC(tSize);
00086         pArea = xmalloc(tSize);
00087 
00088         /* Initialise sprite area */
00089         pArea->areasize = tSize;
00090         pArea->numsprites = 0;
00091         pArea->firstoffset = sizeof(sprite_areainfo);
00092         pArea->freeoffset = sizeof(sprite_areainfo);
00093 
00094         /* Create a blank sprite */
00095         Error_CheckFatal(Sprite_Create(pArea, "wordimage",
00096                 iPaletteEntries > 0 ? 1 : 0,
00097                 pImg->iWidth, pImg->iHeight, uMode));
00098 
00099         /* Add the palette */
00100         pucTmp = (UCHAR *)pArea + pArea->firstoffset + sizeof(sprite_header);
00101         for (iIndex = 0; iIndex < iPaletteEntries; iIndex++) {
00102                 /* First color */
00103                 *pucTmp++ = 0;
00104                 *pucTmp++ = pImg->aucPalette[iIndex][0];
00105                 *pucTmp++ = pImg->aucPalette[iIndex][1];
00106                 *pucTmp++ = pImg->aucPalette[iIndex][2];
00107                 /* Second color */
00108                 *pucTmp++ = 0;
00109                 *pucTmp++ = pImg->aucPalette[iIndex][0];
00110                 *pucTmp++ = pImg->aucPalette[iIndex][1];
00111                 *pucTmp++ = pImg->aucPalette[iIndex][2];
00112         }
00113 
00114         *pSize = tSize;
00115         return pArea;
00116 } /* end of pCreateBlankSprite */
00117 
00118 /*
00119  * iReduceColor - reduce from 24 bit to 8 bit color
00120  *
00121  * Reduce 24 bit true colors to RISC OS default 256 color palette
00122  *
00123  * returns the resulting color
00124  */
00125 static int
00126 iReduceColor(int iRed, int iGreen, int iBlue)
00127 {
00128         int     iResult;
00129 
00130         iResult = (iBlue & 0x80) ? 0x80 : 0;
00131         iResult |= (iGreen & 0x80) ? 0x40 : 0;
00132         iResult |= (iGreen & 0x40) ? 0x20 : 0;
00133         iResult |= (iRed & 0x80) ? 0x10 : 0;
00134         iResult |= (iBlue & 0x40) ? 0x08 : 0;
00135         iResult |= (iRed & 0x40) ? 0x04 : 0;
00136         iResult |= ((iRed | iGreen | iBlue) & 0x20) ? 0x02 : 0;
00137         iResult |= ((iRed | iGreen | iBlue) & 0x10) ? 0x01 : 0;
00138         return iResult;
00139 } /* end of iReduceColor */
00140 
00141 /*
00142  * vDecode1bpp - decode an uncompressed 1 bit per pixel image
00143  */
00144 static void
00145 vDecode1bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
00146 {
00147         int     iX, iY, iByteWidth, iOffset, iTmp, iEighthWidth, iPadding;
00148         UCHAR   ucTmp;
00149 
00150         DBG_MSG("vDecode1bpp");
00151 
00152         fail(pFile == NULL);
00153         fail(pucData == NULL);
00154         fail(pImg == NULL);
00155         fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 2);
00156 
00157         iByteWidth = iGetByteWidth(pImg);
00158 
00159         iEighthWidth = (pImg->iWidth + 7) / 8;
00160         iPadding = ROUND4(iEighthWidth) - iEighthWidth;
00161 
00162         for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
00163                 for (iX = 0; iX < iEighthWidth; iX++) {
00164                         iTmp = iNextByte(pFile);
00165                         if (iTmp == EOF) {
00166                                 return;
00167                         }
00168                         /* Reverse the bit order */
00169                         ucTmp  = (iTmp & BIT(0)) ? (UCHAR)BIT(7) : 0;
00170                         ucTmp |= (iTmp & BIT(1)) ? (UCHAR)BIT(6) : 0;
00171                         ucTmp |= (iTmp & BIT(2)) ? (UCHAR)BIT(5) : 0;
00172                         ucTmp |= (iTmp & BIT(3)) ? (UCHAR)BIT(4) : 0;
00173                         ucTmp |= (iTmp & BIT(4)) ? (UCHAR)BIT(3) : 0;
00174                         ucTmp |= (iTmp & BIT(5)) ? (UCHAR)BIT(2) : 0;
00175                         ucTmp |= (iTmp & BIT(6)) ? (UCHAR)BIT(1) : 0;
00176                         ucTmp |= (iTmp & BIT(7)) ? (UCHAR)BIT(0) : 0;
00177                         iOffset = iY * iByteWidth + iX;
00178                         *(pucData + iOffset) = ucTmp;
00179                 }
00180                 (void)tSkipBytes(pFile, iPadding);
00181         }
00182 } /* end of vDecode1bpp */
00183 
00184 /*
00185  * vDecode4bpp - decode an uncompressed 4 bits per pixel image
00186  */
00187 static void
00188 vDecode4bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
00189 {
00190         int     iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth, iPadding;
00191         UCHAR   ucTmp;
00192 
00193         DBG_MSG("vDecode4bpp");
00194 
00195         fail(pFile == NULL);
00196         fail(pucData == NULL);
00197         fail(pImg == NULL);
00198         fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
00199 
00200         iByteWidth = iGetByteWidth(pImg);
00201 
00202         iHalfWidth = (pImg->iWidth + 1) / 2;
00203         iPadding = ROUND4(iHalfWidth) - iHalfWidth;
00204 
00205         for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
00206                 for (iX = 0; iX < iHalfWidth; iX++) {
00207                         iTmp = iNextByte(pFile);
00208                         if (iTmp == EOF) {
00209                                 return;
00210                         }
00211                         /* Reverse the nibble order */
00212                         ucTmp = (iTmp & 0xf0) >> 4;
00213                         ucTmp |= (iTmp & 0x0f) << 4;
00214                         iOffset = iY * iByteWidth + iX;
00215                         *(pucData + iOffset) = ucTmp;
00216                 }
00217                 (void)tSkipBytes(pFile, iPadding);
00218         }
00219 } /* end of vDecode4bpp */
00220 
00221 /*
00222  * vDecode8bpp - decode an uncompressed 8 bits per pixel image
00223  */
00224 static void
00225 vDecode8bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
00226 {
00227         int     iX, iY, iByteWidth, iOffset, iIndex, iPadding;
00228 
00229         DBG_MSG("vDecode8bpp");
00230 
00231         fail(pFile == NULL);
00232         fail(pucData == NULL);
00233         fail(pImg == NULL);
00234         fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
00235 
00236         iByteWidth = iGetByteWidth(pImg);
00237 
00238         iPadding = ROUND4(pImg->iWidth) - pImg->iWidth;
00239 
00240         for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
00241                 for (iX = 0; iX < pImg->iWidth; iX++) {
00242                         iIndex = iNextByte(pFile);
00243                         if (iIndex == EOF) {
00244                                 return;
00245                         }
00246                         iOffset = iY * iByteWidth + iX;
00247                         *(pucData + iOffset) = iReduceColor(
00248                                 pImg->aucPalette[iIndex][0],
00249                                 pImg->aucPalette[iIndex][1],
00250                                 pImg->aucPalette[iIndex][2]);
00251                 }
00252                 (void)tSkipBytes(pFile, iPadding);
00253         }
00254 } /* end of vDecode8bpp */
00255 
00256 /*
00257  * vDecode24bpp - decode an uncompressed 24 bits per pixel image
00258  */
00259 static void
00260 vDecode24bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
00261 {
00262         int     iX, iY, iTripleWidth, iByteWidth, iOffset, iPadding;
00263         int     iRed, iGreen, iBlue;
00264 
00265         DBG_MSG("vDecode24bpp");
00266 
00267         fail(pFile == NULL);
00268         fail(pucData == NULL);
00269         fail(pImg == NULL);
00270 
00271         iByteWidth = iGetByteWidth(pImg);
00272 
00273         iTripleWidth = pImg->iWidth * 3;
00274         iPadding = ROUND4(iTripleWidth) - iTripleWidth;
00275 
00276         for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
00277                 for (iX = 0; iX < pImg->iWidth; iX++) {
00278                         iBlue = iNextByte(pFile);
00279                         if (iBlue == EOF) {
00280                                 return;
00281                         }
00282                         iGreen = iNextByte(pFile);
00283                         if (iGreen == EOF) {
00284                                 return;
00285                         }
00286                         iRed = iNextByte(pFile);
00287                         if (iRed == EOF) {
00288                                 return;
00289                         }
00290                         iOffset = iY * iByteWidth + iX;
00291                         *(pucData + iOffset) =
00292                                         iReduceColor(iRed, iGreen, iBlue);
00293                 }
00294                 (void)tSkipBytes(pFile, iPadding);
00295         }
00296 } /* end of vDecode24bpp */
00297 
00298 /*
00299  * vDecodeRle4 - decode a RLE compressed 4 bits per pixel image
00300  */
00301 static void
00302 vDecodeRle4(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
00303 {
00304         int     iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth;
00305         int     iRun, iRunLength, iHalfRun;
00306         BOOL    bEOL;
00307         UCHAR   ucTmp;
00308 
00309         DBG_MSG("vDecodeRle4");
00310 
00311         fail(pFile == NULL);
00312         fail(pucData == NULL);
00313         fail(pImg == NULL);
00314         fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
00315 
00316         DBG_DEC(pImg->iWidth);
00317         DBG_DEC(pImg->iHeight);
00318 
00319         iByteWidth = iGetByteWidth(pImg);
00320         iHalfWidth = (pImg->iWidth + 1) / 2;
00321 
00322         for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
00323                 bEOL = FALSE;
00324                 iX = 0;
00325                 while (!bEOL) {
00326                         iRunLength = iNextByte(pFile);
00327                         if (iRunLength == EOF) {
00328                                 return;
00329                         }
00330                         if (iRunLength != 0) {
00331                                 /*
00332                                  * Encoded packet:
00333                                  * RunLength pixels, all the "same" value
00334                                  */
00335                                 iTmp = iNextByte(pFile);
00336                                 if (iTmp == EOF) {
00337                                         return;
00338                                 }
00339                                 /* Reverse the nibble order */
00340                                 ucTmp = (iTmp & 0xf0) >> 4;
00341                                 ucTmp |= (iTmp & 0x0f) << 4;
00342                                 iHalfRun = (iRunLength + 1) / 2;
00343                                 for (iRun = 0; iRun < iHalfRun; iRun++) {
00344                                         if (iX < iHalfWidth) {
00345                                                 iOffset = iY * iByteWidth + iX;
00346                                                 *(pucData + iOffset) = ucTmp;
00347                                         }
00348                                         iX++;
00349                                 }
00350                                 continue;
00351                         }
00352                         /* Literal or escape */
00353                         iRunLength = iNextByte(pFile);
00354                         if (iRunLength == EOF) {
00355                                 return;
00356                         }
00357                         if (iRunLength == 0) {          /* End of line escape */
00358                                 bEOL = TRUE;
00359                         } else if (iRunLength == 1) {   /* End of file escape */
00360                                 return;
00361                         } else if (iRunLength == 2) {   /* Delta escape */
00362                                 DBG_MSG("RLE4: encountered delta escape");
00363                                 return;
00364                         } else {                        /* Literal packet */
00365                                 iHalfRun = (iRunLength + 1) / 2;
00366                                 for (iRun = 0; iRun < iHalfRun; iRun++) {
00367                                         iTmp = iNextByte(pFile);
00368                                         if (iTmp == EOF) {
00369                                                 return;
00370                                         }
00371                                         /* Reverse the nibble order */
00372                                         ucTmp = (iTmp & 0xf0) >> 4;
00373                                         ucTmp |= (iTmp & 0x0f) << 4;
00374                                         if (iX < iHalfWidth) {
00375                                                 iOffset = iY * iByteWidth + iX;
00376                                                 *(pucData + iOffset) = ucTmp;
00377                                         }
00378                                         iX++;
00379                                 }
00380                                 /* Padding if the number of bytes is odd */
00381                                 if (odd(iHalfRun)) {
00382                                         (void)tSkipBytes(pFile, 1);
00383                                 }
00384                         }
00385                 }
00386                 DBG_DEC_C(iX != iHalfWidth, iX);
00387         }
00388 } /* end of vDecodeRle4 */
00389 
00390 /*
00391  * vDecodeRle8 - decode a RLE compressed 8 bits per pixel image
00392  */
00393 static void
00394 vDecodeRle8(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
00395 {
00396         int     iX, iY, iRun, iRunLength, iOffset, iIndex, iByteWidth;
00397         BOOL    bEOL;
00398 
00399         DBG_MSG("vDecodeRle8");
00400 
00401         fail(pFile == NULL);
00402         fail(pucData == NULL);
00403         fail(pImg == NULL);
00404         fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
00405 
00406         DBG_DEC(pImg->iWidth);
00407         DBG_DEC(pImg->iHeight);
00408 
00409         iByteWidth = iGetByteWidth(pImg);
00410 
00411         for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
00412                 bEOL = FALSE;
00413                 iX = 0;
00414                 while (!bEOL) {
00415                         iRunLength = iNextByte(pFile);
00416                         if (iRunLength == EOF) {
00417                                 return;
00418                         }
00419                         if (iRunLength != 0) {
00420                                 /*
00421                                  * Encoded packet:
00422                                  * RunLength pixels, all the same value
00423                                  */
00424                                 iIndex = iNextByte(pFile);
00425                                 if (iIndex == EOF) {
00426                                         return;
00427                                 }
00428                                 for (iRun = 0; iRun < iRunLength; iRun++) {
00429                                         if (iX < pImg->iWidth) {
00430                                                 iOffset = iY * iByteWidth + iX;
00431                                                 *(pucData + iOffset) =
00432                                                         iReduceColor(
00433                                                         pImg->aucPalette[iIndex][0],
00434                                                         pImg->aucPalette[iIndex][1],
00435                                                         pImg->aucPalette[iIndex][2]);
00436                                         }
00437                                         iX++;
00438                                 }
00439                                 continue;
00440                         }
00441                         /* Literal or escape */
00442                         iRunLength = iNextByte(pFile);
00443                         if (iRunLength == EOF) {
00444                                 return;
00445                         }
00446                         if (iRunLength == 0) {          /* End of line escape */
00447                                 bEOL = TRUE;
00448                         } else if (iRunLength == 1) {   /* End of file escape */
00449                                 return;
00450                         } else if (iRunLength == 2) {   /* Delta escape */
00451                                 DBG_MSG("RLE8: encountered delta escape");
00452                                 return;
00453                         } else {                        /* Literal packet */
00454                                 for (iRun = 0; iRun < iRunLength; iRun++) {
00455                                         iIndex = iNextByte(pFile);
00456                                         if (iIndex == EOF) {
00457                                                 return;
00458                                         }
00459                                         if (iX < pImg->iWidth) {
00460                                                 iOffset = iY * iByteWidth + iX;
00461                                                 *(pucData + iOffset) =
00462                                                         iReduceColor(
00463                                                         pImg->aucPalette[iIndex][0],
00464                                                         pImg->aucPalette[iIndex][1],
00465                                                         pImg->aucPalette[iIndex][2]);
00466                                         }
00467                                         iX++;
00468                                 }
00469                                 /* Padding if the number of bytes is odd */
00470                                 if (odd(iRunLength)) {
00471                                         (void)tSkipBytes(pFile, 1);
00472                                 }
00473                         }
00474                 }
00475                 DBG_DEC_C(iX != pImg->iWidth, iX);
00476         }
00477 } /* end of vDecodeRle8 */
00478 
00479 #if 0 /* defined(DEBUG) */
00480 static void
00481 vCopy2File(UCHAR *pucSprite, size_t tSpriteSize)
00482 {
00483         FILE    *pOutFile;
00484         int     iIndex;
00485         char    szFilename[30];
00486 
00487         sprintf(szFilename, "<Wimp$ScrapDir>.sprt%04d", ++iPicCounter);
00488         pOutFile = fopen(szFilename, "wb");
00489         if (pOutFile == NULL) {
00490                 return;
00491         }
00492         DBG_MSG(szFilename);
00493         for (iIndex = 4; iIndex < (int)tSpriteSize; iIndex++) {
00494                 if (putc(pucSprite[iIndex], pOutFile) == EOF) {
00495                         break;
00496                 }
00497         }
00498         (void)fclose(pOutFile);
00499         vSetFiletype(szFilename, FILETYPE_SPRITE);
00500 } /* end of vCopy2File */
00501 #endif /* DEBUG */
00502 
00503 /*
00504  * vDecodeDIB - decode a dib picture
00505  */
00506 static void
00507 vDecodeDIB(diagram_type *pDiag, FILE *pFile, const imagedata_type *pImg)
00508 {
00509         sprite_areainfo *pSprite;
00510         UCHAR   *pucPalette, *pucData;
00511         size_t  tSpriteSize;
00512         int     iHeaderSize;
00513 
00514         /* Skip the bitmap info header */
00515         iHeaderSize = (int)ulNextLong(pFile);
00516         (void)tSkipBytes(pFile, iHeaderSize - 4);
00517         /* Skip the colortable */
00518         if (pImg->uiBitsPerComponent <= 8) {
00519                 (void)tSkipBytes(pFile,
00520                         pImg->iColorsUsed * ((iHeaderSize > 12) ? 4 : 3));
00521         }
00522 
00523         /* Create an blank sprite */
00524         pSprite = pCreateBlankSprite(pImg, &tSpriteSize);
00525         pucPalette = (UCHAR *)pSprite +
00526                         pSprite->firstoffset + sizeof(sprite_header);
00527 
00528         /* Add the pixel information */
00529         switch (pImg->uiBitsPerComponent) {
00530         case  1:
00531                 fail(pImg->eCompression != compression_none);
00532                 pucData = pucPalette + 2 * 8;
00533                 vDecode1bpp(pFile, pucData, pImg);
00534                 break;
00535         case  4:
00536                 fail(pImg->eCompression != compression_none &&
00537                                 pImg->eCompression != compression_rle4);
00538                 pucData = pucPalette + 16 * 8;
00539                 if (pImg->eCompression == compression_rle4) {
00540                         vDecodeRle4(pFile, pucData, pImg);
00541                 } else {
00542                         vDecode4bpp(pFile, pucData, pImg);
00543                 }
00544                 break;
00545         case  8:
00546                 fail(pImg->eCompression != compression_none &&
00547                                 pImg->eCompression != compression_rle8);
00548                 pucData = pucPalette + 0 * 8;
00549                 if (pImg->eCompression == compression_rle8) {
00550                         vDecodeRle8(pFile, pucData, pImg);
00551                 } else {
00552                         vDecode8bpp(pFile, pucData, pImg);
00553                 }
00554                 break;
00555         case 24:
00556                 fail(pImg->eCompression != compression_none);
00557                 pucData = pucPalette + 0 * 8;
00558                 vDecode24bpp(pFile, pucData, pImg);
00559                 break;
00560         default:
00561                 DBG_DEC(pImg->uiBitsPerComponent);
00562                 break;
00563         }
00564 
00565 #if 0 /* defined(DEBUG) */
00566         vCopy2File((UCHAR *)pSprite, tSpriteSize);
00567 #endif /* DEBUG */
00568 
00569         /* Add the sprite to the Draw file */
00570         vImage2Diagram(pDiag, pImg,
00571                 (UCHAR *)pSprite + pSprite->firstoffset,
00572                 tSpriteSize - pSprite->firstoffset);
00573 
00574         /* Clean up before you leave */
00575         pSprite = xfree(pSprite);
00576 } /* end of vDecodeDIB */
00577 
00578 /*
00579  * bTranslateDIB - translate a DIB picture
00580  *
00581  * This function translates a picture from dib to sprite
00582  *
00583  * return TRUE when sucessful, otherwise FALSE
00584  */
00585 BOOL
00586 bTranslateDIB(diagram_type *pDiag, FILE *pFile,
00587         ULONG ulFileOffset, const imagedata_type *pImg)
00588 {
00589         /* Seek to start position of DIB data */
00590         if (!bSetDataOffset(pFile, ulFileOffset)) {
00591                 return FALSE;
00592         }
00593 
00594         vDecodeDIB(pDiag, pFile, pImg);
00595 
00596         return TRUE;
00597 } /* end of bTranslateDIB */

Generated by  doxygen 1.6.2