home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
new
/
gfx
/
edit
/
tsmorph
/
src
/
jpeg_ls
/
jrdjfif.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-18
|
23KB
|
843 lines
/*
* jrdjfif.c
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains routines to decode standard JPEG file headers/markers.
* This code will handle "raw JPEG" and JFIF-convention JPEG files.
*
* You can also use this module to decode a raw-JPEG or JFIF-standard data
* stream that is embedded within a larger file. To do that, you must
* position the file to the JPEG SOI marker (0xFF/0xD8) that begins the
* data sequence to be decoded. If nothing better is possible, you can scan
* the file until you see the SOI marker, then use JUNGETC to push it back.
*
* This module relies on the JGETC macro and the read_jpeg_data method (which
* is provided by the user interface) to read from the JPEG data stream.
* Therefore, this module is not dependent on any particular assumption about
* the data source; it need not be a stdio stream at all. (This fact does
* NOT carry over to more complex JPEG file formats such as JPEG-in-TIFF;
* those format control modules may well need to assume stdio input.)
*
* These routines are invoked via the methods read_file_header,
* read_scan_header, read_jpeg_data, read_scan_trailer, and read_file_trailer.
*/
#include "jinclude.h"
#ifdef JFIF_SUPPORTED
typedef enum { /* JPEG marker codes */
M_SOF0 = 0xc0,
M_SOF1 = 0xc1,
M_SOF2 = 0xc2,
M_SOF3 = 0xc3,
M_SOF5 = 0xc5,
M_SOF6 = 0xc6,
M_SOF7 = 0xc7,
M_JPG = 0xc8,
M_SOF9 = 0xc9,
M_SOF10 = 0xca,
M_SOF11 = 0xcb,
M_SOF13 = 0xcd,
M_SOF14 = 0xce,
M_SOF15 = 0xcf,
M_DHT = 0xc4,
M_DAC = 0xcc,
M_RST0 = 0xd0,
M_RST1 = 0xd1,
M_RST2 = 0xd2,
M_RST3 = 0xd3,
M_RST4 = 0xd4,
M_RST5 = 0xd5,
M_RST6 = 0xd6,
M_RST7 = 0xd7,
M_SOI = 0xd8,
M_EOI = 0xd9,
M_SOS = 0xda,
M_DQT = 0xdb,
M_DNL = 0xdc,
M_DRI = 0xdd,
M_DHP = 0xde,
M_EXP = 0xdf,
M_APP0 = 0xe0,
M_APP15 = 0xef,
M_JPG0 = 0xf0,
M_JPG13 = 0xfd,
M_COM = 0xfe,
M_TEM = 0x01,
M_ERROR = 0x100
} JPEG_MARKER;
/*
* Reload the input buffer after it's been emptied, and return the next byte.
* This is exported for direct use by the entropy decoder.
* See the JGETC macro for calling conditions. Note in particular that
* read_jpeg_data may NOT return EOF. If no more data is available, it must
* exit via ERREXIT, or perhaps synthesize fake data (such as an RST marker).
* For error recovery purposes, synthesizing an EOI marker is probably best.
*
* For this header control module, read_jpeg_data is supplied by the
* user interface. However, header formats that require random access
* to the input file would need to supply their own code. This code is
* left here to indicate what is required.
*/
#if 0 /* not needed in this module */
METHODDEF int
read_jpeg_data (decompress_info_ptr cinfo)
{
cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
cinfo->bytes_in_buffer = (int) JFREAD(cinfo->input_file,
cinfo->next_input_byte,
JPEG_BUF_SIZE);
if (cinfo->bytes_in_buffer <= 0) {
WARNMS(cinfo->emethods, "Premature EOF in JPEG file");
cinfo->next_input_byte[0] = (char) 0xFF;
cinfo->next_input_byte[1] = (char) M_EOI;
cinfo->bytes_in_buffer = 2;
}
return JGETC(cinfo);
}
#endif
/*
* Routines to parse JPEG markers & save away the useful info.
*/
LOCAL INT32
get_2bytes (decompress_info_ptr cinfo)
/* Get a 2-byte unsigned integer (e.g., a marker parameter length field) */
{
INT32 a;
a = JGETC(cinfo);
return (a << 8) + JGETC(cinfo);
}
LOCAL void
skip_variable (decompress_info_ptr cinfo, int code)
/* Skip over an unknown or uninteresting variable-length marker */
{
INT32 length;
length = get_2bytes(cinfo);
TRACEMS2(cinfo->emethods, 1,
"Skipping marker 0x%02x, length %ld", code, (int) length);
for (length -= 2; length > 0; length--)
(void) JGETC(cinfo);
}
LOCAL void
get_dht (decompress_info_ptr cinfo)
/* Process a DHT marker */
{
INT32 length;
UINT8 bits[17];
UINT8 huffval[256];
int i, index, count;
HUFF_TBL **htblptr;
length = get_2bytes(cinfo)-2;
while (length > 0) {
index = JGETC(cinfo);
TRACEMS1(cinfo->emethods, 1, "Define Huffman Table 0x%02x", index);
bits[0] = 0;
count = 0;
for (i = 1; i <= 16; i++) {
bits[i] = (UINT8) JGETC(cinfo);
count += bits[i];
}
TRACEMS8(cinfo->emethods, 2, " %3ld %3ld %3ld %3ld %3ld %3ld %3ld %3ld",
bits[1], bits[2], bits[3], bits[4],
bits[5], bits[6], bits[7], bits[8]);
TRACEMS8(cinfo->emethods, 2, " %3ld %3ld %3ld %3ld %3ld %3ld %3ld %3ld",
bits[9], bits[10], bits[11], bits[12],
bits[13], bits[14], bits[15], bits[16]);
if (count > 256)
ERREXIT(cinfo->emethods, "Bogus DHT counts");
for (i = 0; i < count; i++)
huffval[i] = (UINT8) JGETC(cinfo);
length -= 1 + 16 + count;
if (index & 0x10) { /* AC table definition */
index -= 0x10;
htblptr = &cinfo->ac_huff_tbl_ptrs[index];
} else { /* DC table definition */
htblptr = &cinfo->dc_huff_tbl_ptrs[index];
}
if (index < 0 || index >= NUM_HUFF_TBLS)
ERREXIT1(cinfo->emethods, "Bogus DHT index %ld", index);
if (*htblptr == NULL)
*htblptr = (HUFF_TBL *) (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval));
}
}
LOCAL void
get_dac (decompress_info_ptr cinfo)
/* Process a DAC marker */
{
INT32 length;
int index, val;
length = get_2bytes(cinfo)-2;
while (length > 0) {
index = JGETC(cinfo);
val = JGETC(cinfo);
TRACEMS2(cinfo->emethods, 1,
"Define Arithmetic Table 0x%02x: 0x%02x", index, val);
if (index < 0 || index >= (2*NUM_ARITH_TBLS))
ERREXIT1(cinfo->emethods, "Bogus DAC index %ld", index);
if (index >= NUM_ARITH_TBLS) { /* define AC table */
cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
} else { /* define DC table */
cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
ERREXIT1(cinfo->emethods, "Bogus DAC value 0x%x", val);
}
length -= 2;
}
}
LOCAL void
get_dqt (decompress_info_ptr cinfo)
/* Process a DQT marker */
{
INT32 length;
int n, i, prec;
UINT16 tmp;
QUANT_TBL_PTR quant_ptr;
length = get_2bytes(cinfo) - 2;
while (length > 0) {
n = JGETC(cinfo);
prec = n >> 4;
n &= 0x0F;
TRACEMS2(cinfo->emethods, 1,
"Define Quantization Table %ld precision %ld", n, prec);
if (n >= NUM_QUANT_TBLS)
ERREXIT1(cinfo->emethods, "Bogus table number %ld", n);
if (cinfo->quant_tbl_ptrs[n] == NULL)
cinfo->quant_tbl_ptrs[n] = (QUANT_TBL_PTR)
(*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
quant_ptr = cinfo->quant_tbl_ptrs[n];
for (i = 0; i < DCTSIZE2; i++) {
tmp = JGETC(cinfo);
if (prec)
tmp = (tmp<<8) + JGETC(cinfo);
quant_ptr[i] = tmp;
}
for (i = 0; i < DCTSIZE2; i += 8) {
TRACEMS8(cinfo->emethods, 2, " %4ld %4ld %4ld %4ld %4ld %4ld %4ld %4ld",
quant_ptr[i ], quant_ptr[i+1], quant_ptr[i+2], quant_ptr[i+3],
quant_ptr[i+4], quant_ptr[i+5], quant_ptr[i+6], quant_ptr[i+7]);
}
length -= DCTSIZE2+1;
if (prec) length -= DCTSIZE2;
}
}
LOCAL void
get_dri (decompress_info_ptr cinfo)
/* Process a DRI marker */
{
if (get_2bytes(cinfo) != 4)
ERREXIT(cinfo->emethods, "Bogus length in DRI");
cinfo->restart_interval = (UINT16) get_2bytes(cinfo);
TRACEMS1(cinfo->emethods, 1,
"Define Restart Interval %ld", cinfo->restart_interval);
}
LOCAL void
get_app0 (decompress_info_ptr cinfo)
/* Process an APP0 marker */
{
#define JFIF_LEN 14
INT32 length;
UINT8 b[JFIF_LEN];
int buffp;
length = get_2bytes(cinfo) - 2;
/* See if a JFIF APP0 marker is present */
if (length >= JFIF_LEN) {
for (buff