1 /* 2 * rdgif.c 3 * 4 * Copyright (C) 1991-1996, Thomas G. Lane. 5 * Modified 2019 by Guido Vollbeding. 6 * This file is part of the Independent JPEG Group's software. 7 * For conditions of distribution and use, see the accompanying README file. 8 * 9 * This file contains routines to read input images in GIF format. 10 * 11 * These routines may need modification for non-Unix environments or 12 * specialized applications. As they stand, they assume input from 13 * an ordinary stdio stream. They further assume that reading begins 14 * at the start of the file; start_input may need work if the 15 * user interface has already read some data (e.g., to determine that 16 * the file is indeed GIF format). 17 */ 18 19 /* 20 * This code is loosely based on giftoppm from the PBMPLUS distribution 21 * of Feb. 1991. That file contains the following copyright notice: 22 * +-------------------------------------------------------------------+ 23 * | Copyright 1990, David Koblas. | 24 * | Permission to use, copy, modify, and distribute this software | 25 * | and its documentation for any purpose and without fee is hereby | 26 * | granted, provided that the above copyright notice appear in all | 27 * | copies and that both that copyright notice and this permission | 28 * | notice appear in supporting documentation. This software is | 29 * | provided "as is" without express or implied warranty. | 30 * +-------------------------------------------------------------------+ 31 */ 32 33 #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ 34 35 #ifdef GIF_SUPPORTED 36 37 38 /* Macros to deal with unsigned chars as efficiently as compiler allows */ 39 40 #ifdef HAVE_UNSIGNED_CHAR 41 typedef unsigned char U_CHAR; 42 #define UCH(x) ((int) (x)) 43 #else /* !HAVE_UNSIGNED_CHAR */ 44 typedef char U_CHAR; 45 #ifdef CHAR_IS_UNSIGNED 46 #define UCH(x) ((int) (x)) 47 #else 48 #define UCH(x) ((int) (x) & 0xFF) 49 #endif 50 #endif /* HAVE_UNSIGNED_CHAR */ 51 52 53 #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) 54 55 56 #define MAXCOLORMAPSIZE 256 /* max # of colors in a GIF colormap */ 57 #define NUMCOLORS 3 /* # of colors */ 58 #define CM_RED 0 /* color component numbers */ 59 #define CM_GREEN 1 60 #define CM_BLUE 2 61 62 #define MAX_LZW_BITS 12 /* maximum LZW code size */ 63 #define LZW_TABLE_SIZE (1<<MAX_LZW_BITS) /* # of possible LZW symbols */ 64 65 /* Macros for extracting header data --- note we assume chars may be signed */ 66 67 #define LM_to_uint(array, offset) ((unsigned int) UCH(array[offset]) + \ 68 (((unsigned int) UCH(array[offset+1])) << 8)) 69 70 #define BitSet(byte, bit) ((byte) & (bit)) 71 #define INTERLACE 0x40 /* mask for bit signifying interlaced image */ 72 #define COLORMAPFLAG 0x80 /* mask for bit signifying colormap presence */ 73 74 75 /* 76 * LZW decompression tables look like this: 77 * symbol_head[K] = prefix symbol of any LZW symbol K (0..LZW_TABLE_SIZE-1) 78 * symbol_tail[K] = suffix byte of any LZW symbol K (0..LZW_TABLE_SIZE-1) 79 * Note that entries 0..end_code of the above tables are not used, 80 * since those symbols represent raw bytes or special codes. 81 * 82 * The stack represents the not-yet-used expansion of the last LZW symbol. 83 * In the worst case, a symbol could expand to as many bytes as there are 84 * LZW symbols, so we allocate LZW_TABLE_SIZE bytes for the stack. 85 * (This is conservative since that number includes the raw-byte symbols.) 86 * 87 * The tables are allocated from FAR heap space since they would use up 88 * rather a lot of the near data space in a PC. 89 */ 90 91 92 /* Private version of data source object */ 93 94 typedef struct { 95 struct cjpeg_source_struct pub; /* public fields */ 96 97 j_compress_ptr cinfo; /* back link saves passing separate parm */ 98 99 JSAMPARRAY colormap; /* GIF colormap (converted to my format) */ 100 101 /* State for GetCode and LZWReadByte */ 102 U_CHAR code_buf[256+4]; /* current input data block */ 103 int last_byte; /* # of bytes in code_buf */ 104 int last_bit; /* # of bits in code_buf */ 105 int cur_bit; /* next bit index to read */ 106 boolean first_time; /* flags first call to GetCode */ 107 boolean out_of_blocks; /* TRUE if hit terminator data block */ 108 109 int input_code_size; /* codesize given in GIF file */ 110 int clear_code, end_code; /* values for Clear and End codes */ 111 112 int code_size; /* current actual code size */ 113 int limit_code; /* 2^code_size */ 114 int max_code; /* first unused code value */ 115 116 /* Private state for LZWReadByte */ 117 int oldcode; /* previous LZW symbol */ 118 int firstcode; /* first byte of oldcode's expansion */ 119 120 /* LZW symbol table and expansion stack */ 121 UINT16 FAR *symbol_head; /* => table of prefix symbols */ 122 UINT8 FAR *symbol_tail; /* => table of suffix bytes */ 123 UINT8 FAR *symbol_stack; /* => stack for symbol expansions */ 124 UINT8 FAR *sp; /* stack pointer */ 125 126 /* State for interlaced image processing */ 127 boolean is_interlaced; /* TRUE if have interlaced image */ 128 jvirt_sarray_ptr interlaced_image; /* full image in interlaced order */ 129 JDIMENSION cur_row_number; /* need to know actual row number */ 130 JDIMENSION pass2_offset; /* # of pixel rows in pass 1 */ 131 JDIMENSION pass3_offset; /* # of pixel rows in passes 1&2 */ 132 JDIMENSION pass4_offset; /* # of pixel rows in passes 1,2,3 */ 133 } gif_source_struct; 134 135 typedef gif_source_struct * gif_source_ptr; 136 137 138 /* Forward declarations */ 139 METHODDEF(JDIMENSION) get_pixel_rows 140 JPP((j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); 141 METHODDEF(JDIMENSION) load_interlaced_image 142 JPP((j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); 143 METHODDEF(JDIMENSION) get_interlaced_row 144 JPP((j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); 145 146 147 LOCAL(int) 148 ReadByte (gif_source_ptr sinfo) 149 /* Read next byte from GIF file */ 150 { 151 register FILE *infile = sinfo->pub.input_file; 152 register int c; 153 154 if ((c = getc(infile)) == EOF) 155 ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); 156 return c; 157 } 158 159 160 LOCAL(int) 161 GetDataBlock (gif_source_ptr sinfo, U_CHAR *buf) 162 /* Read a GIF data block, which has a leading count byte */ 163 /* A zero-length block marks the end of a data block sequence */ 164 { 165 int count; 166 167 count = ReadByte(sinfo); 168 if (count > 0) { 169 if (! ReadOK(sinfo->pub.input_file, buf, count)) 170 ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); 171 } 172 return count; 173 } 174 175 176 LOCAL(void) 177 SkipDataBlocks (gif_source_ptr sinfo) 178 /* Skip a series of data blocks, until a block terminator is found */ 179 { 180 U_CHAR buf[256]; 181 182 while (GetDataBlock(sinfo, buf) > 0) 183 /* skip */; 184 } 185 186 187 LOCAL(void) 188 ReInitLZW (gif_source_ptr sinfo) 189 /* (Re)initialize LZW state; shared code for startup and Clear processing */ 190 { 191 sinfo->code_size = sinfo->input_code_size + 1; 192 sinfo->limit_code = sinfo->clear_code << 1; /* 2^code_size */ 193 sinfo->max_code = sinfo->clear_code + 2; /* first unused code value */ 194 sinfo->sp = sinfo->symbol_stack; /* init stack to empty */ 195 } 196 197 198 LOCAL(void) 199 InitLZWCode (gif_source_ptr sinfo) 200 /* Initialize for a series of LZWReadByte (and hence GetCode) calls */ 201 { 202 /* GetCode initialization */ 203 sinfo->last_byte = 2; /* make safe to "recopy last two bytes" */ 204 sinfo->code_buf[0] = 0; 205 sinfo->code_buf[1] = 0; 206 sinfo->last_bit = 0; /* nothing in the buffer */ 207 sinfo->cur_bit = 0; /* force buffer load on first call */ 208 sinfo->first_time = TRUE; 209 sinfo->out_of_blocks = FALSE; 210 211 /* LZWReadByte initialization: */ 212 /* compute special code values (note that these do not change later) */ 213 sinfo->clear_code = 1 << sinfo->input_code_size; 214 sinfo->end_code = sinfo->clear_code + 1; 215 ReInitLZW(sinfo); 216 } 217 218 219 LOCAL(int) 220 GetCode (gif_source_ptr sinfo) 221 /* Fetch the next code_size bits from the GIF data */ 222 /* We assume code_size is less than 16 */ 223 { 224 register INT32 accum; 225 int offs, count; 226 227 while (sinfo->cur_bit + sinfo->code_size > sinfo->last_bit) { 228 /* Time to reload the buffer */ 229 /* First time, share code with Clear case */ 230 if (sinfo->first_time) { 231 sinfo->first_time = FALSE; 232 return sinfo->clear_code; 233 } 234 if (sinfo->out_of_blocks) { 235 WARNMS(sinfo->cinfo, JWRN_GIF_NOMOREDATA); 236 return sinfo->end_code; /* fake something useful */ 237 } 238 /* preserve last two bytes of what we have -- assume code_size <= 16 */ 239 sinfo->code_buf[0] = sinfo->code_buf[sinfo->last_byte-2]; 240 sinfo->code_buf[1] = sinfo->code_buf[sinfo->last_byte-1]; 241 /* Load more bytes; set flag if we reach the terminator block */ 242 if ((count = GetDataBlock(sinfo, &sinfo->code_buf[2])) == 0) { 243 sinfo->out_of_blocks = TRUE; 244 WARNMS(sinfo->cinfo, JWRN_GIF_NOMOREDATA); 245 return sinfo->end_code; /* fake something useful */ 246 } 247 /* Reset counters */ 248 sinfo->cur_bit = (sinfo->cur_bit - sinfo->last_bit) + 16; 249 sinfo->last_byte = 2 + count; 250 sinfo->last_bit = sinfo->last_byte * 8; 251 } 252 253 /* Form up next 24 bits in accum */ 254 offs = sinfo->cur_bit >> 3; /* byte containing cur_bit */ 255 accum = (INT32) UCH(sinfo->code_buf[offs+2]); 256 accum <<= 8; 257 accum |= (INT32) UCH(sinfo->code_buf[offs+1]); 258 accum <<= 8; 259 accum |= (INT32) UCH(sinfo->code_buf[offs]); 260 261 /* Right-align cur_bit in accum, then mask off desired number of bits */ 262 accum >>= (sinfo->cur_bit & 7); 263 sinfo->cur_bit += sinfo->code_size; 264 return ((int) accum) & ((1 << sinfo->code_size) - 1); 265 } 266 267 268 LOCAL(int) 269 LZWReadByte (gif_source_ptr sinfo) 270 /* Read an LZW-compressed byte */ 271 { 272 register int code; /* current working code */ 273 int incode; /* saves actual input code */ 274 275 /* If any codes are stacked from a previously read symbol, return them */ 276 if (sinfo->sp > sinfo->symbol_stack) 277 return (int) *(-- sinfo->sp); 278 279 /* Time to read a new symbol */ 280 code = GetCode(sinfo); 281 282 if (code == sinfo->clear_code) { 283 /* Reinit state, swallow any extra Clear codes, and */ 284 /* return next code, which is expected to be a raw byte. */ 285 ReInitLZW(sinfo); 286 do { 287 code = GetCode(sinfo); 288 } while (code == sinfo->clear_code); 289 if (code > sinfo->clear_code) { /* make sure it is a raw byte */ 290 WARNMS(sinfo->cinfo, JWRN_GIF_BADDATA); 291 code = 0; /* use something valid */ 292 } 293 /* make firstcode, oldcode valid! */ 294 sinfo->firstcode = sinfo->oldcode = code; 295 return code; 296 } 297 298 if (code == sinfo->end_code) { 299 /* Skip the rest of the image, unless GetCode already read terminator */ 300 if (! sinfo->out_of_blocks) { 301 SkipDataBlocks(sinfo); 302 sinfo->out_of_blocks = TRUE; 303 } 304 /* Complain that there's not enough data */ 305 WARNMS(sinfo->cinfo, JWRN_GIF_ENDCODE); 306 /* Pad data with 0's */ 307 return 0; /* fake something usable */ 308 } 309 310 /* Got normal raw byte or LZW symbol */ 311 incode = code; /* save for a moment */ 312 313 if (code >= sinfo->max_code) { /* special case for not-yet-defined symbol */ 314 /* code == max_code is OK; anything bigger is bad data */ 315 if (code > sinfo->max_code) { 316 WARNMS(sinfo->cinfo, JWRN_GIF_BADDATA); 317 incode = 0; /* prevent creation of loops in symbol table */ 318 } 319 /* this symbol will be defined as oldcode/firstcode */ 320 *(sinfo->sp++) = (UINT8) sinfo->firstcode; 321 code = sinfo->oldcode; 322 } 323 324 /* If it's a symbol, expand it into the stack */ 325 while (code >= sinfo->clear_code) { 326 *(sinfo->sp++) = sinfo->symbol_tail[code]; /* tail is a byte value */ 327 code = sinfo->symbol_head[code]; /* head is another LZW symbol */ 328 } 329 /* At this point code just represents a raw byte */ 330 sinfo->firstcode = code; /* save for possible future use */ 331 332 /* If there's room in table... */ 333 if ((code = sinfo->max_code) < LZW_TABLE_SIZE) { 334 /* Define a new symbol = prev sym + head of this sym's expansion */ 335 sinfo->symbol_head[code] = (UINT16) sinfo->oldcode; 336 sinfo->symbol_tail[code] = (UINT8) sinfo->firstcode; 337 sinfo->max_code++; 338 /* Is it time to increase code_size? */ 339 if (sinfo->max_code >= sinfo->limit_code && 340 sinfo->code_size < MAX_LZW_BITS) { 341 sinfo->code_size++; 342 sinfo->limit_code <<= 1; /* keep equal to 2^code_size */ 343 } 344 } 345 346 sinfo->oldcode = incode; /* save last input symbol for future use */ 347 return sinfo->firstcode; /* return first byte of symbol's expansion */ 348 } 349 350 351 LOCAL(void) 352 ReadColorMap (gif_source_ptr sinfo, int cmaplen, JSAMPARRAY cmap) 353 /* Read a GIF colormap */ 354 { 355 int i; 356 357 for (i = 0; i < cmaplen; i++) { 358 #if BITS_IN_JSAMPLE == 8 359 #define UPSCALE(x) (x) 360 #else 361 #define UPSCALE(x) ((x) << (BITS_IN_JSAMPLE-8)) 362 #endif 363 cmap[CM_RED ][i] = (JSAMPLE) UPSCALE(ReadByte(sinfo)); 364 cmap[CM_GREEN][i] = (JSAMPLE) UPSCALE(ReadByte(sinfo)); 365 cmap[CM_BLUE ][i] = (JSAMPLE) UPSCALE(ReadByte(sinfo)); 366 } 367 } 368 369 370 LOCAL(void) 371 DoExtension (gif_source_ptr sinfo) 372 /* Process an extension block */ 373 /* Currently we ignore 'em all */ 374 { 375 int extlabel; 376 377 /* Read extension label byte */ 378 extlabel = ReadByte(sinfo); 379 TRACEMS1(sinfo->cinfo, 1, JTRC_GIF_EXTENSION, extlabel); 380 /* Skip the data block(s) associated with the extension */ 381 SkipDataBlocks(sinfo); 382 } 383 384 385 /* 386 * Read the file header; return image size and component count. 387 */ 388 389 METHODDEF(void) 390 start_input_gif (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) 391 { 392 gif_source_ptr source = (gif_source_ptr) sinfo; 393 U_CHAR hdrbuf[10]; /* workspace for reading control blocks */ 394 unsigned int width, height; /* image dimensions */ 395 int colormaplen, aspectRatio; 396 int c; 397 398 /* Read and verify GIF Header */ 399 if (! ReadOK(source->pub.input_file, hdrbuf, 6)) 400 ERREXIT(cinfo, JERR_GIF_NOT); 401 if (hdrbuf[0] != 'G' || hdrbuf[1] != 'I' || hdrbuf[2] != 'F') 402 ERREXIT(cinfo, JERR_GIF_NOT); 403 /* Check for expected version numbers. 404 * If unknown version, give warning and try to process anyway; 405 * this is per recommendation in GIF89a standard. 406 */ 407 if ((hdrbuf[3] != '8' || hdrbuf[4] != '7' || hdrbuf[5] != 'a') && 408 (hdrbuf[3] != '8' || hdrbuf[4] != '9' || hdrbuf[5] != 'a')) 409 TRACEMS3(cinfo, 1, JTRC_GIF_BADVERSION, hdrbuf[3], hdrbuf[4], hdrbuf[5]); 410 411 /* Read and decipher Logical Screen Descriptor */ 412 if (! ReadOK(source->pub.input_file, hdrbuf, 7)) 413 ERREXIT(cinfo, JERR_INPUT_EOF); 414 width = LM_to_uint(hdrbuf, 0); 415 height = LM_to_uint(hdrbuf, 2); 416 /* we ignore the color resolution, sort flag, and background color index */ 417 aspectRatio = UCH(hdrbuf[6]); 418 if (aspectRatio != 0 && aspectRatio != 49) 419 TRACEMS(cinfo, 1, JTRC_GIF_NONSQUARE); 420 421 /* Allocate space to store the colormap */ 422 source->colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, 423 JPOOL_IMAGE, (JDIMENSION) MAXCOLORMAPSIZE, (JDIMENSION) NUMCOLORS); 424 colormaplen = 0; /* indicate initialization */ 425 426 /* Read global colormap if header indicates it is present */ 427 if (BitSet(hdrbuf[4], COLORMAPFLAG)) { 428 colormaplen = 2 << (hdrbuf[4] & 0x07); 429 ReadColorMap(source, colormaplen, source->colormap); 430 } 431 432 /* Scan until we reach start of desired image. 433 * We don't currently support skipping images, but could add it easily. 434 */ 435 for (;;) { 436 c = ReadByte(source); 437 438 if (c == ';') /* GIF terminator?? */ 439 ERREXIT(cinfo, JERR_GIF_IMAGENOTFOUND); 440 441 if (c == '!') { /* Extension */ 442 DoExtension(source); 443 continue; 444 } 445 446 if (c != ',') { /* Not an image separator? */ 447 WARNMS1(cinfo, JWRN_GIF_CHAR, c); 448 continue; 449 } 450 451 /* Read and decipher Local Image Descriptor */ 452 if (! ReadOK(source->pub.input_file, hdrbuf, 9)) 453 ERREXIT(cinfo, JERR_INPUT_EOF); 454 /* we ignore top/left position info, also sort flag */ 455 width = LM_to_uint(hdrbuf, 4); 456 height = LM_to_uint(hdrbuf, 6); 457 source->is_interlaced = (BitSet(hdrbuf[8], INTERLACE) != 0); 458 459 /* Read local colormap if header indicates it is present */ 460 /* Note: if we wanted to support skipping images, */ 461 /* we'd need to skip rather than read colormap for ignored images */ 462 if (BitSet(hdrbuf[8], COLORMAPFLAG)) { 463 colormaplen = 2 << (hdrbuf[8] & 0x07); 464 ReadColorMap(source, colormaplen, source->colormap); 465 } 466 467 source->input_code_size = ReadByte(source); /* get min-code-size byte */ 468 if (source->input_code_size < 2 || source->input_code_size > 8) 469 ERREXIT1(cinfo, JERR_GIF_CODESIZE, source->input_code_size); 470 471 /* Reached desired image, so break out of loop */ 472 /* If we wanted to skip this image, */ 473 /* we'd call SkipDataBlocks and then continue the loop */ 474 break; 475 } 476 477 /* Prepare to read selected image: first initialize LZW decompressor */ 478 source->symbol_head = (UINT16 FAR *) (*cinfo->mem->alloc_large) 479 ((j_common_ptr) cinfo, JPOOL_IMAGE, LZW_TABLE_SIZE * SIZEOF(UINT16)); 480 source->symbol_tail = (UINT8 FAR *) (*cinfo->mem->alloc_large) 481 ((j_common_ptr) cinfo, JPOOL_IMAGE, LZW_TABLE_SIZE * SIZEOF(UINT8)); 482 source->symbol_stack = (UINT8 FAR *) (*cinfo->mem->alloc_large) 483 ((j_common_ptr) cinfo, JPOOL_IMAGE, LZW_TABLE_SIZE * SIZEOF(UINT8)); 484 InitLZWCode(source); 485 486 /* 487 * If image is interlaced, we read it into a full-size sample array, 488 * decompressing as we go; then get_interlaced_row selects rows from the 489 * sample array in the proper order. 490 */ 491 if (source->is_interlaced) { 492 /* We request the virtual array now, but can't access it until virtual 493 * arrays have been allocated. Hence, the actual work of reading the 494 * image is postponed until the first call to get_pixel_rows. 495 */ 496 source->interlaced_image = (*cinfo->mem->request_virt_sarray) 497 ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, 498 (JDIMENSION) width, (JDIMENSION) height, (JDIMENSION) 1); 499 if (cinfo->progress != NULL) { 500 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; 501 progress->total_extra_passes++; /* count file input as separate pass */ 502 } 503 source->pub.get_pixel_rows = load_interlaced_image; 504 } else { 505 source->pub.get_pixel_rows = get_pixel_rows; 506 } 507 508 /* Create compressor input buffer. */ 509 source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, 510 JPOOL_IMAGE, (JDIMENSION) width * NUMCOLORS, (JDIMENSION) 1); 511 source->pub.buffer_height = 1; 512 513 /* Pad colormap for safety. */ 514 for (c = colormaplen; c < source->clear_code; c++) { 515 source->colormap[CM_RED ][c] = 516 source->colormap[CM_GREEN][c] = 517 source->colormap[CM_BLUE ][c] = CENTERJSAMPLE; 518 } 519 520 /* Return info about the image. */ 521 cinfo->in_color_space = JCS_RGB; 522 cinfo->input_components = NUMCOLORS; 523 cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */ 524 cinfo->image_width = width; 525 cinfo->image_height = height; 526 527 TRACEMS3(cinfo, 1, JTRC_GIF, width, height, colormaplen); 528 } 529 530 531 /* 532 * Read one row of pixels. 533 * This version is used for noninterlaced GIF images: 534 * we read directly from the GIF file. 535 */ 536 537 METHODDEF(JDIMENSION) 538 get_pixel_rows (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) 539 { 540 gif_source_ptr source = (gif_source_ptr) sinfo; 541 register int c; 542 register JSAMPROW ptr; 543 register JDIMENSION col; 544 register JSAMPARRAY colormap = source->colormap; 545 546 ptr = source->pub.buffer[0]; 547 for (col = cinfo->image_width; col > 0; col--) { 548 c = LZWReadByte(source); 549 *ptr++ = colormap[CM_RED ][c]; 550 *ptr++ = colormap[CM_GREEN][c]; 551 *ptr++ = colormap[CM_BLUE ][c]; 552 } 553 return 1; 554 } 555 556 557 /* 558 * Read one row of pixels. 559 * This version is used for the first call on get_pixel_rows when 560 * reading an interlaced GIF file: we read the whole image into memory. 561 */ 562 563 METHODDEF(JDIMENSION) 564 load_interlaced_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) 565 { 566 gif_source_ptr source = (gif_source_ptr) sinfo; 567 register JSAMPROW sptr; 568 register JDIMENSION col; 569 JDIMENSION row; 570 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; 571 572 /* Read the interlaced image into the virtual array we've created. */ 573 for (row = 0; row < cinfo->image_height; row++) { 574 if (progress != NULL) { 575 progress->pub.pass_counter = (long) row; 576 progress->pub.pass_limit = (long) cinfo->image_height; 577 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); 578 } 579 sptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, 580 source->interlaced_image, row, (JDIMENSION) 1, TRUE); 581 for (col = cinfo->image_width; col > 0; col--) { 582 *sptr++ = (JSAMPLE) LZWReadByte(source); 583 } 584 } 585 if (progress != NULL) 586 progress->completed_extra_passes++; 587 588 /* Replace method pointer so subsequent calls don't come here. */ 589 source->pub.get_pixel_rows = get_interlaced_row; 590 /* Initialize for get_interlaced_row, and perform first call on it. */ 591 source->cur_row_number = 0; 592 source->pass2_offset = (cinfo->image_height + 7) / 8; 593 source->pass3_offset = source->pass2_offset + (cinfo->image_height + 3) / 8; 594 source->pass4_offset = source->pass3_offset + (cinfo->image_height + 1) / 4; 595 596 return get_interlaced_row(cinfo, sinfo); 597 } 598 599 600 /* 601 * Read one row of pixels. 602 * This version is used for interlaced GIF images: 603 * we read from the virtual array. 604 */ 605 606 METHODDEF(JDIMENSION) 607 get_interlaced_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) 608 { 609 gif_source_ptr source = (gif_source_ptr) sinfo; 610 register int c; 611 register JSAMPROW sptr, ptr; 612 register JDIMENSION col; 613 register JSAMPARRAY colormap = source->colormap; 614 JDIMENSION irow; 615 616 /* Figure out which row of interlaced image is needed, and access it. */ 617 switch ((int) (source->cur_row_number & 7)) { 618 case 0: /* first-pass row */ 619 irow = source->cur_row_number >> 3; 620 break; 621 case 4: /* second-pass row */ 622 irow = (source->cur_row_number >> 3) + source->pass2_offset; 623 break; 624 case 2: /* third-pass row */ 625 case 6: 626 irow = (source->cur_row_number >> 2) + source->pass3_offset; 627 break; 628 default: /* fourth-pass row */ 629 irow = (source->cur_row_number >> 1) + source->pass4_offset; 630 } 631 sptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, 632 source->interlaced_image, irow, (JDIMENSION) 1, FALSE); 633 /* Scan the row, expand colormap, and output */ 634 ptr = source->pub.buffer[0]; 635 for (col = cinfo->image_width; col > 0; col--) { 636 c = GETJSAMPLE(*sptr++); 637 *ptr++ = colormap[CM_RED ][c]; 638 *ptr++ = colormap[CM_GREEN][c]; 639 *ptr++ = colormap[CM_BLUE ][c]; 640 } 641 source->cur_row_number++; /* for next time */ 642 return 1; 643 } 644 645 646 /* 647 * Finish up at the end of the file. 648 */ 649 650 METHODDEF(void) 651 finish_input_gif (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) 652 { 653 /* no work */ 654 } 655 656 657 /* 658 * The module selection routine for GIF format input. 659 */ 660 661 GLOBAL(cjpeg_source_ptr) 662 jinit_read_gif (j_compress_ptr cinfo) 663 { 664 gif_source_ptr source; 665 666 /* Create module interface object */ 667 source = (gif_source_ptr) (*cinfo->mem->alloc_small) 668 ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(gif_source_struct)); 669 source->cinfo = cinfo; /* make back link for subroutines */ 670 /* Fill in method ptrs, except get_pixel_rows which start_input sets */ 671 source->pub.start_input = start_input_gif; 672 source->pub.finish_input = finish_input_gif; 673 674 return &source->pub; 675 } 676 677 #endif /* GIF_SUPPORTED */ 678