00001
00002
00003
00004
00005
00006
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
00016 static int iPicCounter = 0;
00017 #endif
00018
00019
00020
00021
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 }
00039
00040
00041
00042
00043
00044
00045
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
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
00089 pArea->areasize = tSize;
00090 pArea->numsprites = 0;
00091 pArea->firstoffset = sizeof(sprite_areainfo);
00092 pArea->freeoffset = sizeof(sprite_areainfo);
00093
00094
00095 Error_CheckFatal(Sprite_Create(pArea, "wordimage",
00096 iPaletteEntries > 0 ? 1 : 0,
00097 pImg->iWidth, pImg->iHeight, uMode));
00098
00099
00100 pucTmp = (UCHAR *)pArea + pArea->firstoffset + sizeof(sprite_header);
00101 for (iIndex = 0; iIndex < iPaletteEntries; iIndex++) {
00102
00103 *pucTmp++ = 0;
00104 *pucTmp++ = pImg->aucPalette[iIndex][0];
00105 *pucTmp++ = pImg->aucPalette[iIndex][1];
00106 *pucTmp++ = pImg->aucPalette[iIndex][2];
00107
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 }
00117
00118
00119
00120
00121
00122
00123
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 }
00140
00141
00142
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
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 }
00183
00184
00185
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
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 }
00220
00221
00222
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 }
00255
00256
00257
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 }
00297
00298
00299
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
00333
00334
00335 iTmp = iNextByte(pFile);
00336 if (iTmp == EOF) {
00337 return;
00338 }
00339
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
00353 iRunLength = iNextByte(pFile);
00354 if (iRunLength == EOF) {
00355 return;
00356 }
00357 if (iRunLength == 0) {
00358 bEOL = TRUE;
00359 } else if (iRunLength == 1) {
00360 return;
00361 } else if (iRunLength == 2) {
00362 DBG_MSG("RLE4: encountered delta escape");
00363 return;
00364 } else {
00365 iHalfRun = (iRunLength + 1) / 2;
00366 for (iRun = 0; iRun < iHalfRun; iRun++) {
00367 iTmp = iNextByte(pFile);
00368 if (iTmp == EOF) {
00369 return;
00370 }
00371
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
00381 if (odd(iHalfRun)) {
00382 (void)tSkipBytes(pFile, 1);
00383 }
00384 }
00385 }
00386 DBG_DEC_C(iX != iHalfWidth, iX);
00387 }
00388 }
00389
00390
00391
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
00422
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
00442 iRunLength = iNextByte(pFile);
00443 if (iRunLength == EOF) {
00444 return;
00445 }
00446 if (iRunLength == 0) {
00447 bEOL = TRUE;
00448 } else if (iRunLength == 1) {
00449 return;
00450 } else if (iRunLength == 2) {
00451 DBG_MSG("RLE8: encountered delta escape");
00452 return;
00453 } else {
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
00470 if (odd(iRunLength)) {
00471 (void)tSkipBytes(pFile, 1);
00472 }
00473 }
00474 }
00475 DBG_DEC_C(iX != pImg->iWidth, iX);
00476 }
00477 }
00478
00479 #if 0
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 }
00501 #endif
00502
00503
00504
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
00515 iHeaderSize = (int)ulNextLong(pFile);
00516 (void)tSkipBytes(pFile, iHeaderSize - 4);
00517
00518 if (pImg->uiBitsPerComponent <= 8) {
00519 (void)tSkipBytes(pFile,
00520 pImg->iColorsUsed * ((iHeaderSize > 12) ? 4 : 3));
00521 }
00522
00523
00524 pSprite = pCreateBlankSprite(pImg, &tSpriteSize);
00525 pucPalette = (UCHAR *)pSprite +
00526 pSprite->firstoffset + sizeof(sprite_header);
00527
00528
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
00566 vCopy2File((UCHAR *)pSprite, tSpriteSize);
00567 #endif
00568
00569
00570 vImage2Diagram(pDiag, pImg,
00571 (UCHAR *)pSprite + pSprite->firstoffset,
00572 tSpriteSize - pSprite->firstoffset);
00573
00574
00575 pSprite = xfree(pSprite);
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585 BOOL
00586 bTranslateDIB(diagram_type *pDiag, FILE *pFile,
00587 ULONG ulFileOffset, const imagedata_type *pImg)
00588 {
00589
00590 if (!bSetDataOffset(pFile, ulFileOffset)) {
00591 return FALSE;
00592 }
00593
00594 vDecodeDIB(pDiag, pFile, pImg);
00595
00596 return TRUE;
00597 }