4 * Code for reading and processing JPEG markers. Large parts are grabbed
5 * from the IJG software
8 * $Id: read.c,v 1.2 2004/08/18 02:26:08 malaterre Exp $
19 * To fix a memory leak (memory malloc'd then never freed) in the original
20 * version of lossless JPEG decompression, memory is allocated for 4
21 * Huffman tables once here, then pointers set later as needed
24 static HuffmanTable HuffmanTableMemory[4];
27 * Enumerate all the JPEG marker codes
84 *--------------------------------------------------------------
88 * Get a 2-byte unsigned integer (e.g., a marker parameter length
92 * Next two byte of input as an integer.
95 * Bitstream is parsed.
97 *--------------------------------------------------------------
99 static Uint Get2bytes (void)
103 return (a << 8) + GetJpegChar();
107 *--------------------------------------------------------------
111 * Skip over an unknown or uninteresting variable-length marker
117 * Bitstream is parsed over marker.
120 *--------------------------------------------------------------
122 static void SkipVariable (DecompressInfo *dcPtr)
126 length = Get2bytes () - 2;
134 *--------------------------------------------------------------
138 * Process a DHT marker
144 * A huffman table is read.
147 *--------------------------------------------------------------
149 static void GetDht (DecompressInfo *dcPtr)
155 HuffmanTable **htblptr=NULL;
157 length = Get2bytes () - 2;
160 index = GetJpegChar();
164 for (i = 1; i <= 16; i++) {
165 bits[i] = GetJpegChar();
170 fprintf (stderr, "Bogus DHT counts\n");
172 dcPtr->error = -1; return;
175 for (i = 0; i < count; i++)
176 huffval[i] = GetJpegChar();
178 length -= 1 + 16 + count;
180 if (index & 0x10) { /* AC table definition */
181 fprintf(stderr,"Huffman table for lossless JPEG is not defined.\n");
183 else { /* DC table definition */
184 htblptr = &dcPtr->dcHuffTblPtrs[index];
187 if (index < 0 || index >= 4)
189 fprintf (stderr, "Bogus DHT index %d\n", index);
191 dcPtr->error = -1; return;
194 if (*htblptr == NULL)
196 *htblptr = &HuffmanTableMemory[index];
199 fprintf(stderr,"Can't malloc HuffmanTable\n");
201 dcPtr->error = -1; return;
205 MEMCPY((*htblptr)->bits, bits, sizeof ((*htblptr)->bits));
206 MEMCPY((*htblptr)->huffval, huffval, sizeof ((*htblptr)->huffval));
211 *--------------------------------------------------------------
215 * Process a DRI marker
222 * Bitstream is parsed.
224 *--------------------------------------------------------------
226 static void GetDri (DecompressInfo *dcPtr)
228 if (Get2bytes () != 4)
230 fprintf (stderr, "Bogus length in DRI\n");
232 dcPtr->error = -1; return;
235 dcPtr->restartInterval = (Ushort) Get2bytes ();
239 *--------------------------------------------------------------
243 * Process an APP0 marker.
249 * Bitstream is parsed
251 *--------------------------------------------------------------
253 static void GetApp0 (DecompressInfo *dcPtr)
257 length = Get2bytes () - 2;
258 while (length-- > 0) /* skip any remaining data */
263 *--------------------------------------------------------------
267 * Process a SOFn marker
273 * Bitstream is parsed
275 * dcPtr structure is filled in
277 *--------------------------------------------------------------
279 static void GetSof (DecompressInfo *dcPtr, int code)
284 JpegComponentInfo *compptr;
288 length = Get2bytes ();
290 dcPtr->dataPrecision = GetJpegChar();
291 dcPtr->imageHeight = Get2bytes ();
292 dcPtr->imageWidth = Get2bytes ();
293 dcPtr->numComponents = GetJpegChar();
296 * We don't support files in which the image height is initially
297 * specified as 0 and is later redefined by DNL. As long as we
298 * have to check that, might as well have a general sanity check.
300 if ((dcPtr->imageHeight <= 0 ) ||
301 (dcPtr->imageWidth <= 0) ||
302 (dcPtr->numComponents <= 0)) {
303 fprintf (stderr, "Empty JPEG image (DNL not supported)\n");
305 dcPtr->error = -1; return;
308 if ((dcPtr->dataPrecision<MinPrecisionBits) ||
309 (dcPtr->dataPrecision>MaxPrecisionBits)) {
310 fprintf (stderr, "Unsupported JPEG data precision\n");
312 dcPtr->error = -1; return;
315 if (length != (dcPtr->numComponents * 3 + 8)) {
316 fprintf (stderr, "Bogus SOF length\n");
318 dcPtr->error = -1; return;
321 for (ci = 0; ci < dcPtr->numComponents; ci++) {
322 compptr = &dcPtr->compInfo[ci];
323 compptr->componentIndex = ci;
324 compptr->componentId = GetJpegChar();
326 compptr->hSampFactor = (c >> 4) & 15;
327 compptr->vSampFactor = (c) & 15;
328 (void) GetJpegChar(); /* skip Tq */
334 *--------------------------------------------------------------
338 * Process a SOS marker
344 * Bitstream is parsed.
347 *--------------------------------------------------------------
349 static void GetSos (DecompressInfo *dcPtr)
353 JpegComponentInfo *compptr;
355 length = Get2bytes ();
358 * Get the number of image components.
361 dcPtr->compsInScan = n;
364 if (length != (n * 2 + 3) || n < 1 || n > 4) {
365 fprintf (stderr, "Bogus SOS length\n");
367 dcPtr->error = -1; return;
371 for (i = 0; i < n; i++) {
376 for (ci = 0; ci < dcPtr->numComponents; ci++)
377 if (cc == dcPtr->compInfo[ci].componentId) {
381 if (ci >= dcPtr->numComponents) {
382 fprintf (stderr, "Invalid component number in SOS\n");
384 dcPtr->error = -1; return;
387 compptr = &dcPtr->compInfo[ci];
388 dcPtr->curCompInfo[i] = compptr;
389 compptr->dcTblNo = (c >> 4) & 15;
393 * Get the PSV, skip Se, and get the point transform parameter.
395 dcPtr->Ss = GetJpegChar();
398 dcPtr->Pt = c & 0x0F;
403 *--------------------------------------------------------------
407 * Process an SOI marker
413 * Bitstream is parsed.
416 *--------------------------------------------------------------
418 static void GetSoi (DecompressInfo *dcPtr)
422 * Reset all parameters that are defined to be reset by SOI
424 dcPtr->restartInterval = 0;
428 *--------------------------------------------------------------
432 * Find the next JPEG marker Note that the output might not
433 * be a valid marker code but it will never be 0 or FF
439 * Bitstream is parsed.
441 *--------------------------------------------------------------
443 static int NextMarker (void)
450 * skip any non-FF bytes
457 * skip any duplicate FFs without incrementing nbytes, since
458 * extra FFs are legal
463 } while (c == 0); /* repeat if it was a stuffed FF/00 */
469 *--------------------------------------------------------------
473 * Scan and process JPEG markers that can appear in any order
474 * Return when an SOI, EOI, SOFn, or SOS is found
480 * Bitstream is parsed.
482 *--------------------------------------------------------------
484 static JpegMarker ProcessTables (dcPtr)
485 DecompressInfo *dcPtr;
510 return ((JpegMarker)c);
513 GetDht (dcPtr); if (dcPtr->error) return 0;
517 fprintf(stderr,"Not a lossless JPEG file.\n");
521 GetDri (dcPtr); if (dcPtr->error) return 0;
528 case M_RST0: /* these are all parameterless */
537 fprintf (stderr, "Warning: unexpected marker 0x%02x\n", c);
540 default: /* must be DNL, DHP, EXP, APPn, JPGn, COM,
542 SkipVariable (dcPtr);
546 }/*endof ProcessTables */
550 *--------------------------------------------------------------
554 * Initialize and read the file header (everything through
563 *--------------------------------------------------------------
565 void ReadFileHeader (DecompressInfo *dcPtr)
570 * Demand an SOI marker at the start of the file --- otherwise it's
571 * probably not a JPEG file at all.
575 if ((c != 0xFF) || (c2 != M_SOI)) {
577 fprintf(stderr, "Reached end of input file. All done!\n");
578 /* fclose(outFile); */
580 dcPtr->error = -1; return;
582 fprintf (stderr, "Not a JPEG file. Found %02X %02X\n", c, c2);
584 dcPtr->error = -1; return;
588 GetSoi (dcPtr); if (dcPtr->error) return; /* OK, process SOI */
591 * Process markers until SOF
593 c = ProcessTables (dcPtr); if (dcPtr->error) return;
603 fprintf (stderr, "Unsupported SOF marker type 0x%02x\n", c);
606 }/*endof ReadFileHeader*/
610 *--------------------------------------------------------------
614 * Read the start of a scan (everything through the SOS marker).
617 * 1 if find SOS, 0 if find EOI
620 * Bitstream is parsed, may exit on errors.
622 *--------------------------------------------------------------
624 int ReadScanHeader (DecompressInfo *dcPtr)
629 * Process markers until SOS or EOI
631 c = ProcessTables (dcPtr); if (dcPtr->error) return 0;
642 fprintf (stderr, "Unexpected marker 0x%02x\n", c);
646 }/*endof ReadScanHeader*/
650 *--------------------------------------------------------------
652 * GetJpegChar, UnGetJpegChar --
656 * GetJpegChar returns the next character in the stream, or EOF
657 * UnGetJpegChar returns nothing.
660 * A byte is consumed or put back into the inputBuffer.
662 *--------------------------------------------------------------
664 int GetJpegChar(void)
666 return (int)inputBuffer[inputBufferOffset++];
669 void UnGetJpegChar(int ch)
671 inputBuffer[--inputBufferOffset] = ch;