1 /*---------------------------------------------------------------------------*
2 | PDFlib - A library for generating PDF on the fly |
3 +---------------------------------------------------------------------------+
4 | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
5 +---------------------------------------------------------------------------+
6 | |
7 | This software is subject to the PDFlib license. It is NOT in the |
8 | public domain. Extended versions and commercial licenses are |
9 | available, please check http://www.pdflib.com. |
10 | |
11 *---------------------------------------------------------------------------*/
12
13 /* $Id: p_gif.c,v 1.70.2.6 2008/03/18 16:55:00 kurt Exp $
14 *
15 * GIF processing for PDFlib
16 *
17 */
18
19 /*
20 * This module contains modified parts of the giftopnm.c progam in the
21 * netpbm package. It contained the following copyright notice:
22 */
23
24 /* +-------------------------------------------------------------------+ */
25 /* | Copyright 1990 - 1994, David Koblas. (koblas@netcom.com) | */
26 /* | Permission to use, copy, modify, and distribute this software | */
27 /* | and its documentation for any purpose and without fee is hereby | */
28 /* | granted, provided that the above copyright notice appear in all | */
29 /* | copies and that both that copyright notice and this permission | */
30 /* | notice appear in supporting documentation. This software is | */
31 /* | provided "as is" without express or implied warranty. | */
32 /* +-------------------------------------------------------------------+ */
33
34 #include "p_intern.h"
35 #include "p_color.h"
36 #include "p_image.h"
37
38 #ifndef PDF_GIF_SUPPORTED
39
40 pdc_bool
pdf_is_GIF_file(PDF * p,pdc_file * fp)41 pdf_is_GIF_file(PDF *p, pdc_file *fp)
42 {
43 (void) p;
44 (void) fp;
45
46 return pdc_false;
47 }
48
49 int
pdf_process_GIF_data(PDF * p,int imageslot)50 pdf_process_GIF_data(
51 PDF *p,
52 int imageslot)
53 {
54 (void) imageslot;
55
56 pdc_set_errmsg(p->pdc, PDF_E_UNSUPP_IMAGE, "GIF", 0, 0, 0);
57
58 return -1;
59 }
60
61 void
pdf_cleanup_gif(PDF * p,pdf_image * image)62 pdf_cleanup_gif(PDF *p, pdf_image *image)
63 {
64 (void) p;
65 (void) image;
66 }
67
68 #else
69
70 #define LOCALCOLORMAP 0x80
71 #define BitSet(byteval, bitval) (((byteval) & (bitval)) == (bitval))
72
73 static int ReadColorMap(pdc_core *pdc, pdc_file *fp,
74 int number, pdf_colormap *buffer);
75 static int DoExtension(PDF *p, pdf_image *image, int label);
76 static int GetDataBlock(PDF *p, pdf_image *image, unsigned char *buf);
77 static void ReadImage(PDF *p, pdf_image *image, PDF_data_source *src);
78
79 static void
pdf_data_source_GIF_init(PDF * p,PDF_data_source * src)80 pdf_data_source_GIF_init(PDF *p, PDF_data_source *src)
81 {
82 pdf_image *image;
83
84 image = (pdf_image *) src->private_data;
85
86 src->buffer_length = (size_t) (image->width * image->height * 1);
87 src->buffer_start = (pdc_byte *) pdc_malloc(p->pdc, src->buffer_length,
88 "pdf_data_source_GIF_init");
89 src->bytes_available= 0;
90 src->next_byte = NULL;
91 }
92
93 static pdc_bool
pdf_data_source_GIF_fill(PDF * p,PDF_data_source * src)94 pdf_data_source_GIF_fill(PDF *p, PDF_data_source *src)
95 {
96 pdf_image *image;
97
98 if (src->next_byte != NULL) /* all finished in one turn */
99 return pdc_false;
100
101 image = (pdf_image *) src->private_data;
102
103 src->next_byte = src->buffer_start;
104 src->bytes_available = src->buffer_length;
105
106 PDC_TRY(p->pdc)
107 {
108 ReadImage(p, image, src);
109 }
110 PDC_CATCH(p->pdc)
111 {
112 image->corrupt = pdc_true;
113 }
114
115 pdf_cleanup_gif(p, image);
116
117 return !image->corrupt;
118 }
119
120 static void
pdf_data_source_GIF_terminate(PDF * p,PDF_data_source * src)121 pdf_data_source_GIF_terminate(PDF *p, PDF_data_source *src)
122 {
123 pdc_free(p->pdc, (void *) src->buffer_start);
124 }
125
126 #define PDF_STRING_GIF "\107\111\106"
127 #define PDF_STRING_87a "\070\067\141"
128 #define PDF_STRING_89a "\070\071\141"
129
130 pdc_bool
pdf_is_GIF_file(PDF * p,pdc_file * fp)131 pdf_is_GIF_file(PDF *p, pdc_file *fp)
132 {
133 unsigned char buf[3];
134
135 pdc_logg_cond(p->pdc, 1, trc_image, "\tChecking image type GIF...\n");
136
137 if (!PDC_OK_FREAD(fp, buf, 3) ||
138 strncmp((const char *) buf, PDF_STRING_GIF, 3) != 0)
139 {
140 pdc_fseek(fp, 0L, SEEK_SET);
141 return pdc_false;
142 }
143 return pdc_true;
144 }
145
146 int
pdf_process_GIF_data(PDF * p,int imageslot)147 pdf_process_GIF_data(
148 PDF *p,
149 int imageslot)
150 {
151 unsigned char buf[16];
152 char c;
153 int imageCount = 0;
154 char version[4];
155 int errcode = 0;
156 pdf_image *image;
157 pdf_colorspace cs;
158 pdf_colormap colormap;
159 int slot;
160
161 image = &p->images[imageslot];
162
163 image->info.gif.stack = NULL;
164 image->info.gif.table = NULL;
165
166 /* we invert this flag later */
167 if (image->ignoremask)
168 image->transparent = pdc_true;
169
170 if (image->page == pdc_undef)
171 image->page = 1;
172
173 /* Error reading magic number or not a GIF file */
174 if (pdf_is_GIF_file(p, image->fp) == pdc_false) {
175 errcode = PDC_E_IO_BADFORMAT;
176 goto PDF_GIF_ERROR;
177 }
178
179 /* Version number */
180 if (! PDC_OK_FREAD(image->fp, buf, 3)) {
181 errcode = PDC_E_IO_BADFORMAT;
182 goto PDF_GIF_ERROR;
183 }
184 strncpy(version, (const char *) buf, 3);
185 version[3] = '\0';
186 if ((strcmp(version, PDF_STRING_87a) != 0) &&
187 (strcmp(version, PDF_STRING_89a) != 0)) {
188 errcode = PDC_E_IO_BADFORMAT;
189 goto PDF_GIF_ERROR;
190 }
191
192 /* Failed to read screen descriptor */
193 if (! PDC_OK_FREAD(image->fp, buf, 7)) {
194 errcode = PDC_E_IO_BADFORMAT;
195 goto PDF_GIF_ERROR;
196 }
197
198 cs.type = Indexed;
199 /* size of the global color table */
200 cs.val.indexed.palette_size = 2 << (buf[4] & 0x07);
201 cs.val.indexed.base = DeviceRGB;
202 cs.val.indexed.colormap = &colormap;
203 cs.val.indexed.colormap_id = PDC_BAD_ID;
204
205 if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
206 if (ReadColorMap(p->pdc, image->fp,
207 cs.val.indexed.palette_size, &colormap)) {
208 errcode = PDF_E_IMAGE_COLORMAP;
209 goto PDF_GIF_ERROR;
210 }
211 }
212
213 /* translate the aspect ratio to PDFlib notation */
214 if (buf[6] != 0) {
215 image->dpi_x = (pdc_scalar) (-(buf[6] + 15.0) / 64.0);
216 image->dpi_y = -1.0;
217 }
218
219 for (/* */ ; /* */ ; /* */) {
220 /* EOF / read error in image data */
221 if (!PDC_OK_FREAD(image->fp, &c, 1)) {
222 errcode = PDC_E_IO_READ;
223 goto PDF_GIF_ERROR;
224 }
225
226 #define PDF_SEMICOLON ((char) 0x3b) /* ASCII ';' */
227
228 if (c == PDF_SEMICOLON) { /* GIF terminator */
229 /* Not enough images found in file */
230 if (imageCount < image->page) {
231 if (!imageCount)
232 errcode = PDF_E_IMAGE_CORRUPT;
233 else
234 errcode = PDF_E_IMAGE_NOPAGE;
235 goto PDF_GIF_ERROR;
236 }
237 break;
238 }
239
240 #define PDF_EXCLAM ((char) 0x21) /* ASCII '!' */
241
242 if (c == PDF_EXCLAM) { /* Extension */
243 if (!PDC_OK_FREAD(image->fp, &c, 1)) {
244 /* EOF / read error on extension function code */
245 errcode = PDC_E_IO_READ;
246 goto PDF_GIF_ERROR;
247 }
248 DoExtension(p, image, (int) c);
249 continue;
250 }
251
252 #define PDF_COMMA ((char) 0x2c) /* ASCII ',' */
253
254 if (c != PDF_COMMA) { /* Not a valid start character */
255 /* Bogus character, ignoring */
256 continue;
257 }
258
259 ++imageCount;
260
261 if (! PDC_OK_FREAD(image->fp, buf, 9)) {
262 /* Couldn't read left/top/width/height */
263 errcode = PDC_E_IO_READ;
264 goto PDF_GIF_ERROR;
265 }
266
267 image->components = 1;
268 image->bpc = 8;
269 image->width = (pdc_scalar) pdc_get_le_ushort(&buf[4]);
270 image->height = (pdc_scalar) pdc_get_le_ushort(&buf[6]);
271
272 #define INTERLACE 0x40
273 image->info.gif.interlace= BitSet(buf[8], INTERLACE);
274
275 if (image->imagemask)
276 {
277 if (p->compatibility <= PDC_1_3) {
278 errcode = PDF_E_IMAGE_MASK1BIT13;
279 goto PDF_GIF_ERROR;
280 } else {
281 /* images with more than one bit will be written as /SMask,
282 * and don't require an /ImageMask entry.
283 */
284 image->imagemask = pdc_false;
285 }
286 image->colorspace = DeviceGray;
287 }
288
289 if (BitSet(buf[8], LOCALCOLORMAP)) {
290 /* The local color map may have a different size */
291 cs.val.indexed.palette_size = 2 << (buf[8] & 0x07);
292
293 if (ReadColorMap(p->pdc, image->fp,
294 cs.val.indexed.palette_size, &colormap))
295 {
296 errcode = PDF_E_IMAGE_COLORMAP;
297 goto PDF_GIF_ERROR;
298 }
299 }
300
301 if (imageCount == image->page)
302 break;
303 }
304
305 image->src.init = pdf_data_source_GIF_init;
306 image->src.fill = pdf_data_source_GIF_fill;
307 image->src.terminate = pdf_data_source_GIF_terminate;
308 image->src.private_data = (void *) image;
309
310 image->compression = pdf_comp_none;
311 image->use_raw = pdc_false;
312
313 image->in_use = pdc_true; /* mark slot as used */
314
315 slot = pdf_add_colorspace(p, &cs, pdc_false);
316 image->colorspace = slot;
317
318
319
320
321 pdf_put_image(p, imageslot, pdc_true, pdc_true);
322
323 if (!image->corrupt)
324 return imageslot;
325
326 PDF_GIF_ERROR:
327 {
328 const char *stemp = NULL;
329
330 if (errcode)
331 stemp = pdf_get_image_filename(p, image);
332
333 switch (errcode)
334 {
335 case PDC_E_IO_READ:
336 case PDF_E_IMAGE_COLORMAP:
337 case PDF_E_IMAGE_MASK1BIT13:
338 pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0);
339 break;
340
341 case PDC_E_IO_BADFORMAT:
342 pdc_set_errmsg(p->pdc, errcode, stemp, "GIF", 0, 0);
343 break;
344
345 case PDF_E_IMAGE_CORRUPT:
346 pdc_set_errmsg(p->pdc, errcode, "GIF", stemp, 0, 0);
347 break;
348
349 case PDF_E_IMAGE_NOPAGE:
350 pdc_set_errmsg(p->pdc, errcode,
351 pdc_errprintf(p->pdc, "%d", image->page), "GIF", stemp, 0);
352 break;
353
354 case 0: /* error code and message already set */
355 break;
356 }
357 }
358
359 return -1;
360 } /* pdf_open_GIF_data */
361
362 static int
ReadColorMap(pdc_core * pdc,pdc_file * fp,int number,pdf_colormap * buffer)363 ReadColorMap(pdc_core *pdc, pdc_file *fp, int number, pdf_colormap *buffer)
364 {
365 int i;
366 unsigned char rgb[3];
367
368 (void) pdc;
369
370 for (i = 0; i < number; ++i) {
371 if (! PDC_OK_FREAD(fp, rgb, sizeof(rgb))) {
372 return pdc_true; /* yk: true == error */
373 }
374
375 (*buffer)[i][0] = rgb[0] ;
376 (*buffer)[i][1] = rgb[1] ;
377 (*buffer)[i][2] = rgb[2] ;
378 }
379 return pdc_false; /* yk: false == ok. */
380 } /* ReadColorMap */
381
382 static int
DoExtension(PDF * p,pdf_image * image,int label)383 DoExtension(PDF *p, pdf_image *image, int label)
384 {
385 pdc_byte buf[256];
386
387 switch ((unsigned char) label) {
388 case 0x01: /* Plain Text Extension */
389 break;
390
391 case 0xff: /* Application Extension */
392 break;
393
394 case 0xfe: /* Comment Extension */
395 while (GetDataBlock(p, image, (unsigned char*) buf) != 0) {
396 /* */
397 }
398 return pdc_false;
399
400 case 0xf9: /* Graphic Control Extension */
401 (void) GetDataBlock(p, image, (unsigned char*) buf);
402
403 if ((buf[0] & 0x1) != 0) {
404 image->transparent = !image->transparent;
405 image->transval[0] = buf[3];
406 }
407
408 while (GetDataBlock(p, image, (unsigned char*) buf) != 0) {
409 /* */ ;
410 }
411 return pdc_false;
412
413 default:
414 break;
415 }
416
417 while (GetDataBlock(p, image, (unsigned char*) buf) != 0) {
418 /* */ ;
419 }
420
421 return pdc_false;
422 } /* DoExtension */
423
424 /*
425 * A bunch of formely static variables which are now kept in the
426 * image structure in order to keep the GIF reader thread-safe.
427 */
428
429 /* for GetDataBlock() */
430 #define ZeroDataBlock (image->info.gif.ZeroDataBlock)
431
432 /* for initLWZ() */
433 #define curbit (image->info.gif.curbit)
434 #define lastbit (image->info.gif.lastbit)
435 #define get_done (image->info.gif.get_done)
436 #define last_byte (image->info.gif.last_byte)
437 #define return_clear (image->info.gif.return_clear)
438
439 #define sp (image->info.gif.sp)
440 #define code_size (image->info.gif.code_size)
441 #define set_code_size (image->info.gif.set_code_size)
442 #define max_code (image->info.gif.max_code)
443 #define max_code_size (image->info.gif.max_code_size)
444 #define clear_code (image->info.gif.clear_code)
445 #define end_code (image->info.gif.end_code)
446
447 /* for nextCode() */
448 #define buf (image->info.gif.buf)
449
450 /* for nextLWZ() */
451 #define stack (image->info.gif.stack)
452 #define table (image->info.gif.table)
453 #define firstcode (image->info.gif.firstcode)
454 #define oldcode (image->info.gif.oldcode)
455
456 static int
GetDataBlock(PDF * p,pdf_image * image,unsigned char * lbuf)457 GetDataBlock(PDF *p, pdf_image *image, unsigned char *lbuf)
458 {
459 unsigned char count;
460 pdc_file *fp = image->fp;
461
462 if (!PDC_OK_FREAD(fp, &count, 1))
463 return -1; /* Error in getting DataBlock size */
464
465 ZeroDataBlock = (count == (unsigned char) 0);
466
467 if ((count != (unsigned char) 0) && (!PDC_OK_FREAD(fp, lbuf, count)))
468 {
469 /* Error in reading DataBlock */
470 pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF",
471 pdf_get_image_filename(p, image), 0, 0);
472 }
473
474 return count;
475 } /* GetDataBlock */
476
477 static void
initLWZ(PDF * p,pdf_image * image,int input_code_size)478 initLWZ(PDF *p, pdf_image *image, int input_code_size)
479 {
480 #define GIF_TABLE_SIZE (sizeof(int [2][GIF_TABLE_ELEMENTS]))
481 #define GIF_STACK_SIZE (sizeof(int [GIF_TABLE_ELEMENTS*2]))
482
483 table = (int(*)[GIF_TABLE_ELEMENTS])
484 pdc_malloc(p->pdc, GIF_TABLE_SIZE, "initLWZ");
485 stack = (int *) pdc_malloc(p->pdc, GIF_STACK_SIZE, "initLWZ");
486
487 set_code_size = input_code_size;
488 code_size = set_code_size + 1;
489 clear_code = 1 << set_code_size ;
490 end_code = clear_code + 1;
491 max_code_size = 2 * clear_code;
492 max_code = clear_code + 2;
493
494 curbit = lastbit = 0;
495 last_byte = 2;
496 get_done = pdc_false;
497
498 return_clear = pdc_true;
499
500 sp = stack;
501 }
502
503 /*
504 * We clean up after decompressing the image; in rare cases (exception
505 * caused by damaged compressed data) this may also be called when
506 * cleaning up the full image struct.
507 */
508 void
pdf_cleanup_gif(PDF * p,pdf_image * image)509 pdf_cleanup_gif(PDF *p, pdf_image *image)
510 {
511 if (table)
512 {
513 pdc_free(p->pdc, table);
514 table = NULL;
515 }
516 if (stack)
517 {
518 pdc_free(p->pdc, stack);
519 stack = NULL;
520 }
521 }
522
523 static int
nextCode(PDF * p,pdf_image * image,int codesize)524 nextCode(PDF *p, pdf_image *image, int codesize)
525 {
526 static const int maskTbl[16] = {
527 0x0000, 0x0001, 0x0003, 0x0007,
528 0x000f, 0x001f, 0x003f, 0x007f,
529 0x00ff, 0x01ff, 0x03ff, 0x07ff,
530 0x0fff, 0x1fff, 0x3fff, 0x7fff,
531 };
532 int i, j, ret, end;
533
534 if (return_clear) {
535 return_clear = pdc_false;
536 return clear_code;
537 }
538
539 end = curbit + codesize;
540
541 if (end >= lastbit) {
542 int count;
543
544 if (get_done) {
545 if (curbit >= lastbit)
546 {
547 /*
548 ERROR("ran off the end of my bits" );
549 */
550 pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF",
551 pdf_get_image_filename(p, image), 0, 0);
552 }
553 return -1;
554 }
555
556 if (last_byte >= 2)
557 {
558 buf[0] = buf[last_byte-2];
559 buf[1] = buf[last_byte-1];
560 }
561
562 if ((count = GetDataBlock(p, image, &buf[2])) == 0)
563 get_done = pdc_true;
564
565 last_byte = 2 + count;
566 curbit = (curbit - lastbit) + 16;
567 lastbit = (2+count)*8 ;
568
569 end = curbit + codesize;
570 }
571
572 j = end / 8;
573 i = curbit / 8;
574
575 if (i == j)
576 ret = buf[i];
577 else if (i + 1 == j)
578 ret = buf[i] | (buf[i+1] << 8);
579 else
580 ret = buf[i] | (buf[i+1] << 8) | (buf[i+2] << 16);
581
582 ret = (ret >> (curbit % 8)) & maskTbl[codesize];
583
584 curbit += codesize;
585
586 return ret;
587 }
588
589 #define readLWZ(p, image) ((sp > stack) ? *--sp : nextLWZ(p, image))
590
591 static int
nextLWZ(PDF * p,pdf_image * image)592 nextLWZ(PDF *p, pdf_image *image)
593 {
594 int code, incode;
595 int i;
596
597 while ((code = nextCode(p, image, code_size)) >= 0) {
598 if (code == clear_code) {
599 for (i = 0; i < clear_code; ++i) {
600 table[0][i] = 0;
601 table[1][i] = i;
602 }
603 for (; i < (1<<MAX_LWZ_BITS); ++i)
604 table[0][i] = table[1][i] = 0;
605 code_size = set_code_size+1;
606 max_code_size = 2*clear_code;
607 max_code = clear_code+2;
608 sp = stack;
609 do {
610 firstcode = oldcode = nextCode(p, image, code_size);
611 } while (firstcode == clear_code);
612
613 return firstcode;
614 }
615 if (code == end_code) {
616 int count;
617 unsigned char lbuf[260];
618
619 if (ZeroDataBlock)
620 return -2;
621
622 while ((count = GetDataBlock(p, image, lbuf)) > 0)
623 ;
624
625 /* count != 0: INFO_MSG(("missing EOD in data stream")); */
626
627 return -2;
628 }
629
630 incode = code;
631
632 if (code >= max_code) {
633 *sp++ = firstcode;
634 code = oldcode;
635 }
636
637 while (code >= clear_code) {
638 *sp++ = table[1][code];
639 if (code == table[0][code])
640 {
641 /* ERROR("circular table entry BIG ERROR"); */
642 pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF",
643 pdf_get_image_filename(p, image), 0, 0);
644 }
645 code = table[0][code];
646 }
647
648 *sp++ = firstcode = table[1][code];
649
650 if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
651 table[0][code] = oldcode;
652 table[1][code] = firstcode;
653 ++max_code;
654 if ((max_code >= max_code_size) &&
655 (max_code_size < (1<<MAX_LWZ_BITS))) {
656 max_code_size *= 2;
657 ++code_size;
658 }
659 }
660
661 oldcode = incode;
662
663 if (sp > stack)
664 return *--sp;
665 }
666 return code;
667 }
668
669 static void
ReadImage(PDF * p,pdf_image * image,PDF_data_source * src)670 ReadImage(PDF *p, pdf_image *image, PDF_data_source *src)
671 {
672 unsigned char c;
673 int v;
674 unsigned int xpos = 0, ypos = 0;
675 pdc_byte *dp;
676 unsigned int h = (unsigned int) image->height;
677 unsigned int w = (unsigned int) image->width;
678
679 /*
680 * Initialize the Compression routines
681 */
682 ZeroDataBlock = pdc_false;
683
684 if (!PDC_OK_FREAD(image->fp, &c, 1))
685 {
686 pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF",
687 pdf_get_image_filename(p, image), 0, 0);
688 }
689
690 initLWZ(p, image, c);
691
692 if (image->info.gif.interlace) {
693 int i;
694 int pass = 0, step = 8;
695
696 for (i = 0; i < (int) h; i++) {
697 dp = &src->buffer_start[w * ypos];
698 for (xpos = 0; xpos < w; xpos++) {
699 if ((v = readLWZ(p, image)) < 0)
700 goto fini;
701
702 *dp++ = v;
703 }
704 if ((ypos += step) >= h) {
705 do {
706 if (pass++ > 0)
707 step /= 2;
708 ypos = step / 2;
709 } while (ypos > h);
710 }
711 }
712 } else {
713 dp = src->buffer_start;
714 for (ypos = 0; ypos < h; ypos++) {
715 for (xpos = 0; xpos < w; xpos++) {
716 if ((v = readLWZ(p, image)) < 0)
717 goto fini;
718
719 *dp++ = v;
720 }
721 }
722 }
723
724 fini:
725 if (readLWZ(p, image) >= 0)
726 /* Too much input data in GIF file '%s', ignoring extra. */
727 ;
728 }
729
730 #undef fresh
731 #undef code_size
732 #undef set_code_size
733 #undef max_code
734 #undef max_code_size
735 #undef firstcode
736 #undef oldcode
737 #undef clear_code
738 #undef end_code
739 #undef sp
740 #undef table
741 #undef stack
742
743 #endif /* PDF_GIF_SUPPORTED */
744