Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/libjpeg/rdgif.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * rdgif.c | |
| 3 * | |
| 4 * Copyright (C) 1991-1996, Thomas G. Lane. | |
| 5 * Modified 2019-2020 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 if (width <= 0 || height <= 0) | |
| 458 ERREXIT(cinfo, JERR_GIF_OUTOFRANGE); | |
| 459 source->is_interlaced = (BitSet(hdrbuf[8], INTERLACE) != 0); | |
| 460 | |
| 461 /* Read local colormap if header indicates it is present */ | |
| 462 /* Note: if we wanted to support skipping images, */ | |
| 463 /* we'd need to skip rather than read colormap for ignored images */ | |
| 464 if (BitSet(hdrbuf[8], COLORMAPFLAG)) { | |
| 465 colormaplen = 2 << (hdrbuf[8] & 0x07); | |
| 466 ReadColorMap(source, colormaplen, source->colormap); | |
| 467 } | |
| 468 | |
| 469 source->input_code_size = ReadByte(source); /* get min-code-size byte */ | |
| 470 if (source->input_code_size < 2 || source->input_code_size > 8) | |
| 471 ERREXIT1(cinfo, JERR_GIF_CODESIZE, source->input_code_size); | |
| 472 | |
| 473 /* Reached desired image, so break out of loop */ | |
| 474 /* If we wanted to skip this image, */ | |
| 475 /* we'd call SkipDataBlocks and then continue the loop */ | |
| 476 break; | |
| 477 } | |
| 478 | |
| 479 /* Prepare to read selected image: first initialize LZW decompressor */ | |
| 480 source->symbol_head = (UINT16 FAR *) (*cinfo->mem->alloc_large) | |
| 481 ((j_common_ptr) cinfo, JPOOL_IMAGE, LZW_TABLE_SIZE * SIZEOF(UINT16)); | |
| 482 source->symbol_tail = (UINT8 FAR *) (*cinfo->mem->alloc_large) | |
| 483 ((j_common_ptr) cinfo, JPOOL_IMAGE, LZW_TABLE_SIZE * SIZEOF(UINT8)); | |
| 484 source->symbol_stack = (UINT8 FAR *) (*cinfo->mem->alloc_large) | |
| 485 ((j_common_ptr) cinfo, JPOOL_IMAGE, LZW_TABLE_SIZE * SIZEOF(UINT8)); | |
| 486 InitLZWCode(source); | |
| 487 | |
| 488 /* | |
| 489 * If image is interlaced, we read it into a full-size sample array, | |
| 490 * decompressing as we go; then get_interlaced_row selects rows from the | |
| 491 * sample array in the proper order. | |
| 492 */ | |
| 493 if (source->is_interlaced) { | |
| 494 /* We request the virtual array now, but can't access it until virtual | |
| 495 * arrays have been allocated. Hence, the actual work of reading the | |
| 496 * image is postponed until the first call to get_pixel_rows. | |
| 497 */ | |
| 498 source->interlaced_image = (*cinfo->mem->request_virt_sarray) | |
| 499 ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, | |
| 500 (JDIMENSION) width, (JDIMENSION) height, (JDIMENSION) 1); | |
| 501 if (cinfo->progress != NULL) { | |
| 502 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; | |
| 503 progress->total_extra_passes++; /* count file input as separate pass */ | |
| 504 } | |
| 505 source->pub.get_pixel_rows = load_interlaced_image; | |
| 506 } else { | |
| 507 source->pub.get_pixel_rows = get_pixel_rows; | |
| 508 } | |
| 509 | |
| 510 /* Create compressor input buffer. */ | |
| 511 source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, | |
| 512 JPOOL_IMAGE, (JDIMENSION) width * NUMCOLORS, (JDIMENSION) 1); | |
| 513 source->pub.buffer_height = 1; | |
| 514 | |
| 515 /* Pad colormap for safety. */ | |
| 516 for (c = colormaplen; c < source->clear_code; c++) { | |
| 517 source->colormap[CM_RED ][c] = | |
| 518 source->colormap[CM_GREEN][c] = | |
| 519 source->colormap[CM_BLUE ][c] = CENTERJSAMPLE; | |
| 520 } | |
| 521 | |
| 522 /* Return info about the image. */ | |
| 523 cinfo->in_color_space = JCS_RGB; | |
| 524 cinfo->input_components = NUMCOLORS; | |
| 525 cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */ | |
| 526 cinfo->image_width = width; | |
| 527 cinfo->image_height = height; | |
| 528 | |
| 529 TRACEMS3(cinfo, 1, JTRC_GIF, width, height, colormaplen); | |
| 530 } | |
| 531 | |
| 532 | |
| 533 /* | |
| 534 * Read one row of pixels. | |
| 535 * This version is used for noninterlaced GIF images: | |
| 536 * we read directly from the GIF file. | |
| 537 */ | |
| 538 | |
| 539 METHODDEF(JDIMENSION) | |
| 540 get_pixel_rows (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | |
| 541 { | |
| 542 gif_source_ptr source = (gif_source_ptr) sinfo; | |
| 543 register int c; | |
| 544 register JSAMPROW ptr; | |
| 545 register JDIMENSION col; | |
| 546 register JSAMPARRAY colormap = source->colormap; | |
| 547 | |
| 548 ptr = source->pub.buffer[0]; | |
| 549 for (col = cinfo->image_width; col > 0; col--) { | |
| 550 c = LZWReadByte(source); | |
| 551 *ptr++ = colormap[CM_RED ][c]; | |
| 552 *ptr++ = colormap[CM_GREEN][c]; | |
| 553 *ptr++ = colormap[CM_BLUE ][c]; | |
| 554 } | |
| 555 return 1; | |
| 556 } | |
| 557 | |
| 558 | |
| 559 /* | |
| 560 * Read one row of pixels. | |
| 561 * This version is used for the first call on get_pixel_rows when | |
| 562 * reading an interlaced GIF file: we read the whole image into memory. | |
| 563 */ | |
| 564 | |
| 565 METHODDEF(JDIMENSION) | |
| 566 load_interlaced_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | |
| 567 { | |
| 568 gif_source_ptr source = (gif_source_ptr) sinfo; | |
| 569 register JSAMPROW sptr; | |
| 570 register JDIMENSION col; | |
| 571 JDIMENSION row; | |
| 572 cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; | |
| 573 | |
| 574 /* Read the interlaced image into the virtual array we've created. */ | |
| 575 for (row = 0; row < cinfo->image_height; row++) { | |
| 576 if (progress != NULL) { | |
| 577 progress->pub.pass_counter = (long) row; | |
| 578 progress->pub.pass_limit = (long) cinfo->image_height; | |
| 579 (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); | |
| 580 } | |
| 581 sptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, | |
| 582 source->interlaced_image, row, (JDIMENSION) 1, TRUE); | |
| 583 for (col = cinfo->image_width; col > 0; col--) { | |
| 584 *sptr++ = (JSAMPLE) LZWReadByte(source); | |
| 585 } | |
| 586 } | |
| 587 if (progress != NULL) | |
| 588 progress->completed_extra_passes++; | |
| 589 | |
| 590 /* Replace method pointer so subsequent calls don't come here. */ | |
| 591 source->pub.get_pixel_rows = get_interlaced_row; | |
| 592 /* Initialize for get_interlaced_row, and perform first call on it. */ | |
| 593 source->cur_row_number = 0; | |
| 594 source->pass2_offset = (cinfo->image_height + 7) / 8; | |
| 595 source->pass3_offset = source->pass2_offset + (cinfo->image_height + 3) / 8; | |
| 596 source->pass4_offset = source->pass3_offset + (cinfo->image_height + 1) / 4; | |
| 597 | |
| 598 return get_interlaced_row(cinfo, sinfo); | |
| 599 } | |
| 600 | |
| 601 | |
| 602 /* | |
| 603 * Read one row of pixels. | |
| 604 * This version is used for interlaced GIF images: | |
| 605 * we read from the virtual array. | |
| 606 */ | |
| 607 | |
| 608 METHODDEF(JDIMENSION) | |
| 609 get_interlaced_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | |
| 610 { | |
| 611 gif_source_ptr source = (gif_source_ptr) sinfo; | |
| 612 register int c; | |
| 613 register JSAMPROW sptr, ptr; | |
| 614 register JDIMENSION col; | |
| 615 register JSAMPARRAY colormap = source->colormap; | |
| 616 JDIMENSION irow; | |
| 617 | |
| 618 /* Figure out which row of interlaced image is needed, and access it. */ | |
| 619 switch ((int) (source->cur_row_number & 7)) { | |
| 620 case 0: /* first-pass row */ | |
| 621 irow = source->cur_row_number >> 3; | |
| 622 break; | |
| 623 case 4: /* second-pass row */ | |
| 624 irow = (source->cur_row_number >> 3) + source->pass2_offset; | |
| 625 break; | |
| 626 case 2: /* third-pass row */ | |
| 627 case 6: | |
| 628 irow = (source->cur_row_number >> 2) + source->pass3_offset; | |
| 629 break; | |
| 630 default: /* fourth-pass row */ | |
| 631 irow = (source->cur_row_number >> 1) + source->pass4_offset; | |
| 632 } | |
| 633 sptr = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, | |
| 634 source->interlaced_image, irow, (JDIMENSION) 1, FALSE); | |
| 635 /* Scan the row, expand colormap, and output */ | |
| 636 ptr = source->pub.buffer[0]; | |
| 637 for (col = cinfo->image_width; col > 0; col--) { | |
| 638 c = GETJSAMPLE(*sptr++); | |
| 639 *ptr++ = colormap[CM_RED ][c]; | |
| 640 *ptr++ = colormap[CM_GREEN][c]; | |
| 641 *ptr++ = colormap[CM_BLUE ][c]; | |
| 642 } | |
| 643 source->cur_row_number++; /* for next time */ | |
| 644 return 1; | |
| 645 } | |
| 646 | |
| 647 | |
| 648 /* | |
| 649 * Finish up at the end of the file. | |
| 650 */ | |
| 651 | |
| 652 METHODDEF(void) | |
| 653 finish_input_gif (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | |
| 654 { | |
| 655 /* no work */ | |
| 656 } | |
| 657 | |
| 658 | |
| 659 /* | |
| 660 * The module selection routine for GIF format input. | |
| 661 */ | |
| 662 | |
| 663 GLOBAL(cjpeg_source_ptr) | |
| 664 jinit_read_gif (j_compress_ptr cinfo) | |
| 665 { | |
| 666 gif_source_ptr source; | |
| 667 | |
| 668 /* Create module interface object */ | |
| 669 source = (gif_source_ptr) (*cinfo->mem->alloc_small) | |
| 670 ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(gif_source_struct)); | |
| 671 source->cinfo = cinfo; /* make back link for subroutines */ | |
| 672 /* Fill in method ptrs, except get_pixel_rows which start_input sets */ | |
| 673 source->pub.start_input = start_input_gif; | |
| 674 source->pub.finish_input = finish_input_gif; | |
| 675 | |
| 676 return &source->pub; | |
| 677 } | |
| 678 | |
| 679 #endif /* GIF_SUPPORTED */ |
