📄 jrdjfif.c
字号:
/*
* 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"); */
send_command(ERR13);
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 %u", 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, " %3d %3d %3d %3d %3d %3d %3d %3d",
bits[1], bits[2], bits[3], bits[4],
bits[5], bits[6], bits[7], bits[8]); */
/* TRACEMS8(cinfo->emethods, 2, " %3d %3d %3d %3d %3d %3d %3d %3d",
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"); */
send_command(ERR12);
receive_command();
exit();
}
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 %d", index); */
send_command(ERR12);
receive_command();
exit();
}
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 %d", index); */
send_command(ERR12);
receive_command();
exit();
}
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); */
send_command(ERR12);
receive_command();
exit();
}
}
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 %d precision %d", n, prec); */
if (n >= NUM_QUANT_TBLS)
{
/* ERREXIT1(cinfo->emethods, "Bogus table number %d", n); */
send_command(ERR12);
receive_command();
exit();
}
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, " %4u %4u %4u %4u %4u %4u %4u %4u",
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"); */
send_command(ERR12);
receive_command();
exit();
}
cinfo->restart_interval = (UINT16) get_2bytes(cinfo);
/* TRACEMS1(cinfo->emethods, 1,
"Define Restart Interval %u", 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 (buffp = 0; buffp < JFIF_LEN; buffp++)
b[buffp] = (UINT8) JGETC(cinfo);
length -= JFIF_LEN;
if (b[0]==0x4A && b[1]==0x46 && b[2]==0x49 && b[3]==0x46 && b[4]==0) {
/* Found JFIF APP0 marker: check version */
/* Major version must be 1 */
if (b[5] != 1)
{
/* ERREXIT2(cinfo->emethods, "Unsupported JFIF revision number %d.%02d",
b[5], b[6]); */
send_command(ERR12);
receive_command();
exit();
}
/* Minor version should be 0..2, but try to process anyway if newer */
/* if (b[6] > 2)
TRACEMS2(cinfo->emethods, 1, "Warning: unknown JFIF revision number %d.%02d",
b[5], b[6]); */
/* Save info */
cinfo->density_unit = b[7];
cinfo->X_density = (b[8] << 8) + b[9];
cinfo->Y_density = (b[10] << 8) + b[11];
/* Assume colorspace is YCbCr, unless UI has overridden me */
/* if (cinfo->jpeg_color_space == CS_UNKNOWN)
cinfo->jpeg_color_space = CS_YCbCr;
TRACEMS3(cinfo->emethods, 1, "JFIF APP0 marker, density %dx%d %d",
cinfo->X_density, cinfo->Y_density, cinfo->density_unit); */
/* if (b[12] | b[13])
TRACEMS2(cinfo->emethods, 1, " with %d x %d thumbnail image",
b[12], b[13]); */
/* if (length != ((INT32) b[12] * (INT32) b[13] * (INT32) 3))
TRACEMS1(cinfo->emethods, 1,
"Warning: thumbnail image size does not match data length %u",
(int) length); */
} else {
/* TRACEMS1(cinfo->emethods, 1, "Unknown APP0 marker (not JFIF), length %u",
(int) length + JFIF_LEN); */
}
} else {
/* TRACEMS1(cinfo->emethods, 1, "Short APP0 marker, length %u", (int) length); */
}
while (length-- > 0) /* skip any remaining data */
(void) JGETC(cinfo);
}
LOCAL void
get_sof (decompress_info_ptr cinfo, int code)
/* Process a SOFn marker */
{
INT32 length;
short ci;
int c;
jpeg_component_info * compptr;
length = get_2bytes(cinfo);
cinfo->data_precision = JGETC(cinfo);
cinfo->image_height = get_2bytes(cinfo);
cinfo->image_width = get_2bytes(cinfo);
cinfo->num_components = JGETC(cinfo);
/* TRACEMS4(cinfo->emethods, 1,
"Start Of Frame 0x%02x: width=%u, height=%u, components=%d",
code, (int) cinfo->image_width, (int) cinfo->image_height,
cinfo->num_components); */
/* We don't support files in which the image height is initially specified */
/* as 0 and is later redefined by DNL. As long as we have to check that, */
/* might as well have a general sanity check. */
if (cinfo->image_height <= 0 || cinfo->image_width <= 0
|| cinfo->num_components <= 0)
{
/* ERREXIT(cinfo->emethods, "Empty JPEG image (DNL not supported)"); */
send_command(ERR12);
receive_command();
exit();
}
#ifdef EIGHT_BIT_SAMPLES
if (cinfo->data_precision != 8)
{
/* ERREXIT(cinfo->emethods, "Unsupported JPEG data precision"); */
send_command(ERR12);
receive_command();
exit();
}
#endif
#ifdef TWELVE_BIT_SAMPLES
if (cinfo->data_precision != 12) /* this needs more thought?? */
{
/* ERREXIT(cinfo->emethods, "Unsupported JPEG data precision"); */
send_command(ERR12);
receive_command();
exit();
}
#endif
#ifdef SIXTEEN_BIT_SAMPLES
if (cinfo->data_precision != 16) /* this needs more thought?? */
{
/* ERREXIT(cinfo->emethods, "Unsupported JPEG data precision"); */
send_command(ERR12);
receive_command();
exit();
}
#endif
if (length != (cinfo->num_components * 3 + 8))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -