1 /*
2 * dib2eps.c
3 * Copyright (C) 2000-2003 A.J. van Os; Released under GPL
4 *
5 * Description:
6 * Functions to translate dib pictures into eps
7 *
8 *================================================================
9 * This part of the software is based on:
10 * The Windows Bitmap Decoder Class part of paintlib
11 * Paintlib is copyright (c) 1996-2000 Ulrich von Zadow
12 *================================================================
13 * The credit should go to him, but all the bugs are mine.
14 */
15
16 #include <stdio.h>
17 #include "antiword.h"
18
19
20 /*
21 * vDecode1bpp - decode an uncompressed 1 bit per pixel image
22 */
23 static void
vDecode1bpp(FILE * pInFile,FILE * pOutFile,const imagedata_type * pImg)24 vDecode1bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
25 {
26 size_t tPadding;
27 int iX, iY, iN, iByte, iTmp, iEighthWidth, iUse;
28
29 DBG_MSG("vDecode1bpp");
30
31 fail(pOutFile == NULL);
32 fail(pImg == NULL);
33 fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 2);
34
35 DBG_DEC(pImg->iWidth);
36 DBG_DEC(pImg->iHeight);
37
38 iEighthWidth = (pImg->iWidth + 7) / 8;
39 tPadding = (size_t)(ROUND4(iEighthWidth) - iEighthWidth);
40
41 for (iY = 0; iY < pImg->iHeight; iY++) {
42 for (iX = 0; iX < iEighthWidth; iX++) {
43 iByte = iNextByte(pInFile);
44 if (iByte == EOF) {
45 vASCII85EncodeByte(pOutFile, EOF);
46 return;
47 }
48 if (iX == iEighthWidth - 1 && pImg->iWidth % 8 != 0) {
49 iUse = pImg->iWidth % 8;
50 } else {
51 iUse = 8;
52 }
53 for (iN = 0; iN < iUse; iN++) {
54 switch (iN) {
55 case 0: iTmp = (iByte & 0x80) / 128; break;
56 case 1: iTmp = (iByte & 0x40) / 64; break;
57 case 2: iTmp = (iByte & 0x20) / 32; break;
58 case 3: iTmp = (iByte & 0x10) / 16; break;
59 case 4: iTmp = (iByte & 0x08) / 8; break;
60 case 5: iTmp = (iByte & 0x04) / 4; break;
61 case 6: iTmp = (iByte & 0x02) / 2; break;
62 case 7: iTmp = (iByte & 0x01); break;
63 default: iTmp = 0; break;
64 }
65 vASCII85EncodeByte(pOutFile, iTmp);
66 }
67 }
68 (void)tSkipBytes(pInFile, tPadding);
69 }
70 vASCII85EncodeByte(pOutFile, EOF);
71 } /* end of vDecode1bpp */
72
73 /*
74 * vDecode4bpp - decode an uncompressed 4 bits per pixel image
75 */
76 static void
vDecode4bpp(FILE * pInFile,FILE * pOutFile,const imagedata_type * pImg)77 vDecode4bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
78 {
79 size_t tPadding;
80 int iX, iY, iN, iByte, iTmp, iHalfWidth, iUse;
81
82 DBG_MSG("vDecode4bpp");
83
84 fail(pInFile == NULL);
85 fail(pOutFile == NULL);
86 fail(pImg == NULL);
87 fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
88
89 DBG_DEC(pImg->iWidth);
90 DBG_DEC(pImg->iHeight);
91
92 iHalfWidth = (pImg->iWidth + 1) / 2;
93 tPadding = (size_t)(ROUND4(iHalfWidth) - iHalfWidth);
94
95 for (iY = 0; iY < pImg->iHeight; iY++) {
96 for (iX = 0; iX < iHalfWidth; iX++) {
97 iByte = iNextByte(pInFile);
98 if (iByte == EOF) {
99 vASCII85EncodeByte(pOutFile, EOF);
100 return;
101 }
102 if (iX == iHalfWidth - 1 && odd(pImg->iWidth)) {
103 iUse = 1;
104 } else {
105 iUse = 2;
106 }
107 for (iN = 0; iN < iUse; iN++) {
108 if (odd(iN)) {
109 iTmp = iByte & 0x0f;
110 } else {
111 iTmp = (iByte & 0xf0) / 16;
112 }
113 vASCII85EncodeByte(pOutFile, iTmp);
114 }
115 }
116 (void)tSkipBytes(pInFile, tPadding);
117 }
118 vASCII85EncodeByte(pOutFile, EOF);
119 } /* end of vDecode4bpp */
120
121 /*
122 * vDecode8bpp - decode an uncompressed 8 bits per pixel image
123 */
124 static void
vDecode8bpp(FILE * pInFile,FILE * pOutFile,const imagedata_type * pImg)125 vDecode8bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
126 {
127 size_t tPadding;
128 int iX, iY, iByte;
129
130 DBG_MSG("vDecode8bpp");
131
132 fail(pInFile == NULL);
133 fail(pOutFile == NULL);
134 fail(pImg == NULL);
135 fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
136
137 DBG_DEC(pImg->iWidth);
138 DBG_DEC(pImg->iHeight);
139
140 tPadding = (size_t)(ROUND4(pImg->iWidth) - pImg->iWidth);
141
142 for (iY = 0; iY < pImg->iHeight; iY++) {
143 for (iX = 0; iX < pImg->iWidth; iX++) {
144 iByte = iNextByte(pInFile);
145 if (iByte == EOF) {
146 vASCII85EncodeByte(pOutFile, EOF);
147 return;
148 }
149 vASCII85EncodeByte(pOutFile, iByte);
150 }
151 (void)tSkipBytes(pInFile, tPadding);
152 }
153 vASCII85EncodeByte(pOutFile, EOF);
154 } /* end of vDecode8bpp */
155
156 /*
157 * vDecode24bpp - decode an uncompressed 24 bits per pixel image
158 */
159 static void
vDecode24bpp(FILE * pInFile,FILE * pOutFile,const imagedata_type * pImg)160 vDecode24bpp(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
161 {
162 size_t tPadding;
163 int iX, iY, iBlue, iGreen, iRed, iTripleWidth;
164
165 DBG_MSG("vDecode24bpp");
166
167 fail(pInFile == NULL);
168 fail(pOutFile == NULL);
169 fail(pImg == NULL);
170 fail(!pImg->bColorImage);
171
172 DBG_DEC(pImg->iWidth);
173 DBG_DEC(pImg->iHeight);
174
175 iTripleWidth = pImg->iWidth * 3;
176 tPadding = (size_t)(ROUND4(iTripleWidth) - iTripleWidth);
177
178 for (iY = 0; iY < pImg->iHeight; iY++) {
179 for (iX = 0; iX < pImg->iWidth; iX++) {
180 /* Change from BGR order to RGB order */
181 iBlue = iNextByte(pInFile);
182 if (iBlue == EOF) {
183 vASCII85EncodeByte(pOutFile, EOF);
184 return;
185 }
186 iGreen = iNextByte(pInFile);
187 if (iGreen == EOF) {
188 vASCII85EncodeByte(pOutFile, EOF);
189 return;
190 }
191 iRed = iNextByte(pInFile);
192 if (iRed == EOF) {
193 vASCII85EncodeByte(pOutFile, EOF);
194 return;
195 }
196 vASCII85EncodeByte(pOutFile, iRed);
197 vASCII85EncodeByte(pOutFile, iGreen);
198 vASCII85EncodeByte(pOutFile, iBlue);
199 }
200 (void)tSkipBytes(pInFile, tPadding);
201 }
202 vASCII85EncodeByte(pOutFile, EOF);
203 } /* end of vDecode24bpp */
204
205 /*
206 * vDecodeRle4 - decode a RLE compressed 4 bits per pixel image
207 */
208 static void
vDecodeRle4(FILE * pInFile,FILE * pOutFile,const imagedata_type * pImg)209 vDecodeRle4(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
210 {
211 int iX, iY, iByte, iTmp, iRunLength, iRun;
212 BOOL bEOF, bEOL;
213
214 DBG_MSG("vDecodeRle4");
215
216 fail(pInFile == NULL);
217 fail(pOutFile == NULL);
218 fail(pImg == NULL);
219 fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 16);
220
221 DBG_DEC(pImg->iWidth);
222 DBG_DEC(pImg->iHeight);
223
224 bEOF = FALSE;
225
226 for (iY = 0; iY < pImg->iHeight && !bEOF; iY++) {
227 bEOL = FALSE;
228 iX = 0;
229 while (!bEOL) {
230 iRunLength = iNextByte(pInFile);
231 if (iRunLength == EOF) {
232 vASCII85EncodeByte(pOutFile, EOF);
233 return;
234 }
235 if (iRunLength != 0) {
236 /*
237 * Encoded packet:
238 * RunLength pixels, all the "same" value
239 */
240 iByte = iNextByte(pInFile);
241 if (iByte == EOF) {
242 vASCII85EncodeByte(pOutFile, EOF);
243 return;
244 }
245 for (iRun = 0; iRun < iRunLength; iRun++) {
246 if (odd(iRun)) {
247 iTmp = iByte & 0x0f;
248 } else {
249 iTmp = (iByte & 0xf0) / 16;
250 }
251 if (iX < pImg->iWidth) {
252 vASCII85EncodeByte(pOutFile, iTmp);
253 }
254 iX++;
255 }
256 continue;
257 }
258 /* Literal or escape */
259 iRunLength = iNextByte(pInFile);
260 if (iRunLength == EOF) {
261 vASCII85EncodeByte(pOutFile, EOF);
262 return;
263 }
264 if (iRunLength == 0) { /* End of line escape */
265 bEOL = TRUE;
266 } else if (iRunLength == 1) { /* End of file escape */
267 bEOF = TRUE;
268 bEOL = TRUE;
269 } else if (iRunLength == 2) { /* Delta escape */
270 DBG_MSG("RLE4: encountered delta escape");
271 bEOF = TRUE;
272 bEOL = TRUE;
273 } else { /* Literal packet */
274 iByte = 0;
275 for (iRun = 0; iRun < iRunLength; iRun++) {
276 if (odd(iRun)) {
277 iTmp = iByte & 0x0f;
278 } else {
279 iByte = iNextByte(pInFile);
280 if (iByte == EOF) {
281 vASCII85EncodeByte(pOutFile, EOF);
282 return;
283 }
284 iTmp = (iByte & 0xf0) / 16;
285 }
286 if (iX < pImg->iWidth) {
287 vASCII85EncodeByte(pOutFile, iTmp);
288 }
289 iX++;
290 }
291 /* Padding if the number of bytes is odd */
292 if (odd((iRunLength + 1) / 2)) {
293 (void)tSkipBytes(pInFile, 1);
294 }
295 }
296 }
297 DBG_DEC_C(iX != pImg->iWidth, iX);
298 }
299 vASCII85EncodeByte(pOutFile, EOF);
300 } /* end of vDecodeRle4 */
301
302 /*
303 * vDecodeRle8 - decode a RLE compressed 8 bits per pixel image
304 */
305 static void
vDecodeRle8(FILE * pInFile,FILE * pOutFile,const imagedata_type * pImg)306 vDecodeRle8(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
307 {
308 int iX, iY, iByte, iRunLength, iRun;
309 BOOL bEOF, bEOL;
310
311 DBG_MSG("vDecodeRle8");
312
313 fail(pInFile == NULL);
314 fail(pOutFile == NULL);
315 fail(pImg == NULL);
316 fail(pImg->iColorsUsed < 1 || pImg->iColorsUsed > 256);
317
318 DBG_DEC(pImg->iWidth);
319 DBG_DEC(pImg->iHeight);
320
321 bEOF = FALSE;
322
323 for (iY = 0; iY < pImg->iHeight && !bEOF; iY++) {
324 bEOL = FALSE;
325 iX = 0;
326 while (!bEOL) {
327 iRunLength = iNextByte(pInFile);
328 if (iRunLength == EOF) {
329 vASCII85EncodeByte(pOutFile, EOF);
330 return;
331 }
332 if (iRunLength != 0) {
333 /*
334 * Encoded packet:
335 * RunLength pixels, all the same value
336 */
337 iByte = iNextByte(pInFile);
338 if (iByte == EOF) {
339 vASCII85EncodeByte(pOutFile, EOF);
340 return;
341 }
342 for (iRun = 0; iRun < iRunLength; iRun++) {
343 if (iX < pImg->iWidth) {
344 vASCII85EncodeByte(pOutFile, iByte);
345 }
346 iX++;
347 }
348 continue;
349 }
350 /* Literal or escape */
351 iRunLength = iNextByte(pInFile);
352 if (iRunLength == EOF) {
353 vASCII85EncodeByte(pOutFile, EOF);
354 return;
355 }
356 if (iRunLength == 0) { /* End of line escape */
357 bEOL = TRUE;
358 } else if (iRunLength == 1) { /* End of file escape */
359 bEOF = TRUE;
360 bEOL = TRUE;
361 } else if (iRunLength == 2) { /* Delta escape */
362 DBG_MSG("RLE8: encountered delta escape");
363 bEOF = TRUE;
364 bEOL = TRUE;
365 } else { /* Literal packet */
366 for (iRun = 0; iRun < iRunLength; iRun++) {
367 iByte = iNextByte(pInFile);
368 if (iByte == EOF) {
369 vASCII85EncodeByte(pOutFile, EOF);
370 return;
371 }
372 if (iX < pImg->iWidth) {
373 vASCII85EncodeByte(pOutFile, iByte);
374 }
375 iX++;
376 }
377 /* Padding if the number of bytes is odd */
378 if (odd(iRunLength)) {
379 (void)tSkipBytes(pInFile, 1);
380 }
381 }
382 }
383 DBG_DEC_C(iX != pImg->iWidth, iX);
384 }
385 vASCII85EncodeByte(pOutFile, EOF);
386 } /* end of vDecodeRle8 */
387
388 /*
389 * vDecodeDIB - decode a dib picture
390 */
391 static void
vDecodeDIB(FILE * pInFile,FILE * pOutFile,const imagedata_type * pImg)392 vDecodeDIB(FILE *pInFile, FILE *pOutFile, const imagedata_type *pImg)
393 {
394 size_t tHeaderSize;
395
396 fail(pInFile == NULL);
397 fail(pOutFile == NULL);
398 fail(pImg == NULL);
399
400 /* Skip the bitmap info header */
401 tHeaderSize = (size_t)ulNextLong(pInFile);
402 (void)tSkipBytes(pInFile, tHeaderSize - 4);
403 /* Skip the colortable */
404 if (pImg->uiBitsPerComponent <= 8) {
405 (void)tSkipBytes(pInFile,
406 (size_t)(pImg->iColorsUsed *
407 ((tHeaderSize > 12) ? 4 : 3)));
408 }
409
410 switch (pImg->uiBitsPerComponent) {
411 case 1:
412 fail(pImg->eCompression != compression_none);
413 vDecode1bpp(pInFile, pOutFile, pImg);
414 break;
415 case 4:
416 fail(pImg->eCompression != compression_none &&
417 pImg->eCompression != compression_rle4);
418 if (pImg->eCompression == compression_rle4) {
419 vDecodeRle4(pInFile, pOutFile, pImg);
420 } else {
421 vDecode4bpp(pInFile, pOutFile, pImg);
422 }
423 break;
424 case 8:
425 fail(pImg->eCompression != compression_none &&
426 pImg->eCompression != compression_rle8);
427 if (pImg->eCompression == compression_rle8) {
428 vDecodeRle8(pInFile, pOutFile, pImg);
429 } else {
430 vDecode8bpp(pInFile, pOutFile, pImg);
431 }
432 break;
433 case 24:
434 fail(pImg->eCompression != compression_none);
435 vDecode24bpp(pInFile, pOutFile, pImg);
436 break;
437 default:
438 DBG_DEC(pImg->uiBitsPerComponent);
439 break;
440 }
441 } /* end of vDecodeDIB */
442
443 #if defined(DEBUG)
444 /*
445 * vCopy2File
446 */
447 static void
vCopy2File(FILE * pInFile,ULONG ulFileOffset,size_t tPictureLen)448 vCopy2File(FILE *pInFile, ULONG ulFileOffset, size_t tPictureLen)
449 {
450 static int iPicCounter = 0;
451 FILE *pOutFile;
452 size_t tIndex;
453 int iTmp;
454 char szFilename[30];
455
456 if (!bSetDataOffset(pInFile, ulFileOffset)) {
457 return;
458 }
459
460 sprintf(szFilename, "/tmp/pic/pic%04d.bmp", ++iPicCounter);
461 pOutFile = fopen(szFilename, "wb");
462 if (pOutFile == NULL) {
463 return;
464 }
465 /* Turn a dib into a bmp by adding a fake 14 byte header */
466 (void)putc('B', pOutFile);
467 (void)putc('M', pOutFile);
468 for (iTmp = 0; iTmp < 12; iTmp++) {
469 if (putc(0, pOutFile) == EOF) {
470 break;
471 }
472 }
473 for (tIndex = 0; tIndex < tPictureLen; tIndex++) {
474 iTmp = iNextByte(pInFile);
475 if (putc(iTmp, pOutFile) == EOF) {
476 break;
477 }
478 }
479 (void)fclose(pOutFile);
480 } /* end of vCopy2File */
481 #endif /* DEBUG */
482
483 /*
484 * bTranslateDIB - translate a DIB picture
485 *
486 * This function translates a picture from dib to eps
487 *
488 * return TRUE when sucessful, otherwise FALSE
489 */
490 BOOL
bTranslateDIB(diagram_type * pDiag,FILE * pInFile,ULONG ulFileOffset,const imagedata_type * pImg)491 bTranslateDIB(diagram_type *pDiag, FILE *pInFile,
492 ULONG ulFileOffset, const imagedata_type *pImg)
493 {
494 #if defined(DEBUG)
495 fail(pImg->tPosition > pImg->tLength);
496 vCopy2File(pInFile, ulFileOffset, pImg->tLength - pImg->tPosition);
497 #endif /* DEBUG */
498
499 /* Seek to start position of DIB data */
500 if (!bSetDataOffset(pInFile, ulFileOffset)) {
501 return FALSE;
502 }
503
504 vImagePrologue(pDiag, pImg);
505 vDecodeDIB(pInFile, pDiag->pOutFile, pImg);
506 vImageEpilogue(pDiag);
507
508 return TRUE;
509 } /* end of bTranslateDIB */
510