Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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