xref: /plan9/sys/src/cmd/aux/antiword/dib2sprt.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
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