1/*---------------------------------------------------------------------------* 2 | PDFlib - A library for generating PDF on the fly | 3 +---------------------------------------------------------------------------+ 4 | Copyright (c) 1997-2004 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 14574 2005-10-29 16:27:43Z bonefish $ 14 * 15 * GIF processing for PDFlib 16 * 17 */ 18 19#include "p_intern.h" 20#include "p_image.h" 21 22#ifndef PDF_GIF_SUPPORTED 23 24pdc_bool 25pdf_is_GIF_file(PDF *p, pdc_file *fp) 26{ 27 (void) p; 28 (void) fp; 29 30 return pdc_false; 31} 32 33int 34pdf_process_GIF_data( 35 PDF *p, 36 int imageslot) 37{ 38 (void) imageslot; 39 40 pdc_warning(p->pdc, PDF_E_UNSUPP_IMAGE, "GIF", 0, 0, 0); 41 return -1; 42} 43 44#else 45 46#define LOCALCOLORMAP 0x80 47#define BitSet(byteval, bitval) (((byteval) & (bitval)) == (bitval)) 48 49static int ReadColorMap(pdc_core *pdc, pdc_file *fp, 50 int number, pdf_colormap *buffer); 51static int DoExtension(PDF *p, pdf_image *image, int label); 52static int GetDataBlock(PDF *p, pdf_image *image, unsigned char *buf); 53 54static void 55pdf_data_source_GIF_init(PDF *p, PDF_data_source *src) 56{ 57 pdf_image *image = (pdf_image *) src->private_data; 58 59 src->buffer_length = 260; /* max. GIF "data sub-block" length */ 60 61 src->buffer_start = (pdc_byte*) pdc_malloc(p->pdc, src->buffer_length, 62 "pdf_data_source_GIF_init"); 63 src->bytes_available= 0; 64 src->next_byte = src->buffer_start; 65 66 /* init the LZW transformation vars */ 67 image->info.gif.c_size = 9; /* initial code size */ 68 image->info.gif.t_size = 257; /* initial "table" size */ 69 image->info.gif.i_buff = 0; /* input buffer */ 70 image->info.gif.i_bits = 0; /* input buffer empty */ 71 image->info.gif.o_bits = 0; /* output buffer empty */ 72} /* pdf_data_source_GIF_init */ 73 74static pdc_bool 75pdf_data_source_GIF_fill(PDF *p, PDF_data_source *src) 76{ 77#define c_size image->info.gif.c_size 78#define t_size image->info.gif.t_size 79#define i_buff image->info.gif.i_buff 80#define i_bits image->info.gif.i_bits 81#define o_buff image->info.gif.o_buff 82#define o_bits image->info.gif.o_bits 83 84 pdf_image * image = (pdf_image *) src->private_data; 85 pdc_file * fp = image->fp; 86 int n_bytes = pdc_fgetc(fp); 87 /* # of bytes to read */ 88 unsigned char * o_curr = src->buffer_start; 89 int c_mask = (1 << c_size) - 1; 90 pdc_bool flag13 = pdc_false; 91 92 src->bytes_available = 0; 93 94 if (n_bytes == EOF) 95 { 96 const char *stemp = pdc_errprintf(p->pdc, "%s", image->filename); 97 pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF", stemp, 0, 0); 98 } 99 100 if (n_bytes == 0) 101 return pdc_false; 102 103 for (/* */ ; /* */ ; /* */) 104 { 105 int w_bits = c_size; /* number of bits to write */ 106 int code; 107 108 /* get at least c_size bits into i_buff */ 109 while (i_bits < c_size) 110 { 111 if (n_bytes-- == 0) 112 { 113 src->bytes_available = (size_t) (o_curr - src->buffer_start); 114 return pdc_true; 115 } 116 /* EOF will be caught later */ 117 i_buff |= pdc_fgetc(fp) << i_bits; 118 i_bits += 8; 119 } 120 code = i_buff & c_mask; 121 i_bits -= c_size; 122 i_buff >>= c_size; 123 124 if (flag13 && code != 256 && code != 257) 125 { 126 const char *stemp = pdc_errprintf(p->pdc, "%s", image->filename); 127 pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF", stemp, 0, 0); 128 } 129 130 if (o_bits > 0) 131 { 132 o_buff |= code >> (c_size - 8 + o_bits); 133 w_bits -= 8 - o_bits; 134 *(o_curr++) = (unsigned char) o_buff; 135 } 136 if (w_bits >= 8) 137 { 138 w_bits -= 8; 139 *(o_curr++) = (unsigned char) (code >> w_bits); 140 } 141 o_bits = w_bits; 142 if (o_bits > 0) 143 o_buff = code << (8 - o_bits); 144 145 ++t_size; 146 if (code == 256) /* clear code */ 147 { 148 c_size = 9; 149 c_mask = (1 << c_size) - 1; 150 t_size = 257; 151 flag13 = pdc_false; 152 } 153 154 if (code == 257) /* end code */ 155 { 156 src->bytes_available = (size_t) (o_curr - src->buffer_start); 157 return pdc_true; 158 } 159 160 if (t_size == (1 << c_size)) 161 { 162 if (++c_size > 12) 163 { 164 --c_size; 165 flag13 = pdc_true; 166 } 167 else 168 c_mask = (1 << c_size) - 1; 169 } 170 } /* for (;;) */ 171 172#undef c_size 173#undef t_size 174#undef i_buff 175#undef i_bits 176#undef o_buff 177#undef o_bits 178} /* pdf_data_source_GIF_fill */ 179 180static void 181pdf_data_source_GIF_terminate(PDF *p, PDF_data_source *src) 182{ 183 pdc_free(p->pdc, (void *) src->buffer_start); 184} 185 186#define PDF_STRING_GIF "\107\111\106" 187#define PDF_STRING_87a "\070\067\141" 188#define PDF_STRING_89a "\070\071\141" 189 190pdc_bool 191pdf_is_GIF_file(PDF *p, pdc_file *fp) 192{ 193 unsigned char buf[3]; 194 195 (void) p; 196 197 if (!PDC_OK_FREAD(fp, buf, 3) || 198 strncmp((const char *) buf, PDF_STRING_GIF, 3) != 0) { 199 pdc_fseek(fp, 0L, SEEK_SET); 200 return pdc_false; 201 } 202 return pdc_true; 203} 204 205int 206pdf_process_GIF_data( 207 PDF *p, 208 int imageslot) 209{ 210 static const char fn[] = "pdf_process_GIF_data"; 211 unsigned char buf[16]; 212 char c; 213 int imageCount = 0; 214 char version[4]; 215 int errcode = 0; 216 pdf_image *image; 217 pdf_colorspace cs; 218 pdf_colormap colormap; 219 int slot; 220 221 image = &p->images[imageslot]; 222 223 224 /* we invert this flag later */ 225 if (image->ignoremask) 226 image->transparent = pdc_true; 227 228 if (image->page == pdc_undef) 229 image->page = 1; 230 231 /* Error reading magic number or not a GIF file */ 232 if (pdf_is_GIF_file(p, image->fp) == pdc_false) { 233 errcode = PDC_E_IO_BADFORMAT; 234 goto PDF_GIF_ERROR; 235 } 236 237 /* Version number */ 238 if (! PDC_OK_FREAD(image->fp, buf, 3)) { 239 errcode = PDC_E_IO_BADFORMAT; 240 goto PDF_GIF_ERROR; 241 } 242 strncpy(version, (const char *) buf, 3); 243 version[3] = '\0'; 244 if ((strcmp(version, PDF_STRING_87a) != 0) && 245 (strcmp(version, PDF_STRING_89a) != 0)) { 246 errcode = PDC_E_IO_BADFORMAT; 247 goto PDF_GIF_ERROR; 248 } 249 250 /* Failed to read screen descriptor */ 251 if (! PDC_OK_FREAD(image->fp, buf, 7)) { 252 errcode = PDC_E_IO_BADFORMAT; 253 goto PDF_GIF_ERROR; 254 } 255 256 cs.type = Indexed; 257 /* size of the global color table */ 258 cs.val.indexed.palette_size = 2 << (buf[4] & 0x07); 259 cs.val.indexed.base = DeviceRGB; 260 cs.val.indexed.colormap = &colormap; 261 cs.val.indexed.colormap_id = PDC_BAD_ID; 262 263 if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ 264 if (ReadColorMap(p->pdc, image->fp, 265 cs.val.indexed.palette_size, &colormap)) { 266 errcode = PDF_E_IMAGE_COLORMAP; 267 goto PDF_GIF_ERROR; 268 } 269 } 270 271 /* translate the aspect ratio to PDFlib notation */ 272 if (buf[6] != 0) { 273 image->dpi_x = -(buf[6] + ((float) 15.0)) / ((float) 64.0); 274 image->dpi_y = (float) -1.0; 275 } 276 277 for (/* */ ; /* */ ; /* */) { 278 /* EOF / read error in image data */ 279 if (!PDC_OK_FREAD(image->fp, &c, 1)) { 280 errcode = PDC_E_IO_NODATA; 281 goto PDF_GIF_ERROR; 282 } 283 284#define PDF_SEMICOLON ((char) 0x3b) /* ASCII ';' */ 285 286 if (c == PDF_SEMICOLON) { /* GIF terminator */ 287 /* Not enough images found in file */ 288 if (imageCount < image->page) { 289 if (!imageCount) 290 errcode = PDF_E_IMAGE_CORRUPT; 291 else 292 errcode = PDF_E_IMAGE_NOPAGE; 293 goto PDF_GIF_ERROR; 294 } 295 break; 296 } 297 298#define PDF_EXCLAM ((char) 0x21) /* ASCII '!' */ 299 300 if (c == PDF_EXCLAM) { /* Extension */ 301 if (!PDC_OK_FREAD(image->fp, &c, 1)) { 302 /* EOF / read error on extension function code */ 303 errcode = PDC_E_IO_NODATA; 304 goto PDF_GIF_ERROR; 305 } 306 DoExtension(p, image, (int) c); 307 continue; 308 } 309 310#define PDF_COMMA ((char) 0x2c) /* ASCII ',' */ 311 312 if (c != PDF_COMMA) { /* Not a valid start character */ 313 /* Bogus character, ignoring */ 314 continue; 315 } 316 317 ++imageCount; 318 319 if (! PDC_OK_FREAD(image->fp, buf, 9)) { 320 /* Couldn't read left/top/width/height */ 321 errcode = PDC_E_IO_NODATA; 322 goto PDF_GIF_ERROR; 323 } 324 325 image->components = 1; 326 image->bpc = 8; 327 image->width = (float) pdc_get_le_ushort(&buf[4]); 328 image->height = (float) pdc_get_le_ushort(&buf[6]); 329 330 if (image->imagemask) 331 { 332 if (p->compatibility <= PDC_1_3) { 333 errcode = PDF_E_IMAGE_MASK1BIT13; 334 goto PDF_GIF_ERROR; 335 } else { 336 /* images with more than one bit will be written as /SMask, 337 * and don't require an /ImageMask entry. 338 */ 339 image->imagemask = pdc_false; 340 } 341 image->colorspace = DeviceGray; 342 } 343 344#define INTERLACE 0x40 345 if (BitSet(buf[8], INTERLACE)) { 346 errcode = PDF_E_GIF_INTERLACED; 347 goto PDF_GIF_ERROR; 348 } 349 350 if (BitSet(buf[8], LOCALCOLORMAP)) { 351 if (ReadColorMap(p->pdc, image->fp, 352 cs.val.indexed.palette_size, &colormap)) 353 { 354 errcode = PDF_E_IMAGE_COLORMAP; 355 goto PDF_GIF_ERROR; 356 } 357 } 358 359 /* read the "LZW initial code size". 360 */ 361 if (!PDC_OK_FREAD(image->fp, buf, 1)) { 362 errcode = PDC_E_IO_NODATA; 363 goto PDF_GIF_ERROR; 364 } 365 if (buf[0] != 8) { 366 if (imageCount > 1) 367 errcode = PDF_E_IMAGE_NOPAGE; 368 else 369 errcode = PDF_E_GIF_LZWSIZE; 370 goto PDF_GIF_ERROR; 371 } 372 373 if (imageCount == image->page) 374 break; 375 } 376 377 image->src.init = pdf_data_source_GIF_init; 378 image->src.fill = pdf_data_source_GIF_fill; 379 image->src.terminate = pdf_data_source_GIF_terminate; 380 image->src.private_data = (void *) image; 381 382 image->compression = lzw; 383 image->use_raw = pdc_true; 384 385 image->params = (char *) pdc_malloc(p->pdc, PDF_MAX_PARAMSTRING, fn); 386 strcpy(image->params, "/EarlyChange 0"); 387 388 image->in_use = pdc_true; /* mark slot as used */ 389 390 slot = pdf_add_colorspace(p, &cs, pdc_false); 391 image->colorspace = (pdf_colorspacetype) slot; 392 393 394 395 pdf_put_image(p, imageslot, pdc_true); 396 397 return imageslot; 398 399 PDF_GIF_ERROR: 400 { 401 const char *stemp = pdc_errprintf(p->pdc, "%s", image->filename); 402 switch (errcode) 403 { 404 case PDC_E_IO_NODATA: 405 case PDF_E_IMAGE_COLORMAP: 406 case PDF_E_GIF_INTERLACED: 407 case PDF_E_GIF_LZWSIZE: 408 pdc_set_errmsg(p->pdc, errcode, stemp, 0, 0, 0); 409 break; 410 411 case PDC_E_IO_BADFORMAT: 412 pdc_set_errmsg(p->pdc, errcode, stemp, "GIF", 0, 0); 413 break; 414 415 case PDF_E_IMAGE_CORRUPT: 416 pdc_set_errmsg(p->pdc, errcode, "GIF", stemp, 0, 0); 417 break; 418 419 case PDF_E_IMAGE_NOPAGE: 420 pdc_set_errmsg(p->pdc, errcode, 421 pdc_errprintf(p->pdc, "%d", image->page), "GIF", stemp, 0); 422 break; 423 424 case 0: /* error code and message already set */ 425 break; 426 } 427 } 428 429 if (image->verbose) 430 pdc_error(p->pdc, -1, 0, 0, 0, 0); 431 432 return -1; 433} /* pdf_open_GIF_data */ 434 435static int 436ReadColorMap(pdc_core *pdc, pdc_file *fp, int number, pdf_colormap *buffer) 437{ 438 int i; 439 unsigned char rgb[3]; 440 441 (void) pdc; 442 443 for (i = 0; i < number; ++i) { 444 if (! PDC_OK_FREAD(fp, rgb, sizeof(rgb))) { 445 return pdc_true; /* yk: true == error */ 446 } 447 448 (*buffer)[i][0] = rgb[0] ; 449 (*buffer)[i][1] = rgb[1] ; 450 (*buffer)[i][2] = rgb[2] ; 451 } 452 return pdc_false; /* yk: false == ok. */ 453} /* ReadColorMap */ 454 455static int 456DoExtension(PDF *p, pdf_image *image, int label) 457{ 458 pdc_byte buf[256]; 459 460 switch ((unsigned char) label) { 461 case 0x01: /* Plain Text Extension */ 462 break; 463 464 case 0xff: /* Application Extension */ 465 break; 466 467 case 0xfe: /* Comment Extension */ 468 while (GetDataBlock(p, image, (unsigned char*) buf) != 0) { 469 /* */ 470 } 471 return pdc_false; 472 473 case 0xf9: /* Graphic Control Extension */ 474 (void) GetDataBlock(p, image, (unsigned char*) buf); 475 476 if ((buf[0] & 0x1) != 0) { 477 image->transparent = !image->transparent; 478 image->transval[0] = buf[3]; 479 } 480 481 while (GetDataBlock(p, image, (unsigned char*) buf) != 0) { 482 /* */ ; 483 } 484 return pdc_false; 485 486 default: 487 break; 488 } 489 490 while (GetDataBlock(p, image, (unsigned char*) buf) != 0) { 491 /* */ ; 492 } 493 494 return pdc_false; 495} /* DoExtension */ 496 497static int 498GetDataBlock(PDF *p, pdf_image *image, unsigned char *buf) 499{ 500 unsigned char count; 501 pdc_file *fp = image->fp; 502 503 if ((!PDC_OK_FREAD(fp, &count, 1)) || 504 ((count != 0) && (!PDC_OK_FREAD(fp, buf, count)))) 505 { 506 const char *stemp = pdc_errprintf(p->pdc, "%s", image->filename); 507 pdc_error(p->pdc, PDF_E_IMAGE_CORRUPT, "GIF", stemp, 0, 0); 508 } 509 510 return count; 511} /* GetDataBlock */ 512 513#endif /* PDF_GIF_SUPPORTED */ 514