1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier * dib2sprt.c
3f5736e95SDavid du Colombier * Copyright (C) 2000-2003 A.J. van Os; Released under GPL
4f5736e95SDavid du Colombier *
5f5736e95SDavid du Colombier * Description:
6f5736e95SDavid du Colombier * Functions to translate dib pictures into sprites
7f5736e95SDavid du Colombier */
8f5736e95SDavid du Colombier
9f5736e95SDavid du Colombier #include <stdio.h>
10f5736e95SDavid du Colombier #include <string.h>
11*25b329d5SDavid du Colombier #include "DeskLib:Error.h"
12*25b329d5SDavid du Colombier #include "DeskLib:Sprite.h"
13f5736e95SDavid du Colombier #include "antiword.h"
14f5736e95SDavid du Colombier
15f5736e95SDavid du Colombier #if 0 /* defined(DEBUG) */
16f5736e95SDavid du Colombier static int iPicCounter = 0;
17f5736e95SDavid du Colombier #endif /* DEBUG */
18f5736e95SDavid du Colombier
19f5736e95SDavid du Colombier
20f5736e95SDavid du Colombier /*
21f5736e95SDavid du Colombier * iGetByteWidth - compute the number of bytes needed for a row of pixels
22f5736e95SDavid du Colombier */
23f5736e95SDavid du Colombier static int
iGetByteWidth(const imagedata_type * pImg)24f5736e95SDavid du Colombier iGetByteWidth(const imagedata_type *pImg)
25f5736e95SDavid du Colombier {
26f5736e95SDavid du Colombier switch (pImg->uiBitsPerComponent) {
27f5736e95SDavid du Colombier case 1:
28f5736e95SDavid du Colombier return (pImg->iWidth + 31) / 32 * sizeof(int);
29f5736e95SDavid du Colombier case 4:
30f5736e95SDavid du Colombier return (pImg->iWidth + 7) / 8 * sizeof(int);
31f5736e95SDavid du Colombier case 8:
32f5736e95SDavid du Colombier case 24:
33f5736e95SDavid du Colombier return (pImg->iWidth + 3) / 4 * sizeof(int);
34f5736e95SDavid du Colombier default:
35f5736e95SDavid du Colombier DBG_DEC(pImg->uiBitsPerComponent);
36f5736e95SDavid du Colombier return 0;
37f5736e95SDavid du Colombier }
38f5736e95SDavid du Colombier } /* end of iGetByteWidth */
39f5736e95SDavid du Colombier
40f5736e95SDavid du Colombier /*
41*25b329d5SDavid du Colombier * pCreateBlankSprite - Create a blank sprite.
42f5736e95SDavid du Colombier *
43f5736e95SDavid du Colombier * Create a blank sprite and add a palette if needed
44f5736e95SDavid du Colombier *
45f5736e95SDavid du Colombier * returns a pointer to the sprite when successful, otherwise NULL
46f5736e95SDavid du Colombier */
47*25b329d5SDavid du Colombier static sprite_areainfo *
pCreateBlankSprite(const imagedata_type * pImg,size_t * pSize)48*25b329d5SDavid du Colombier pCreateBlankSprite(const imagedata_type *pImg, size_t *pSize)
49f5736e95SDavid du Colombier {
50*25b329d5SDavid du Colombier sprite_areainfo *pArea;
51f5736e95SDavid du Colombier UCHAR *pucTmp;
52f5736e95SDavid du Colombier size_t tSize;
53*25b329d5SDavid du Colombier screen_modeval uMode;
54*25b329d5SDavid du Colombier int iIndex, iPaletteEntries;
55f5736e95SDavid du Colombier
56*25b329d5SDavid du Colombier TRACE_MSG("pCreateBlankSprite");
57f5736e95SDavid du Colombier
58f5736e95SDavid du Colombier fail(pImg == NULL);
59*25b329d5SDavid du Colombier fail(pSize == NULL);
60f5736e95SDavid du Colombier
61f5736e95SDavid du Colombier switch (pImg->uiBitsPerComponent) {
62f5736e95SDavid du Colombier case 1:
63*25b329d5SDavid du Colombier uMode.screen_mode = 18;
64f5736e95SDavid du Colombier iPaletteEntries = 2;
65f5736e95SDavid du Colombier break;
66f5736e95SDavid du Colombier case 4:
67*25b329d5SDavid du Colombier uMode.screen_mode = 20;
68f5736e95SDavid du Colombier iPaletteEntries = 16;
69f5736e95SDavid du Colombier break;
70f5736e95SDavid du Colombier case 8:
71f5736e95SDavid du Colombier case 24:
72*25b329d5SDavid du Colombier uMode.screen_mode = 21;
73f5736e95SDavid du Colombier iPaletteEntries = 0;
74f5736e95SDavid du Colombier break;
75f5736e95SDavid du Colombier default:
76f5736e95SDavid du Colombier DBG_DEC(pImg->uiBitsPerComponent);
77f5736e95SDavid du Colombier return NULL;
78f5736e95SDavid du Colombier }
79f5736e95SDavid du Colombier fail(iPaletteEntries < 0 || iPaletteEntries > 16);
80f5736e95SDavid du Colombier
81*25b329d5SDavid du Colombier /* Get memory for the sprite */
82*25b329d5SDavid du Colombier tSize = sizeof(sprite_areainfo) +
83*25b329d5SDavid du Colombier Sprite_MemorySize(pImg->iWidth, pImg->iHeight, uMode,
84*25b329d5SDavid du Colombier iPaletteEntries > 0 ? sprite_HASPAL : sprite_HASNOMASKPAL);
85f5736e95SDavid du Colombier DBG_DEC(tSize);
86f5736e95SDavid du Colombier pArea = xmalloc(tSize);
87f5736e95SDavid du Colombier
88*25b329d5SDavid du Colombier /* Initialise sprite area */
89*25b329d5SDavid du Colombier pArea->areasize = tSize;
90*25b329d5SDavid du Colombier pArea->numsprites = 0;
91*25b329d5SDavid du Colombier pArea->firstoffset = sizeof(sprite_areainfo);
92*25b329d5SDavid du Colombier pArea->freeoffset = sizeof(sprite_areainfo);
93*25b329d5SDavid du Colombier
94*25b329d5SDavid du Colombier /* Create a blank sprite */
95*25b329d5SDavid du Colombier Error_CheckFatal(Sprite_Create(pArea, "wordimage",
96*25b329d5SDavid du Colombier iPaletteEntries > 0 ? 1 : 0,
97*25b329d5SDavid du Colombier pImg->iWidth, pImg->iHeight, uMode));
98f5736e95SDavid du Colombier
99f5736e95SDavid du Colombier /* Add the palette */
100*25b329d5SDavid du Colombier pucTmp = (UCHAR *)pArea + pArea->firstoffset + sizeof(sprite_header);
101f5736e95SDavid du Colombier for (iIndex = 0; iIndex < iPaletteEntries; iIndex++) {
102f5736e95SDavid du Colombier /* First color */
103f5736e95SDavid du Colombier *pucTmp++ = 0;
104f5736e95SDavid du Colombier *pucTmp++ = pImg->aucPalette[iIndex][0];
105f5736e95SDavid du Colombier *pucTmp++ = pImg->aucPalette[iIndex][1];
106f5736e95SDavid du Colombier *pucTmp++ = pImg->aucPalette[iIndex][2];
107f5736e95SDavid du Colombier /* Second color */
108f5736e95SDavid du Colombier *pucTmp++ = 0;
109f5736e95SDavid du Colombier *pucTmp++ = pImg->aucPalette[iIndex][0];
110f5736e95SDavid du Colombier *pucTmp++ = pImg->aucPalette[iIndex][1];
111f5736e95SDavid du Colombier *pucTmp++ = pImg->aucPalette[iIndex][2];
112f5736e95SDavid du Colombier }
113f5736e95SDavid du Colombier
114*25b329d5SDavid du Colombier *pSize = tSize;
115*25b329d5SDavid du Colombier return pArea;
116*25b329d5SDavid du Colombier } /* end of pCreateBlankSprite */
117f5736e95SDavid du Colombier
118f5736e95SDavid du Colombier /*
119f5736e95SDavid du Colombier * iReduceColor - reduce from 24 bit to 8 bit color
120f5736e95SDavid du Colombier *
121f5736e95SDavid du Colombier * Reduce 24 bit true colors to RISC OS default 256 color palette
122f5736e95SDavid du Colombier *
123f5736e95SDavid du Colombier * returns the resulting color
124f5736e95SDavid du Colombier */
125f5736e95SDavid du Colombier static int
iReduceColor(int iRed,int iGreen,int iBlue)126f5736e95SDavid du Colombier iReduceColor(int iRed, int iGreen, int iBlue)
127f5736e95SDavid du Colombier {
128f5736e95SDavid du Colombier int iResult;
129f5736e95SDavid du Colombier
130f5736e95SDavid du Colombier iResult = (iBlue & 0x80) ? 0x80 : 0;
131f5736e95SDavid du Colombier iResult |= (iGreen & 0x80) ? 0x40 : 0;
132f5736e95SDavid du Colombier iResult |= (iGreen & 0x40) ? 0x20 : 0;
133f5736e95SDavid du Colombier iResult |= (iRed & 0x80) ? 0x10 : 0;
134f5736e95SDavid du Colombier iResult |= (iBlue & 0x40) ? 0x08 : 0;
135f5736e95SDavid du Colombier iResult |= (iRed & 0x40) ? 0x04 : 0;
136f5736e95SDavid du Colombier iResult |= ((iRed | iGreen | iBlue) & 0x20) ? 0x02 : 0;
137f5736e95SDavid du Colombier iResult |= ((iRed | iGreen | iBlue) & 0x10) ? 0x01 : 0;
138f5736e95SDavid du Colombier return iResult;
139f5736e95SDavid du Colombier } /* end of iReduceColor */
140f5736e95SDavid du Colombier
141f5736e95SDavid du Colombier /*
142f5736e95SDavid du Colombier * vDecode1bpp - decode an uncompressed 1 bit per pixel image
143f5736e95SDavid du Colombier */
144f5736e95SDavid du Colombier static void
vDecode1bpp(FILE * pFile,UCHAR * pucData,const imagedata_type * pImg)145f5736e95SDavid du Colombier vDecode1bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
146f5736e95SDavid du Colombier {
147f5736e95SDavid du Colombier int iX, iY, iByteWidth, iOffset, iTmp, iEighthWidth, iPadding;
148f5736e95SDavid du Colombier UCHAR ucTmp;
149f5736e95SDavid du Colombier
150f5736e95SDavid du Colombier DBG_MSG("vDecode1bpp");
151f5736e95SDavid du Colombier
152f5736e95SDavid du Colombier fail(pFile == NULL);
153f5736e95SDavid du Colombier fail(pucData == NULL);
154f5736e95SDavid du Colombier fail(pImg == NULL);
155f5736e95SDavid du Colombier fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 2);
156f5736e95SDavid du Colombier
157f5736e95SDavid du Colombier iByteWidth = iGetByteWidth(pImg);
158f5736e95SDavid du Colombier
159f5736e95SDavid du Colombier iEighthWidth = (pImg->iWidth + 7) / 8;
160f5736e95SDavid du Colombier iPadding = ROUND4(iEighthWidth) - iEighthWidth;
161f5736e95SDavid du Colombier
162f5736e95SDavid du Colombier for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
163f5736e95SDavid du Colombier for (iX = 0; iX < iEighthWidth; iX++) {
164f5736e95SDavid du Colombier iTmp = iNextByte(pFile);
165f5736e95SDavid du Colombier if (iTmp == EOF) {
166f5736e95SDavid du Colombier return;
167f5736e95SDavid du Colombier }
168f5736e95SDavid du Colombier /* Reverse the bit order */
169f5736e95SDavid du Colombier ucTmp = (iTmp & BIT(0)) ? (UCHAR)BIT(7) : 0;
170f5736e95SDavid du Colombier ucTmp |= (iTmp & BIT(1)) ? (UCHAR)BIT(6) : 0;
171f5736e95SDavid du Colombier ucTmp |= (iTmp & BIT(2)) ? (UCHAR)BIT(5) : 0;
172f5736e95SDavid du Colombier ucTmp |= (iTmp & BIT(3)) ? (UCHAR)BIT(4) : 0;
173f5736e95SDavid du Colombier ucTmp |= (iTmp & BIT(4)) ? (UCHAR)BIT(3) : 0;
174f5736e95SDavid du Colombier ucTmp |= (iTmp & BIT(5)) ? (UCHAR)BIT(2) : 0;
175f5736e95SDavid du Colombier ucTmp |= (iTmp & BIT(6)) ? (UCHAR)BIT(1) : 0;
176f5736e95SDavid du Colombier ucTmp |= (iTmp & BIT(7)) ? (UCHAR)BIT(0) : 0;
177f5736e95SDavid du Colombier iOffset = iY * iByteWidth + iX;
178f5736e95SDavid du Colombier *(pucData + iOffset) = ucTmp;
179f5736e95SDavid du Colombier }
180f5736e95SDavid du Colombier (void)tSkipBytes(pFile, iPadding);
181f5736e95SDavid du Colombier }
182f5736e95SDavid du Colombier } /* end of vDecode1bpp */
183f5736e95SDavid du Colombier
184f5736e95SDavid du Colombier /*
185f5736e95SDavid du Colombier * vDecode4bpp - decode an uncompressed 4 bits per pixel image
186f5736e95SDavid du Colombier */
187f5736e95SDavid du Colombier static void
vDecode4bpp(FILE * pFile,UCHAR * pucData,const imagedata_type * pImg)188f5736e95SDavid du Colombier vDecode4bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
189f5736e95SDavid du Colombier {
190f5736e95SDavid du Colombier int iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth, iPadding;
191f5736e95SDavid du Colombier UCHAR ucTmp;
192f5736e95SDavid du Colombier
193f5736e95SDavid du Colombier DBG_MSG("vDecode4bpp");
194f5736e95SDavid du Colombier
195f5736e95SDavid du Colombier fail(pFile == NULL);
196f5736e95SDavid du Colombier fail(pucData == NULL);
197f5736e95SDavid du Colombier fail(pImg == NULL);
198f5736e95SDavid du Colombier fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
199f5736e95SDavid du Colombier
200f5736e95SDavid du Colombier iByteWidth = iGetByteWidth(pImg);
201f5736e95SDavid du Colombier
202f5736e95SDavid du Colombier iHalfWidth = (pImg->iWidth + 1) / 2;
203f5736e95SDavid du Colombier iPadding = ROUND4(iHalfWidth) - iHalfWidth;
204f5736e95SDavid du Colombier
205f5736e95SDavid du Colombier for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
206f5736e95SDavid du Colombier for (iX = 0; iX < iHalfWidth; iX++) {
207f5736e95SDavid du Colombier iTmp = iNextByte(pFile);
208f5736e95SDavid du Colombier if (iTmp == EOF) {
209f5736e95SDavid du Colombier return;
210f5736e95SDavid du Colombier }
211f5736e95SDavid du Colombier /* Reverse the nibble order */
212f5736e95SDavid du Colombier ucTmp = (iTmp & 0xf0) >> 4;
213f5736e95SDavid du Colombier ucTmp |= (iTmp & 0x0f) << 4;
214f5736e95SDavid du Colombier iOffset = iY * iByteWidth + iX;
215f5736e95SDavid du Colombier *(pucData + iOffset) = ucTmp;
216f5736e95SDavid du Colombier }
217f5736e95SDavid du Colombier (void)tSkipBytes(pFile, iPadding);
218f5736e95SDavid du Colombier }
219f5736e95SDavid du Colombier } /* end of vDecode4bpp */
220f5736e95SDavid du Colombier
221f5736e95SDavid du Colombier /*
222f5736e95SDavid du Colombier * vDecode8bpp - decode an uncompressed 8 bits per pixel image
223f5736e95SDavid du Colombier */
224f5736e95SDavid du Colombier static void
vDecode8bpp(FILE * pFile,UCHAR * pucData,const imagedata_type * pImg)225f5736e95SDavid du Colombier vDecode8bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
226f5736e95SDavid du Colombier {
227f5736e95SDavid du Colombier int iX, iY, iByteWidth, iOffset, iIndex, iPadding;
228f5736e95SDavid du Colombier
229f5736e95SDavid du Colombier DBG_MSG("vDecode8bpp");
230f5736e95SDavid du Colombier
231f5736e95SDavid du Colombier fail(pFile == NULL);
232f5736e95SDavid du Colombier fail(pucData == NULL);
233f5736e95SDavid du Colombier fail(pImg == NULL);
234f5736e95SDavid du Colombier fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
235f5736e95SDavid du Colombier
236f5736e95SDavid du Colombier iByteWidth = iGetByteWidth(pImg);
237f5736e95SDavid du Colombier
238f5736e95SDavid du Colombier iPadding = ROUND4(pImg->iWidth) - pImg->iWidth;
239f5736e95SDavid du Colombier
240f5736e95SDavid du Colombier for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
241f5736e95SDavid du Colombier for (iX = 0; iX < pImg->iWidth; iX++) {
242f5736e95SDavid du Colombier iIndex = iNextByte(pFile);
243f5736e95SDavid du Colombier if (iIndex == EOF) {
244f5736e95SDavid du Colombier return;
245f5736e95SDavid du Colombier }
246f5736e95SDavid du Colombier iOffset = iY * iByteWidth + iX;
247f5736e95SDavid du Colombier *(pucData + iOffset) = iReduceColor(
248f5736e95SDavid du Colombier pImg->aucPalette[iIndex][0],
249f5736e95SDavid du Colombier pImg->aucPalette[iIndex][1],
250f5736e95SDavid du Colombier pImg->aucPalette[iIndex][2]);
251f5736e95SDavid du Colombier }
252f5736e95SDavid du Colombier (void)tSkipBytes(pFile, iPadding);
253f5736e95SDavid du Colombier }
254f5736e95SDavid du Colombier } /* end of vDecode8bpp */
255f5736e95SDavid du Colombier
256f5736e95SDavid du Colombier /*
257f5736e95SDavid du Colombier * vDecode24bpp - decode an uncompressed 24 bits per pixel image
258f5736e95SDavid du Colombier */
259f5736e95SDavid du Colombier static void
vDecode24bpp(FILE * pFile,UCHAR * pucData,const imagedata_type * pImg)260f5736e95SDavid du Colombier vDecode24bpp(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
261f5736e95SDavid du Colombier {
262f5736e95SDavid du Colombier int iX, iY, iTripleWidth, iByteWidth, iOffset, iPadding;
263f5736e95SDavid du Colombier int iRed, iGreen, iBlue;
264f5736e95SDavid du Colombier
265f5736e95SDavid du Colombier DBG_MSG("vDecode24bpp");
266f5736e95SDavid du Colombier
267f5736e95SDavid du Colombier fail(pFile == NULL);
268f5736e95SDavid du Colombier fail(pucData == NULL);
269f5736e95SDavid du Colombier fail(pImg == NULL);
270f5736e95SDavid du Colombier
271f5736e95SDavid du Colombier iByteWidth = iGetByteWidth(pImg);
272f5736e95SDavid du Colombier
273f5736e95SDavid du Colombier iTripleWidth = pImg->iWidth * 3;
274f5736e95SDavid du Colombier iPadding = ROUND4(iTripleWidth) - iTripleWidth;
275f5736e95SDavid du Colombier
276f5736e95SDavid du Colombier for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
277f5736e95SDavid du Colombier for (iX = 0; iX < pImg->iWidth; iX++) {
278f5736e95SDavid du Colombier iBlue = iNextByte(pFile);
279f5736e95SDavid du Colombier if (iBlue == EOF) {
280f5736e95SDavid du Colombier return;
281f5736e95SDavid du Colombier }
282f5736e95SDavid du Colombier iGreen = iNextByte(pFile);
283f5736e95SDavid du Colombier if (iGreen == EOF) {
284f5736e95SDavid du Colombier return;
285f5736e95SDavid du Colombier }
286f5736e95SDavid du Colombier iRed = iNextByte(pFile);
287f5736e95SDavid du Colombier if (iRed == EOF) {
288f5736e95SDavid du Colombier return;
289f5736e95SDavid du Colombier }
290f5736e95SDavid du Colombier iOffset = iY * iByteWidth + iX;
291f5736e95SDavid du Colombier *(pucData + iOffset) =
292f5736e95SDavid du Colombier iReduceColor(iRed, iGreen, iBlue);
293f5736e95SDavid du Colombier }
294f5736e95SDavid du Colombier (void)tSkipBytes(pFile, iPadding);
295f5736e95SDavid du Colombier }
296f5736e95SDavid du Colombier } /* end of vDecode24bpp */
297f5736e95SDavid du Colombier
298f5736e95SDavid du Colombier /*
299f5736e95SDavid du Colombier * vDecodeRle4 - decode a RLE compressed 4 bits per pixel image
300f5736e95SDavid du Colombier */
301f5736e95SDavid du Colombier static void
vDecodeRle4(FILE * pFile,UCHAR * pucData,const imagedata_type * pImg)302f5736e95SDavid du Colombier vDecodeRle4(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
303f5736e95SDavid du Colombier {
304f5736e95SDavid du Colombier int iX, iY, iByteWidth, iOffset, iTmp, iHalfWidth;
305f5736e95SDavid du Colombier int iRun, iRunLength, iHalfRun;
306f5736e95SDavid du Colombier BOOL bEOL;
307f5736e95SDavid du Colombier UCHAR ucTmp;
308f5736e95SDavid du Colombier
309f5736e95SDavid du Colombier DBG_MSG("vDecodeRle4");
310f5736e95SDavid du Colombier
311f5736e95SDavid du Colombier fail(pFile == NULL);
312f5736e95SDavid du Colombier fail(pucData == NULL);
313f5736e95SDavid du Colombier fail(pImg == NULL);
314f5736e95SDavid du Colombier fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
315f5736e95SDavid du Colombier
316f5736e95SDavid du Colombier DBG_DEC(pImg->iWidth);
317f5736e95SDavid du Colombier DBG_DEC(pImg->iHeight);
318f5736e95SDavid du Colombier
319f5736e95SDavid du Colombier iByteWidth = iGetByteWidth(pImg);
320f5736e95SDavid du Colombier iHalfWidth = (pImg->iWidth + 1) / 2;
321f5736e95SDavid du Colombier
322f5736e95SDavid du Colombier for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
323f5736e95SDavid du Colombier bEOL = FALSE;
324f5736e95SDavid du Colombier iX = 0;
325f5736e95SDavid du Colombier while (!bEOL) {
326f5736e95SDavid du Colombier iRunLength = iNextByte(pFile);
327f5736e95SDavid du Colombier if (iRunLength == EOF) {
328f5736e95SDavid du Colombier return;
329f5736e95SDavid du Colombier }
330f5736e95SDavid du Colombier if (iRunLength != 0) {
331f5736e95SDavid du Colombier /*
332f5736e95SDavid du Colombier * Encoded packet:
333f5736e95SDavid du Colombier * RunLength pixels, all the "same" value
334f5736e95SDavid du Colombier */
335f5736e95SDavid du Colombier iTmp = iNextByte(pFile);
336f5736e95SDavid du Colombier if (iTmp == EOF) {
337f5736e95SDavid du Colombier return;
338f5736e95SDavid du Colombier }
339f5736e95SDavid du Colombier /* Reverse the nibble order */
340f5736e95SDavid du Colombier ucTmp = (iTmp & 0xf0) >> 4;
341f5736e95SDavid du Colombier ucTmp |= (iTmp & 0x0f) << 4;
342f5736e95SDavid du Colombier iHalfRun = (iRunLength + 1) / 2;
343f5736e95SDavid du Colombier for (iRun = 0; iRun < iHalfRun; iRun++) {
344f5736e95SDavid du Colombier if (iX < iHalfWidth) {
345f5736e95SDavid du Colombier iOffset = iY * iByteWidth + iX;
346f5736e95SDavid du Colombier *(pucData + iOffset) = ucTmp;
347f5736e95SDavid du Colombier }
348f5736e95SDavid du Colombier iX++;
349f5736e95SDavid du Colombier }
350f5736e95SDavid du Colombier continue;
351f5736e95SDavid du Colombier }
352f5736e95SDavid du Colombier /* Literal or escape */
353f5736e95SDavid du Colombier iRunLength = iNextByte(pFile);
354f5736e95SDavid du Colombier if (iRunLength == EOF) {
355f5736e95SDavid du Colombier return;
356f5736e95SDavid du Colombier }
357f5736e95SDavid du Colombier if (iRunLength == 0) { /* End of line escape */
358f5736e95SDavid du Colombier bEOL = TRUE;
359f5736e95SDavid du Colombier } else if (iRunLength == 1) { /* End of file escape */
360f5736e95SDavid du Colombier return;
361f5736e95SDavid du Colombier } else if (iRunLength == 2) { /* Delta escape */
362f5736e95SDavid du Colombier DBG_MSG("RLE4: encountered delta escape");
363f5736e95SDavid du Colombier return;
364f5736e95SDavid du Colombier } else { /* Literal packet */
365f5736e95SDavid du Colombier iHalfRun = (iRunLength + 1) / 2;
366f5736e95SDavid du Colombier for (iRun = 0; iRun < iHalfRun; iRun++) {
367f5736e95SDavid du Colombier iTmp = iNextByte(pFile);
368f5736e95SDavid du Colombier if (iTmp == EOF) {
369f5736e95SDavid du Colombier return;
370f5736e95SDavid du Colombier }
371f5736e95SDavid du Colombier /* Reverse the nibble order */
372f5736e95SDavid du Colombier ucTmp = (iTmp & 0xf0) >> 4;
373f5736e95SDavid du Colombier ucTmp |= (iTmp & 0x0f) << 4;
374f5736e95SDavid du Colombier if (iX < iHalfWidth) {
375f5736e95SDavid du Colombier iOffset = iY * iByteWidth + iX;
376f5736e95SDavid du Colombier *(pucData + iOffset) = ucTmp;
377f5736e95SDavid du Colombier }
378f5736e95SDavid du Colombier iX++;
379f5736e95SDavid du Colombier }
380f5736e95SDavid du Colombier /* Padding if the number of bytes is odd */
381f5736e95SDavid du Colombier if (odd(iHalfRun)) {
382f5736e95SDavid du Colombier (void)tSkipBytes(pFile, 1);
383f5736e95SDavid du Colombier }
384f5736e95SDavid du Colombier }
385f5736e95SDavid du Colombier }
386f5736e95SDavid du Colombier DBG_DEC_C(iX != iHalfWidth, iX);
387f5736e95SDavid du Colombier }
388f5736e95SDavid du Colombier } /* end of vDecodeRle4 */
389f5736e95SDavid du Colombier
390f5736e95SDavid du Colombier /*
391f5736e95SDavid du Colombier * vDecodeRle8 - decode a RLE compressed 8 bits per pixel image
392f5736e95SDavid du Colombier */
393f5736e95SDavid du Colombier static void
vDecodeRle8(FILE * pFile,UCHAR * pucData,const imagedata_type * pImg)394f5736e95SDavid du Colombier vDecodeRle8(FILE *pFile, UCHAR *pucData, const imagedata_type *pImg)
395f5736e95SDavid du Colombier {
396f5736e95SDavid du Colombier int iX, iY, iRun, iRunLength, iOffset, iIndex, iByteWidth;
397f5736e95SDavid du Colombier BOOL bEOL;
398f5736e95SDavid du Colombier
399f5736e95SDavid du Colombier DBG_MSG("vDecodeRle8");
400f5736e95SDavid du Colombier
401f5736e95SDavid du Colombier fail(pFile == NULL);
402f5736e95SDavid du Colombier fail(pucData == NULL);
403f5736e95SDavid du Colombier fail(pImg == NULL);
404f5736e95SDavid du Colombier fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
405f5736e95SDavid du Colombier
406f5736e95SDavid du Colombier DBG_DEC(pImg->iWidth);
407f5736e95SDavid du Colombier DBG_DEC(pImg->iHeight);
408f5736e95SDavid du Colombier
409f5736e95SDavid du Colombier iByteWidth = iGetByteWidth(pImg);
410f5736e95SDavid du Colombier
411f5736e95SDavid du Colombier for (iY = pImg->iHeight - 1; iY >= 0; iY--) {
412f5736e95SDavid du Colombier bEOL = FALSE;
413f5736e95SDavid du Colombier iX = 0;
414f5736e95SDavid du Colombier while (!bEOL) {
415f5736e95SDavid du Colombier iRunLength = iNextByte(pFile);
416f5736e95SDavid du Colombier if (iRunLength == EOF) {
417f5736e95SDavid du Colombier return;
418f5736e95SDavid du Colombier }
419f5736e95SDavid du Colombier if (iRunLength != 0) {
420f5736e95SDavid du Colombier /*
421f5736e95SDavid du Colombier * Encoded packet:
422f5736e95SDavid du Colombier * RunLength pixels, all the same value
423f5736e95SDavid du Colombier */
424f5736e95SDavid du Colombier iIndex = iNextByte(pFile);
425f5736e95SDavid du Colombier if (iIndex == EOF) {
426f5736e95SDavid du Colombier return;
427f5736e95SDavid du Colombier }
428f5736e95SDavid du Colombier for (iRun = 0; iRun < iRunLength; iRun++) {
429f5736e95SDavid du Colombier if (iX < pImg->iWidth) {
430f5736e95SDavid du Colombier iOffset = iY * iByteWidth + iX;
431f5736e95SDavid du Colombier *(pucData + iOffset) =
432f5736e95SDavid du Colombier iReduceColor(
433f5736e95SDavid du Colombier pImg->aucPalette[iIndex][0],
434f5736e95SDavid du Colombier pImg->aucPalette[iIndex][1],
435f5736e95SDavid du Colombier pImg->aucPalette[iIndex][2]);
436f5736e95SDavid du Colombier }
437f5736e95SDavid du Colombier iX++;
438f5736e95SDavid du Colombier }
439f5736e95SDavid du Colombier continue;
440f5736e95SDavid du Colombier }
441f5736e95SDavid du Colombier /* Literal or escape */
442f5736e95SDavid du Colombier iRunLength = iNextByte(pFile);
443f5736e95SDavid du Colombier if (iRunLength == EOF) {
444f5736e95SDavid du Colombier return;
445f5736e95SDavid du Colombier }
446f5736e95SDavid du Colombier if (iRunLength == 0) { /* End of line escape */
447f5736e95SDavid du Colombier bEOL = TRUE;
448f5736e95SDavid du Colombier } else if (iRunLength == 1) { /* End of file escape */
449f5736e95SDavid du Colombier return;
450f5736e95SDavid du Colombier } else if (iRunLength == 2) { /* Delta escape */
451f5736e95SDavid du Colombier DBG_MSG("RLE8: encountered delta escape");
452f5736e95SDavid du Colombier return;
453f5736e95SDavid du Colombier } else { /* Literal packet */
454f5736e95SDavid du Colombier for (iRun = 0; iRun < iRunLength; iRun++) {
455f5736e95SDavid du Colombier iIndex = iNextByte(pFile);
456f5736e95SDavid du Colombier if (iIndex == EOF) {
457f5736e95SDavid du Colombier return;
458f5736e95SDavid du Colombier }
459f5736e95SDavid du Colombier if (iX < pImg->iWidth) {
460f5736e95SDavid du Colombier iOffset = iY * iByteWidth + iX;
461f5736e95SDavid du Colombier *(pucData + iOffset) =
462f5736e95SDavid du Colombier iReduceColor(
463f5736e95SDavid du Colombier pImg->aucPalette[iIndex][0],
464f5736e95SDavid du Colombier pImg->aucPalette[iIndex][1],
465f5736e95SDavid du Colombier pImg->aucPalette[iIndex][2]);
466f5736e95SDavid du Colombier }
467f5736e95SDavid du Colombier iX++;
468f5736e95SDavid du Colombier }
469f5736e95SDavid du Colombier /* Padding if the number of bytes is odd */
470f5736e95SDavid du Colombier if (odd(iRunLength)) {
471f5736e95SDavid du Colombier (void)tSkipBytes(pFile, 1);
472f5736e95SDavid du Colombier }
473f5736e95SDavid du Colombier }
474f5736e95SDavid du Colombier }
475f5736e95SDavid du Colombier DBG_DEC_C(iX != pImg->iWidth, iX);
476f5736e95SDavid du Colombier }
477f5736e95SDavid du Colombier } /* end of vDecodeRle8 */
478f5736e95SDavid du Colombier
479f5736e95SDavid du Colombier #if 0 /* defined(DEBUG) */
480f5736e95SDavid du Colombier static void
481f5736e95SDavid du Colombier vCopy2File(UCHAR *pucSprite, size_t tSpriteSize)
482f5736e95SDavid du Colombier {
483f5736e95SDavid du Colombier FILE *pOutFile;
484f5736e95SDavid du Colombier int iIndex;
485f5736e95SDavid du Colombier char szFilename[30];
486f5736e95SDavid du Colombier
487f5736e95SDavid du Colombier sprintf(szFilename, "<Wimp$ScrapDir>.sprt%04d", ++iPicCounter);
488f5736e95SDavid du Colombier pOutFile = fopen(szFilename, "wb");
489f5736e95SDavid du Colombier if (pOutFile == NULL) {
490f5736e95SDavid du Colombier return;
491f5736e95SDavid du Colombier }
492f5736e95SDavid du Colombier DBG_MSG(szFilename);
493f5736e95SDavid du Colombier for (iIndex = 4; iIndex < (int)tSpriteSize; iIndex++) {
494f5736e95SDavid du Colombier if (putc(pucSprite[iIndex], pOutFile) == EOF) {
495f5736e95SDavid du Colombier break;
496f5736e95SDavid du Colombier }
497f5736e95SDavid du Colombier }
498f5736e95SDavid du Colombier (void)fclose(pOutFile);
499f5736e95SDavid du Colombier vSetFiletype(szFilename, FILETYPE_SPRITE);
500f5736e95SDavid du Colombier } /* end of vCopy2File */
501f5736e95SDavid du Colombier #endif /* DEBUG */
502f5736e95SDavid du Colombier
503f5736e95SDavid du Colombier /*
504f5736e95SDavid du Colombier * vDecodeDIB - decode a dib picture
505f5736e95SDavid du Colombier */
506f5736e95SDavid du Colombier static void
vDecodeDIB(diagram_type * pDiag,FILE * pFile,const imagedata_type * pImg)507f5736e95SDavid du Colombier vDecodeDIB(diagram_type *pDiag, FILE *pFile, const imagedata_type *pImg)
508f5736e95SDavid du Colombier {
509*25b329d5SDavid du Colombier sprite_areainfo *pSprite;
510*25b329d5SDavid du Colombier UCHAR *pucPalette, *pucData;
511f5736e95SDavid du Colombier size_t tSpriteSize;
512f5736e95SDavid du Colombier int iHeaderSize;
513f5736e95SDavid du Colombier
514f5736e95SDavid du Colombier /* Skip the bitmap info header */
515f5736e95SDavid du Colombier iHeaderSize = (int)ulNextLong(pFile);
516f5736e95SDavid du Colombier (void)tSkipBytes(pFile, iHeaderSize - 4);
517f5736e95SDavid du Colombier /* Skip the colortable */
518f5736e95SDavid du Colombier if (pImg->uiBitsPerComponent <= 8) {
519f5736e95SDavid du Colombier (void)tSkipBytes(pFile,
520f5736e95SDavid du Colombier pImg->iColorsUsed * ((iHeaderSize > 12) ? 4 : 3));
521f5736e95SDavid du Colombier }
522f5736e95SDavid du Colombier
523*25b329d5SDavid du Colombier /* Create an blank sprite */
524*25b329d5SDavid du Colombier pSprite = pCreateBlankSprite(pImg, &tSpriteSize);
525*25b329d5SDavid du Colombier pucPalette = (UCHAR *)pSprite +
526*25b329d5SDavid du Colombier pSprite->firstoffset + sizeof(sprite_header);
527f5736e95SDavid du Colombier
528f5736e95SDavid du Colombier /* Add the pixel information */
529f5736e95SDavid du Colombier switch (pImg->uiBitsPerComponent) {
530f5736e95SDavid du Colombier case 1:
531f5736e95SDavid du Colombier fail(pImg->eCompression != compression_none);
532f5736e95SDavid du Colombier pucData = pucPalette + 2 * 8;
533f5736e95SDavid du Colombier vDecode1bpp(pFile, pucData, pImg);
534f5736e95SDavid du Colombier break;
535f5736e95SDavid du Colombier case 4:
536f5736e95SDavid du Colombier fail(pImg->eCompression != compression_none &&
537f5736e95SDavid du Colombier pImg->eCompression != compression_rle4);
538f5736e95SDavid du Colombier pucData = pucPalette + 16 * 8;
539f5736e95SDavid du Colombier if (pImg->eCompression == compression_rle4) {
540f5736e95SDavid du Colombier vDecodeRle4(pFile, pucData, pImg);
541f5736e95SDavid du Colombier } else {
542f5736e95SDavid du Colombier vDecode4bpp(pFile, pucData, pImg);
543f5736e95SDavid du Colombier }
544f5736e95SDavid du Colombier break;
545f5736e95SDavid du Colombier case 8:
546f5736e95SDavid du Colombier fail(pImg->eCompression != compression_none &&
547f5736e95SDavid du Colombier pImg->eCompression != compression_rle8);
548*25b329d5SDavid du Colombier pucData = pucPalette + 0 * 8;
549f5736e95SDavid du Colombier if (pImg->eCompression == compression_rle8) {
550f5736e95SDavid du Colombier vDecodeRle8(pFile, pucData, pImg);
551f5736e95SDavid du Colombier } else {
552f5736e95SDavid du Colombier vDecode8bpp(pFile, pucData, pImg);
553f5736e95SDavid du Colombier }
554f5736e95SDavid du Colombier break;
555f5736e95SDavid du Colombier case 24:
556f5736e95SDavid du Colombier fail(pImg->eCompression != compression_none);
557*25b329d5SDavid du Colombier pucData = pucPalette + 0 * 8;
558f5736e95SDavid du Colombier vDecode24bpp(pFile, pucData, pImg);
559f5736e95SDavid du Colombier break;
560f5736e95SDavid du Colombier default:
561f5736e95SDavid du Colombier DBG_DEC(pImg->uiBitsPerComponent);
562f5736e95SDavid du Colombier break;
563f5736e95SDavid du Colombier }
564f5736e95SDavid du Colombier
565f5736e95SDavid du Colombier #if 0 /* defined(DEBUG) */
566*25b329d5SDavid du Colombier vCopy2File((UCHAR *)pSprite, tSpriteSize);
567f5736e95SDavid du Colombier #endif /* DEBUG */
568f5736e95SDavid du Colombier
569f5736e95SDavid du Colombier /* Add the sprite to the Draw file */
570f5736e95SDavid du Colombier vImage2Diagram(pDiag, pImg,
571*25b329d5SDavid du Colombier (UCHAR *)pSprite + pSprite->firstoffset,
572*25b329d5SDavid du Colombier tSpriteSize - pSprite->firstoffset);
573f5736e95SDavid du Colombier
574f5736e95SDavid du Colombier /* Clean up before you leave */
575*25b329d5SDavid du Colombier pSprite = xfree(pSprite);
576f5736e95SDavid du Colombier } /* end of vDecodeDIB */
577f5736e95SDavid du Colombier
578f5736e95SDavid du Colombier /*
579f5736e95SDavid du Colombier * bTranslateDIB - translate a DIB picture
580f5736e95SDavid du Colombier *
581f5736e95SDavid du Colombier * This function translates a picture from dib to sprite
582f5736e95SDavid du Colombier *
583f5736e95SDavid du Colombier * return TRUE when sucessful, otherwise FALSE
584f5736e95SDavid du Colombier */
585f5736e95SDavid du Colombier BOOL
bTranslateDIB(diagram_type * pDiag,FILE * pFile,ULONG ulFileOffset,const imagedata_type * pImg)586f5736e95SDavid du Colombier bTranslateDIB(diagram_type *pDiag, FILE *pFile,
587f5736e95SDavid du Colombier ULONG ulFileOffset, const imagedata_type *pImg)
588f5736e95SDavid du Colombier {
589f5736e95SDavid du Colombier /* Seek to start position of DIB data */
590f5736e95SDavid du Colombier if (!bSetDataOffset(pFile, ulFileOffset)) {
591f5736e95SDavid du Colombier return FALSE;
592f5736e95SDavid du Colombier }
593f5736e95SDavid du Colombier
594f5736e95SDavid du Colombier vDecodeDIB(pDiag, pFile, pImg);
595f5736e95SDavid du Colombier
596f5736e95SDavid du Colombier return TRUE;
597f5736e95SDavid du Colombier } /* end of bTranslateDIB */
598