mirror of
https://github.com/simon987/antiword.git
synced 2025-04-10 13:06:41 +00:00
598 lines
14 KiB
C
598 lines
14 KiB
C
/*
|
|
* dib2sprt.c
|
|
* Copyright (C) 2000-2003 A.J. van Os; Released under GPL
|
|
*
|
|
* Description:
|
|
* Functions to translate dib pictures into sprites
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "DeskLib:Error.h"
|
|
#include "DeskLib:Sprite.h"
|
|
#include "antiword.h"
|
|
|
|
#if 0 /* defined(DEBUG) */
|
|
static int iPicCounter = 0;
|
|
#endif /* DEBUG */
|
|
|
|
|
|
/*
|
|
* iGetByteWidth - compute the number of bytes needed for a row of pixels
|
|
*/
|
|
static int
|
|
iGetByteWidth(const imagedata_type *pImg)
|
|
{
|
|
switch (pImg->uiBitsPerComponent) {
|
|
case 1:
|
|
return (pImg->iWidth + 31) / 32 * sizeof(int);
|
|
case 4:
|
|
return (pImg->iWidth + 7) / 8 * sizeof(int);
|
|
case 8:
|
|
case 24:
|
|
return (pImg->iWidth + 3) / 4 * sizeof(int);
|
|
default:
|
|
DBG_DEC(pImg->uiBitsPerComponent);
|
|
return 0;
|
|
}
|
|
} /* end of iGetByteWidth */
|
|
|
|
/*
|
|
* pCreateBlankSprite - Create a blank sprite.
|
|
*
|
|
* Create a blank sprite and add a palette if needed
|
|
*
|
|
* returns a pointer to the sprite when successful, otherwise NULL
|
|
*/
|
|
static sprite_areainfo *
|
|
pCreateBlankSprite(const imagedata_type *pImg, size_t *pSize)
|
|
{
|
|
sprite_areainfo *pArea;
|
|
UCHAR *pucTmp;
|
|
size_t tSize;
|
|
screen_modeval uMode;
|
|
int iIndex, iPaletteEntries;
|
|
|
|
TRACE_MSG("pCreateBlankSprite");
|
|
|
|
fail(pImg == NULL);
|
|
fail(pSize == NULL);
|
|
|
|
switch (pImg->uiBitsPerComponent) {
|
|
case 1:
|
|
uMode.screen_mode = 18;
|
|
iPaletteEntries = 2;
|
|
break;
|
|
case 4:
|
|
uMode.screen_mode = 20;
|
|
iPaletteEntries = 16;
|
|
break;
|
|
case 8:
|
|
case 24:
|
|
uMode.screen_mode = 21;
|
|
iPaletteEntries = 0;
|
|
break;
|
|
default:
|
|
DBG_DEC(pImg->uiBitsPerComponent);
|
|
return NULL;
|
|
}
|
|
fail(iPaletteEntries < 0 || iPaletteEntries > 16);
|
|
|
|
/* Get memory for the sprite */
|
|
tSize = sizeof(sprite_areainfo) +
|
|
Sprite_MemorySize(pImg->iWidth, pImg->iHeight, uMode,
|
|
iPaletteEntries > 0 ? sprite_HASPAL : sprite_HASNOMASKPAL);
|
|
DBG_DEC(tSize);
|
|
pArea = xmalloc(tSize);
|
|
|
|
/* Initialise sprite area */
|
|
pArea->areasize = tSize;
|
|
pArea->numsprites = 0;
|
|
pArea->firstoffset = sizeof(sprite_areainfo);
|
|
pArea->freeoffset = sizeof(sprite_areainfo);
|
|
|
|
/* Create a blank sprite */
|
|
Error_CheckFatal(Sprite_Create(pArea, "wordimage",
|
|
iPaletteEntries > 0 ? 1 : 0,
|
|
pImg->iWidth, pImg->iHeight, uMode));
|
|
|
|
/* Add the palette */
|
|
pucTmp = (UCHAR *)pArea + pArea->firstoffset + sizeof(sprite_header);
|
|
for (iIndex = 0; iIndex < iPaletteEntries; iIndex++) {
|
|
/* First color */
|
|
*pucTmp++ = 0;
|
|
*pucTmp++ = pImg->aucPalette[iIndex][0];
|
|
*pucTmp++ = pImg->aucPalette[iIndex][1];
|
|
*pucTmp++ = pImg->aucPalette[iIndex][2];
|
|
/* Second color */
|
|
*pucTmp++ = 0;
|
|
*pucTmp++ = pImg->aucPalette[iIndex][0];
|
|
*pucTmp++ = pImg->aucPalette[iIndex][1];
|
|
*pucTmp++ = pImg->aucPalette[iIndex][2];
|
|
}
|
|
|
|
*pSize = tSize;
|
|
return pArea;
|
|
} /* end of pCreateBlankSprite */
|
|
|
|
/*
|
|
* iReduceColor - reduce from 24 bit to 8 bit color
|
|
*
|
|
* Reduce 24 bit true colors to RISC OS default 256 color palette
|
|
*
|
|
* returns the resulting color
|
|
*/
|
|
static int
|
|
iReduceColor(int iRed, int iGreen, int iBlue)
|
|
{
|
|
int iResult;
|
|
|
|
iResult = (iBlue & 0x80) ? 0x80 : 0;
|
|
iResult |= (iGreen & 0x80) ? 0x40 : 0;
|
|
iResult |= (iGreen & 0x40) ? 0x20 : 0;
|
|
iResult |= (iRed & 0x80) ? 0x10 : 0;
|
|
iResult |= (iBlue & 0x40) ? 0x08 : 0;
|
|
iResult |= (iRed & 0x40) ? 0x04 : 0;
|
|
iResult |= ((iRed | iGreen | iBlue) & 0x20) ? 0x02 : 0;
|
|
iResult |= ((iRed | iGreen | iBlue) & 0x10) ? 0x01 : 0;
|
|
return iResult;
|
|
} /* end of iReduceColor */
|
|
|
|
/*
|
|
* vDecode1bpp - decode an uncompressed 1 bit per pixel image
|
|
*/
|
|
static void
|
|
vDecode1bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
|
|
{
|
|
int iX, iY, iByteWidth, iOffset, iTmp, iEighthWidth, iPadding;
|
|
UCHAR ucTmp;
|
|
|
|
DBG_MSG("vDecode1bpp");
|
|
|
|
fail(pFile == NULL);
|
|
fail(pucData == NULL);
|
|
fail(pImg == NULL);
|
|
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 2);
|
|
|
|
iByteWidth = iGetByteWidth(pImg);
|
|
|
|
iEighthWidth = (pImg->iWidth + 7) / 8;
|
|
iPadding = ROUND4(iEighthWidth) - iEighthWidth;
|
|
|
|
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
|
|
for (iX = 0; iX < iEighthWidth; iX++) {
|
|
iTmp = iNextByte(pFile);
|
|
if (iTmp == EOF) {
|
|
return;
|
|
}
|
|
/* Reverse the bit order */
|
|
ucTmp = (iTmp & BIT(0)) ? (UCHAR)BIT(7) : 0;
|
|
ucTmp |= (iTmp & BIT(1)) ? (UCHAR)BIT(6) : 0;
|
|
ucTmp |= (iTmp & BIT(2)) ? (UCHAR)BIT(5) : 0;
|
|
ucTmp |= (iTmp & BIT(3)) ? (UCHAR)BIT(4) : 0;
|
|
ucTmp |= (iTmp & BIT(4)) ? (UCHAR)BIT(3) : 0;
|
|
ucTmp |= (iTmp & BIT(5)) ? (UCHAR)BIT(2) : 0;
|
|
ucTmp |= (iTmp & BIT(6)) ? (UCHAR)BIT(1) : 0;
|
|
ucTmp |= (iTmp & BIT(7)) ? (UCHAR)BIT(0) : 0;
|
|
iOffset = iY * iByteWidth + iX;
|
|
*(pucData + iOffset) = ucTmp;
|
|
}
|
|
(void)tSkipBytes(pFile, iPadding);
|
|
}
|
|
} /* end of vDecode1bpp */
|
|
|
|
/*
|
|
* vDecode4bpp - decode an uncompressed 4 bits per pixel image
|
|
*/
|
|
static void
|
|
vDecode4bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
|
|
{
|
|
int iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth, iPadding;
|
|
UCHAR ucTmp;
|
|
|
|
DBG_MSG("vDecode4bpp");
|
|
|
|
fail(pFile == NULL);
|
|
fail(pucData == NULL);
|
|
fail(pImg == NULL);
|
|
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
|
|
|
|
iByteWidth = iGetByteWidth(pImg);
|
|
|
|
iHalfWidth = (pImg->iWidth + 1) / 2;
|
|
iPadding = ROUND4(iHalfWidth) - iHalfWidth;
|
|
|
|
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
|
|
for (iX = 0; iX < iHalfWidth; iX++) {
|
|
iTmp = iNextByte(pFile);
|
|
if (iTmp == EOF) {
|
|
return;
|
|
}
|
|
/* Reverse the nibble order */
|
|
ucTmp = (iTmp & 0xf0) >> 4;
|
|
ucTmp |= (iTmp & 0x0f) << 4;
|
|
iOffset = iY * iByteWidth + iX;
|
|
*(pucData + iOffset) = ucTmp;
|
|
}
|
|
(void)tSkipBytes(pFile, iPadding);
|
|
}
|
|
} /* end of vDecode4bpp */
|
|
|
|
/*
|
|
* vDecode8bpp - decode an uncompressed 8 bits per pixel image
|
|
*/
|
|
static void
|
|
vDecode8bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
|
|
{
|
|
int iX, iY, iByteWidth, iOffset, iIndex, iPadding;
|
|
|
|
DBG_MSG("vDecode8bpp");
|
|
|
|
fail(pFile == NULL);
|
|
fail(pucData == NULL);
|
|
fail(pImg == NULL);
|
|
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
|
|
|
|
iByteWidth = iGetByteWidth(pImg);
|
|
|
|
iPadding = ROUND4(pImg->iWidth) - pImg->iWidth;
|
|
|
|
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
|
|
for (iX = 0; iX < pImg->iWidth; iX++) {
|
|
iIndex = iNextByte(pFile);
|
|
if (iIndex == EOF) {
|
|
return;
|
|
}
|
|
iOffset = iY * iByteWidth + iX;
|
|
*(pucData + iOffset) = iReduceColor(
|
|
pImg->aucPalette[iIndex][0],
|
|
pImg->aucPalette[iIndex][1],
|
|
pImg->aucPalette[iIndex][2]);
|
|
}
|
|
(void)tSkipBytes(pFile, iPadding);
|
|
}
|
|
} /* end of vDecode8bpp */
|
|
|
|
/*
|
|
* vDecode24bpp - decode an uncompressed 24 bits per pixel image
|
|
*/
|
|
static void
|
|
vDecode24bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
|
|
{
|
|
int iX, iY, iTripleWidth, iByteWidth, iOffset, iPadding;
|
|
int iRed, iGreen, iBlue;
|
|
|
|
DBG_MSG("vDecode24bpp");
|
|
|
|
fail(pFile == NULL);
|
|
fail(pucData == NULL);
|
|
fail(pImg == NULL);
|
|
|
|
iByteWidth = iGetByteWidth(pImg);
|
|
|
|
iTripleWidth = pImg->iWidth * 3;
|
|
iPadding = ROUND4(iTripleWidth) - iTripleWidth;
|
|
|
|
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
|
|
for (iX = 0; iX < pImg->iWidth; iX++) {
|
|
iBlue = iNextByte(pFile);
|
|
if (iBlue == EOF) {
|
|
return;
|
|
}
|
|
iGreen = iNextByte(pFile);
|
|
if (iGreen == EOF) {
|
|
return;
|
|
}
|
|
iRed = iNextByte(pFile);
|
|
if (iRed == EOF) {
|
|
return;
|
|
}
|
|
iOffset = iY * iByteWidth + iX;
|
|
*(pucData + iOffset) =
|
|
iReduceColor(iRed, iGreen, iBlue);
|
|
}
|
|
(void)tSkipBytes(pFile, iPadding);
|
|
}
|
|
} /* end of vDecode24bpp */
|
|
|
|
/*
|
|
* vDecodeRle4 - decode a RLE compressed 4 bits per pixel image
|
|
*/
|
|
static void
|
|
vDecodeRle4(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
|
|
{
|
|
int iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth;
|
|
int iRun, iRunLength, iHalfRun;
|
|
BOOL bEOL;
|
|
UCHAR ucTmp;
|
|
|
|
DBG_MSG("vDecodeRle4");
|
|
|
|
fail(pFile == NULL);
|
|
fail(pucData == NULL);
|
|
fail(pImg == NULL);
|
|
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
|
|
|
|
DBG_DEC(pImg->iWidth);
|
|
DBG_DEC(pImg->iHeight);
|
|
|
|
iByteWidth = iGetByteWidth(pImg);
|
|
iHalfWidth = (pImg->iWidth + 1) / 2;
|
|
|
|
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
|
|
bEOL = FALSE;
|
|
iX = 0;
|
|
while (!bEOL) {
|
|
iRunLength = iNextByte(pFile);
|
|
if (iRunLength == EOF) {
|
|
return;
|
|
}
|
|
if (iRunLength != 0) {
|
|
/*
|
|
* Encoded packet:
|
|
* RunLength pixels, all the "same" value
|
|
*/
|
|
iTmp = iNextByte(pFile);
|
|
if (iTmp == EOF) {
|
|
return;
|
|
}
|
|
/* Reverse the nibble order */
|
|
ucTmp = (iTmp & 0xf0) >> 4;
|
|
ucTmp |= (iTmp & 0x0f) << 4;
|
|
iHalfRun = (iRunLength + 1) / 2;
|
|
for (iRun = 0; iRun < iHalfRun; iRun++) {
|
|
if (iX < iHalfWidth) {
|
|
iOffset = iY * iByteWidth + iX;
|
|
*(pucData + iOffset) = ucTmp;
|
|
}
|
|
iX++;
|
|
}
|
|
continue;
|
|
}
|
|
/* Literal or escape */
|
|
iRunLength = iNextByte(pFile);
|
|
if (iRunLength == EOF) {
|
|
return;
|
|
}
|
|
if (iRunLength == 0) { /* End of line escape */
|
|
bEOL = TRUE;
|
|
} else if (iRunLength == 1) { /* End of file escape */
|
|
return;
|
|
} else if (iRunLength == 2) { /* Delta escape */
|
|
DBG_MSG("RLE4: encountered delta escape");
|
|
return;
|
|
} else { /* Literal packet */
|
|
iHalfRun = (iRunLength + 1) / 2;
|
|
for (iRun = 0; iRun < iHalfRun; iRun++) {
|
|
iTmp = iNextByte(pFile);
|
|
if (iTmp == EOF) {
|
|
return;
|
|
}
|
|
/* Reverse the nibble order */
|
|
ucTmp = (iTmp & 0xf0) >> 4;
|
|
ucTmp |= (iTmp & 0x0f) << 4;
|
|
if (iX < iHalfWidth) {
|
|
iOffset = iY * iByteWidth + iX;
|
|
*(pucData + iOffset) = ucTmp;
|
|
}
|
|
iX++;
|
|
}
|
|
/* Padding if the number of bytes is odd */
|
|
if (odd(iHalfRun)) {
|
|
(void)tSkipBytes(pFile, 1);
|
|
}
|
|
}
|
|
}
|
|
DBG_DEC_C(iX != iHalfWidth, iX);
|
|
}
|
|
} /* end of vDecodeRle4 */
|
|
|
|
/*
|
|
* vDecodeRle8 - decode a RLE compressed 8 bits per pixel image
|
|
*/
|
|
static void
|
|
vDecodeRle8(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
|
|
{
|
|
int iX, iY, iRun, iRunLength, iOffset, iIndex, iByteWidth;
|
|
BOOL bEOL;
|
|
|
|
DBG_MSG("vDecodeRle8");
|
|
|
|
fail(pFile == NULL);
|
|
fail(pucData == NULL);
|
|
fail(pImg == NULL);
|
|
fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
|
|
|
|
DBG_DEC(pImg->iWidth);
|
|
DBG_DEC(pImg->iHeight);
|
|
|
|
iByteWidth = iGetByteWidth(pImg);
|
|
|
|
for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
|
|
bEOL = FALSE;
|
|
iX = 0;
|
|
while (!bEOL) {
|
|
iRunLength = iNextByte(pFile);
|
|
if (iRunLength == EOF) {
|
|
return;
|
|
}
|
|
if (iRunLength != 0) {
|
|
/*
|
|
* Encoded packet:
|
|
* RunLength pixels, all the same value
|
|
*/
|
|
iIndex = iNextByte(pFile);
|
|
if (iIndex == EOF) {
|
|
return;
|
|
}
|
|
for (iRun = 0; iRun < iRunLength; iRun++) {
|
|
if (iX < pImg->iWidth) {
|
|
iOffset = iY * iByteWidth + iX;
|
|
*(pucData + iOffset) =
|
|
iReduceColor(
|
|
pImg->aucPalette[iIndex][0],
|
|
pImg->aucPalette[iIndex][1],
|
|
pImg->aucPalette[iIndex][2]);
|
|
}
|
|
iX++;
|
|
}
|
|
continue;
|
|
}
|
|
/* Literal or escape */
|
|
iRunLength = iNextByte(pFile);
|
|
if (iRunLength == EOF) {
|
|
return;
|
|
}
|
|
if (iRunLength == 0) { /* End of line escape */
|
|
bEOL = TRUE;
|
|
} else if (iRunLength == 1) { /* End of file escape */
|
|
return;
|
|
} else if (iRunLength == 2) { /* Delta escape */
|
|
DBG_MSG("RLE8: encountered delta escape");
|
|
return;
|
|
} else { /* Literal packet */
|
|
for (iRun = 0; iRun < iRunLength; iRun++) {
|
|
iIndex = iNextByte(pFile);
|
|
if (iIndex == EOF) {
|
|
return;
|
|
}
|
|
if (iX < pImg->iWidth) {
|
|
iOffset = iY * iByteWidth + iX;
|
|
*(pucData + iOffset) =
|
|
iReduceColor(
|
|
pImg->aucPalette[iIndex][0],
|
|
pImg->aucPalette[iIndex][1],
|
|
pImg->aucPalette[iIndex][2]);
|
|
}
|
|
iX++;
|
|
}
|
|
/* Padding if the number of bytes is odd */
|
|
if (odd(iRunLength)) {
|
|
(void)tSkipBytes(pFile, 1);
|
|
}
|
|
}
|
|
}
|
|
DBG_DEC_C(iX != pImg->iWidth, iX);
|
|
}
|
|
} /* end of vDecodeRle8 */
|
|
|
|
#if 0 /* defined(DEBUG) */
|
|
static void
|
|
vCopy2File(UCHAR *pucSprite, size_t tSpriteSize)
|
|
{
|
|
FILE *pOutFile;
|
|
int iIndex;
|
|
char szFilename[30];
|
|
|
|
sprintf(szFilename, "<Wimp$ScrapDir>.sprt%04d", ++iPicCounter);
|
|
pOutFile = fopen(szFilename, "wb");
|
|
if (pOutFile == NULL) {
|
|
return;
|
|
}
|
|
DBG_MSG(szFilename);
|
|
for (iIndex = 4; iIndex < (int)tSpriteSize; iIndex++) {
|
|
if (putc(pucSprite[iIndex], pOutFile) == EOF) {
|
|
break;
|
|
}
|
|
}
|
|
(void)fclose(pOutFile);
|
|
vSetFiletype(szFilename, FILETYPE_SPRITE);
|
|
} /* end of vCopy2File */
|
|
#endif /* DEBUG */
|
|
|
|
/*
|
|
* vDecodeDIB - decode a dib picture
|
|
*/
|
|
static void
|
|
vDecodeDIB(diagram_type *pDiag, FILE *pFile, const imagedata_type *pImg)
|
|
{
|
|
sprite_areainfo *pSprite;
|
|
UCHAR *pucPalette, *pucData;
|
|
size_t tSpriteSize;
|
|
int iHeaderSize;
|
|
|
|
/* Skip the bitmap info header */
|
|
iHeaderSize = (int)ulNextLong(pFile);
|
|
(void)tSkipBytes(pFile, iHeaderSize - 4);
|
|
/* Skip the colortable */
|
|
if (pImg->uiBitsPerComponent <= 8) {
|
|
(void)tSkipBytes(pFile,
|
|
pImg->iColorsUsed * ((iHeaderSize > 12) ? 4 : 3));
|
|
}
|
|
|
|
/* Create an blank sprite */
|
|
pSprite = pCreateBlankSprite(pImg, &tSpriteSize);
|
|
pucPalette = (UCHAR *)pSprite +
|
|
pSprite->firstoffset + sizeof(sprite_header);
|
|
|
|
/* Add the pixel information */
|
|
switch (pImg->uiBitsPerComponent) {
|
|
case 1:
|
|
fail(pImg->eCompression != compression_none);
|
|
pucData = pucPalette + 2 * 8;
|
|
vDecode1bpp(pFile, pucData, pImg);
|
|
break;
|
|
case 4:
|
|
fail(pImg->eCompression != compression_none &&
|
|
pImg->eCompression != compression_rle4);
|
|
pucData = pucPalette + 16 * 8;
|
|
if (pImg->eCompression == compression_rle4) {
|
|
vDecodeRle4(pFile, pucData, pImg);
|
|
} else {
|
|
vDecode4bpp(pFile, pucData, pImg);
|
|
}
|
|
break;
|
|
case 8:
|
|
fail(pImg->eCompression != compression_none &&
|
|
pImg->eCompression != compression_rle8);
|
|
pucData = pucPalette + 0 * 8;
|
|
if (pImg->eCompression == compression_rle8) {
|
|
vDecodeRle8(pFile, pucData, pImg);
|
|
} else {
|
|
vDecode8bpp(pFile, pucData, pImg);
|
|
}
|
|
break;
|
|
case 24:
|
|
fail(pImg->eCompression != compression_none);
|
|
pucData = pucPalette + 0 * 8;
|
|
vDecode24bpp(pFile, pucData, pImg);
|
|
break;
|
|
default:
|
|
DBG_DEC(pImg->uiBitsPerComponent);
|
|
break;
|
|
}
|
|
|
|
#if 0 /* defined(DEBUG) */
|
|
vCopy2File((UCHAR *)pSprite, tSpriteSize);
|
|
#endif /* DEBUG */
|
|
|
|
/* Add the sprite to the Draw file */
|
|
vImage2Diagram(pDiag, pImg,
|
|
(UCHAR *)pSprite + pSprite->firstoffset,
|
|
tSpriteSize - pSprite->firstoffset);
|
|
|
|
/* Clean up before you leave */
|
|
pSprite = xfree(pSprite);
|
|
} /* end of vDecodeDIB */
|
|
|
|
/*
|
|
* bTranslateDIB - translate a DIB picture
|
|
*
|
|
* This function translates a picture from dib to sprite
|
|
*
|
|
* return TRUE when sucessful, otherwise FALSE
|
|
*/
|
|
BOOL
|
|
bTranslateDIB(diagram_type *pDiag, FILE *pFile,
|
|
ULONG ulFileOffset, const imagedata_type *pImg)
|
|
{
|
|
/* Seek to start position of DIB data */
|
|
if (!bSetDataOffset(pFile, ulFileOffset)) {
|
|
return FALSE;
|
|
}
|
|
|
|
vDecodeDIB(pDiag, pFile, pImg);
|
|
|
|
return TRUE;
|
|
} /* end of bTranslateDIB */
|