/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.shavenpuppy.jglib.jpeg;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteOrder;
import com.shavenpuppy.jglib.Image;
public class JPEGDecoder {
static final int DCTSIZE = 8;
static final int DCTSIZE2 = 64;
static final int NUM_QUANT_TBLS = 4;
static final int NUM_HUFF_TBLS = 4;
static final int NUM_ARITH_TBLS = 16;
static final int MAX_COMPS_IN_SCAN = 4;
static final int MAX_COMPONENTS = 10;
static final int MAX_SAMP_FACTOR = 4;
static final int D_MAX_BLOCKS_IN_MCU = 10;
static final int HUFF_LOOKAHEAD = 8;
static final int MAX_Q_COMPS = 4;
static final int IFAST_SCALE_BITS = 2;
static final int MAXJSAMPLE = 255;
static final int CENTERJSAMPLE = 128;
static final int MIN_GET_BITS = 32 - 7;
static final int INPUT_BUFFER_SIZE = 4096;
static final int SCALEBITS = 16; /*
* speediest right-shift on some
* machines
*/
static final int ONE_HALF = 1 << (SCALEBITS - 1);
static final int RGB_RED = 2; /* Offset of Red in an RGB scanline element */
static final int RGB_GREEN = 1; /* Offset of Green */
static final int RGB_BLUE = 0; /* Offset of Blue */
static final int RGB_PIXELSIZE = 3;
static final int JBUF_PASS_THRU = 0;
static final int JBUF_SAVE_SOURCE = 1; /*
* Run source subobject only, save
* output
*/
static final int JBUF_CRANK_DEST = 2; /*
* Run dest subobject only, using
* saved data
*/
static final int JBUF_SAVE_AND_PASS = 3;
static final int JPEG_MAX_DIMENSION = 65500;
static final int BITS_IN_JSAMPLE = 8;
static final int JDITHER_NONE = 0; /* no dithering */
static final int JDITHER_ORDERED = 1; /* simple ordered dither */
static final int JDITHER_FS = 2;
static final int JDCT_ISLOW = 0; /* slow but accurate integer algorithm */
static final int JDCT_IFAST = 1; /* faster, less accurate integer method */
static final int JDCT_FLOAT = 2; /*
* floating-point: accurate, fast on
* fast HW
*/
static final int JDCT_DEFAULT = JDCT_ISLOW;
static final int JCS_UNKNOWN = 0; /* error/unspecified */
static final int JCS_GRAYSCALE = 1; /* monochrome */
static final int JCS_RGB = 2; /* red/green/blue */
static final int JCS_YCbCr = 3; /* Y/Cb/Cr (also known as YUV) */
static final int JCS_CMYK = 4; /* C/M/Y/K */
static final int JCS_YCCK = 5; /* Y/Cb/Cr/K */
static final int SAVED_COEFS = 6;
static final int Q01_POS = 1;
static final int Q10_POS = 8;
static final int Q20_POS = 16;
static final int Q11_POS = 9;
static final int Q02_POS = 2;
static final int CTX_PREPARE_FOR_IMCU = 0; /* need to prepare for MCU row */
static final int CTX_PROCESS_IMCU = 1; /* feeding iMCU to postprocessor */
static final int CTX_POSTPONED_ROW = 2; /* feeding postponed row group */
static final int APP0_DATA_LEN = 14; /*
* Length of interesting data in
* APP0
*/
static final int APP14_DATA_LEN = 12; /*
* Length of interesting data in
* APP14
*/
static final int APPN_DATA_LEN = 14; /*
* Must be the largest of the
* above!!
*/
/* markers */
static final int M_SOF0 = 0xc0;
static final int M_SOF1 = 0xc1;
static final int M_SOF2 = 0xc2;
static final int M_SOF3 = 0xc3;
static final int M_SOF5 = 0xc5;
static final int M_SOF6 = 0xc6;
static final int M_SOF7 = 0xc7;
static final int M_JPG = 0xc8;
static final int M_SOF9 = 0xc9;
static final int M_SOF10 = 0xca;
static final int M_SOF11 = 0xcb;
static final int M_SOF13 = 0xcd;
static final int M_SOF14 = 0xce;
static final int M_SOF15 = 0xcf;
static final int M_DHT = 0xc4;
static final int M_DAC = 0xcc;
static final int M_RST0 = 0xd0;
static final int M_RST1 = 0xd1;
static final int M_RST2 = 0xd2;
static final int M_RST3 = 0xd3;
static final int M_RST4 = 0xd4;
static final int M_RST5 = 0xd5;
static final int M_RST6 = 0xd6;
static final int M_RST7 = 0xd7;
static final int M_SOI = 0xd8;
static final int M_EOI = 0xd9;
static final int M_SOS = 0xda;
static final int M_DQT = 0xdb;
static final int M_DNL = 0xdc;
static final int M_DRI = 0xdd;
static final int M_DHP = 0xde;
static final int M_EXP = 0xdf;
static final int M_APP0 = 0xe0;
static final int M_APP1 = 0xe1;
static final int M_APP2 = 0xe2;
static final int M_APP3 = 0xe3;
static final int M_APP4 = 0xe4;
static final int M_APP5 = 0xe5;
static final int M_APP6 = 0xe6;
static final int M_APP7 = 0xe7;
static final int M_APP8 = 0xe8;
static final int M_APP9 = 0xe9;
static final int M_APP10 = 0xea;
static final int M_APP11 = 0xeb;
static final int M_APP12 = 0xec;
static final int M_APP13 = 0xed;
static final int M_APP14 = 0xee;
static final int M_APP15 = 0xef;
static final int M_JPG0 = 0xf0;
static final int M_JPG13 = 0xfd;
static final int M_COM = 0xfe;
static final int M_TEM = 0x01;
static final int M_ERROR = 0x100;
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
static final int CSTATE_START = 100; /* after create_compress */
static final int CSTATE_SCANNING = 101; /*
* start_compress done,
* write_scanlines OK
*/
static final int CSTATE_RAW_OK = 102; /*
* start_compress done,
* write_raw_data OK
*/
static final int CSTATE_WRCOEFS = 103; /* jpeg_write_coefficients done */
static final int DSTATE_START = 200; /* after create_decompress */
static final int DSTATE_INHEADER = 201; /*
* reading header markers, no SOS
* yet
*/
static final int DSTATE_READY = 202; /*
* found SOS, ready for
* start_decompress
*/
static final int DSTATE_PRELOAD = 203; /*
* reading multiscan file in
* start_decompress
*/
static final int DSTATE_PRESCAN = 204; /*
* performing dummy pass for 2-pass
* quant
*/
static final int DSTATE_SCANNING = 205; /*
* start_decompress done,
* read_scanlines OK
*/
static final int DSTATE_RAW_OK = 206; /*
* start_decompress done,
* read_raw_data OK
*/
static final int DSTATE_BUFIMAGE = 207; /* expecting jpeg_start_output */
static final int DSTATE_BUFPOST = 208; /*
* looking for SOS/EOI in
* jpeg_finish_output
*/
static final int DSTATE_RDCOEFS = 209; /*
* reading file in
* jpeg_read_coefficients
*/
static final int DSTATE_STOPPING = 210; /*
* looking for EOI in
* jpeg_finish_decompress
*/
static final int JPEG_REACHED_SOS = 1; /* Reached start of new scan */
static final int JPEG_REACHED_EOI = 2; /* Reached end of image */
static final int JPEG_ROW_COMPLETED = 3; /* Completed one iMCU row */
static final int JPEG_SCAN_COMPLETED = 4; /*
* Completed last iMCU row of a
* scan
*/
static final int JPEG_SUSPENDED = 0; /*
* Suspended due to lack of input
* data
*/
static final int JPEG_HEADER_OK = 1; /* Found valid image datastream */
static final int JPEG_HEADER_TABLES_ONLY = 2; /*
* Found valid
* table-specs-only
* datastream
*/
/* Function pointers */
static final int DECOMPRESS_DATA = 0;
static final int DECOMPRESS_SMOOTH_DATA = 1;
static final int DECOMPRESS_ONEPASS = 2;
static final int CONSUME_DATA = 0;
static final int DUMMY_CONSUME_DATA = 1;
static final int PROCESS_DATA_SIMPLE_MAIN = 0;
static final int PROCESS_DATA_CONTEXT_MAIN = 1;
static final int PROCESS_DATA_CRANK_POST = 2;
static final int POST_PROCESS_1PASS = 0;
static final int POST_PROCESS_DATA_UPSAMPLE = 1;
static final int NULL_CONVERT = 0;
static final int GRAYSCALE_CONVERT = 1;
static final int YCC_RGB_CONVERT = 2;
static final int GRAY_RGB_CONVERT = 3;
static final int YCCK_CMYK_CONVERT = 4;
static final int NOOP_UPSAMPLE = 0;
static final int FULLSIZE_UPSAMPLE = 1;
static final int H2V1_FANCY_UPSAMPLE = 2;
static final int H2V1_UPSAMPLE = 3;
static final int H2V2_FANCY_UPSAMPLE = 4;
static final int H2V2_UPSAMPLE = 5;
static final int INT_UPSAMPLE = 6;
static final int INPUT_CONSUME_INPUT = 0;
static final int COEF_CONSUME_INPUT = 1;
static int extend_test[] = /* entry n is 2**(n-1) */
{ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
static int extend_offset[] = /* entry n is (-1 << n) + 1 */
{ 0, ((-1) << 1) + 1, ((-1) << 2) + 1, ((-1) << 3) + 1, ((-1) << 4) + 1,
((-1) << 5) + 1, ((-1) << 6) + 1, ((-1) << 7) + 1, ((-1) << 8) + 1,
((-1) << 9) + 1, ((-1) << 10) + 1, ((-1) << 11) + 1,
((-1) << 12) + 1, ((-1) << 13) + 1, ((-1) << 14) + 1,
((-1) << 15) + 1 };
static int jpeg_natural_order[] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32,
25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7,
14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37,
44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62,
63, 63, 63, 63, 63, 63, 63, 63, 63, /*
* extra entries for safety in
* decoder
*/
63, 63, 63, 63, 63, 63, 63, 63 };
static final class JQUANT_TBL {
/*
* This array gives the coefficient quantizers in natural array order
* (not the zigzag order in which they are stored in a JPEG DQT marker).
* CAUTION: IJG versions prior to v6a kept this array in zigzag order.
*/
short[] quantval = new short[DCTSIZE2]; /*
* quantization step for each
* coefficient
*/
/*
* This field is used only during compression. It's initialized false
* when the table is created, and set true when it's been output to the
* file. You could suppress output of a table by setting this to true.
* (See jpeg_suppress_tables for an example.)
*/
boolean sent_table; /* true when table has been output */
}
static final class JHUFF_TBL {
/* These two fields directly represent the contents of a JPEG DHT marker */
byte[] bits = new byte[17]; /* bits[k] = # of symbols with codes of */
/* length k bits; bits[0] is unused */
byte[] huffval = new byte[256]; /*
* The symbols, in order of incr code
* length
*/
/*
* This field is used only during compression. It's initialized false
* when the table is created, and set true when it's been output to the
* file. You could suppress output of a table by setting this to true.
* (See jpeg_suppress_tables for an example.)
*/
boolean sent_table; /* true when table has been output */
}
static final class bitread_perm_state { /*
* Bitreading state saved across
* MCUs
*/
int get_buffer; /* current bit-extraction buffer */
int bits_left; /* # of unused bits in it */
}
static final class bitread_working_state { /*
* Bitreading working state
* within an MCU
*/
/* Current data source location */
/*
* We need a copy, rather than munging the original, in case of
* suspension
*/
byte[] buffer; /* => next byte to read from source */
int bytes_offset;
int bytes_in_buffer; /* # of bytes remaining in source buffer */
/*
* Bit input buffer --- note these values are kept in register
* variables, not in this struct, inside the inner loops.
*/
int get_buffer; /* current bit-extraction buffer */
int bits_left; /* # of unused bits in it */
/* Pointer needed by jpeg_fill_bit_buffer. */
jpeg_decompress_struct cinfo; /* back link to decompress master record */
}
static final class savable_state {
int EOBRUN; // Note that this is only used in the progressive case
int[] last_dc_val = new int[MAX_COMPS_IN_SCAN]; /*
* last DC coef for each
* component
*/
}
static final class d_derived_tbl {
/* Basic tables: (element [0] of each array is unused) */
int[] maxcode = new int[18]; /* largest code of length k (-1 if none) */
/* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
int[] valoffset = new int[17]; /*
* huffval[] offset for codes of length
* k
*/
/*
* valoffset[k] = huffval[] index of 1st symbol of code length k, less
* the smallest code of length k; so given a code of length k, the
* corresponding symbol is huffval[code + valoffset[k]]
*/
/* Link to public Huffman table (needed only in jpeg_huff_decode) */
JHUFF_TBL pub;
/*
* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of the
* input data stream. If the next Huffman code is no more than
* HUFF_LOOKAHEAD bits long, we can obtain its length and the
* corresponding symbol directly from these tables.
*/
int[] look_nbits = new int[1 << HUFF_LOOKAHEAD]; /*
* # bits, or 0 if
* too long
*/
byte[] look_sym = new byte[1 << HUFF_LOOKAHEAD]; /* symbol, or unused */
}
static final class jpeg_d_coef_controller {
int consume_data;
int decompress_data;
/* Pointer to array of coefficient virtual arrays, or null if none */
short[][][] coef_arrays;
/* These variables keep track of the current location of the input side. */
/* cinfo.input_iMCU_row is also used for this. */
int MCU_ctr; /* counts MCUs processed in current row */
int MCU_vert_offset; /* counts MCU rows within iMCU row */
int MCU_rows_per_iMCU_row; /* number of such rows needed */
/* The output side's location is represented by cinfo.output_iMCU_row. */
/*
* In single-pass modes, it's sufficient to buffer just one MCU. We
* allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, and
* let the entropy decoder write into that workspace each time. (On
* 80x86, the workspace is FAR even though it's not really very big;
* this is to keep the module interfaces unchanged when a large
* coefficient buffer is necessary.) In multi-pass modes, this array
* points to the current MCU's blocks within the virtual arrays; it is
* used only by the input side.
*/
short[][] MCU_buffer = new short[D_MAX_BLOCKS_IN_MCU][];
/*
* In multi-pass modes, we need a virtual block array for each
* component.
*/
short[][][][] whole_image = new short[MAX_COMPONENTS][][][];
/* When doing block smoothing, we latch coefficient Al values here */
int[] coef_bits_latch;
short[] workspace;
void start_input_pass(jpeg_decompress_struct cinfo) {
cinfo.input_iMCU_row = 0;
start_iMCU_row(cinfo);
}
/* Reset within-iMCU-row counters for a new row (input side) */
void start_iMCU_row(jpeg_decompress_struct cinfo) {
jpeg_d_coef_controller coef = cinfo.coef;
/*
* In an interleaved scan, an MCU row is the same as an iMCU row. In
* a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
* But at the bottom of the image, process only what's left.
*/
if (cinfo.comps_in_scan > 1) {
coef.MCU_rows_per_iMCU_row = 1;
} else {
if (cinfo.input_iMCU_row < (cinfo.total_iMCU_rows - 1)) {
coef.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].v_samp_factor;
} else {
coef.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].last_row_height;
}
}
coef.MCU_ctr = 0;
coef.MCU_vert_offset = 0;
}
}
static abstract class jpeg_entropy_decoder {
abstract void start_pass(jpeg_decompress_struct cinfo);
abstract boolean decode_mcu(jpeg_decompress_struct cinfo,
short[][] MCU_data);
/* This is here to share code between baseline and progressive decoders; */
/* other modules probably should not use it */
boolean insufficient_data; /* set true after emitting warning */
bitread_working_state br_state_local = new bitread_working_state();
savable_state state_local = new savable_state();
}
static final class huff_entropy_decoder extends jpeg_entropy_decoder {
bitread_perm_state bitstate = new bitread_perm_state(); /*
* Bit buffer at
* start of MCU
*/
savable_state saved = new savable_state(); /*
* Other state at start of
* MCU
*/
/* These fields are NOT loaded into local working state. */
int restarts_to_go; /* MCUs left in this restart interval */
/* Pointers to derived tables (these workspaces have image lifespan) */
d_derived_tbl[] dc_derived_tbls = new d_derived_tbl[NUM_HUFF_TBLS];
d_derived_tbl[] ac_derived_tbls = new d_derived_tbl[NUM_HUFF_TBLS];
/* Precalculated info set up by start_pass for use in decode_mcu: */
/* Pointers to derived tables to be used for each block within an MCU */
d_derived_tbl[] dc_cur_tbls = new d_derived_tbl[D_MAX_BLOCKS_IN_MCU];
d_derived_tbl[] ac_cur_tbls = new d_derived_tbl[D_MAX_BLOCKS_IN_MCU];
/* Whether we care about the DC and AC coefficient values for each block */
boolean[] dc_needed = new boolean[D_MAX_BLOCKS_IN_MCU];
boolean[] ac_needed = new boolean[D_MAX_BLOCKS_IN_MCU];
@Override
void start_pass(jpeg_decompress_struct cinfo) {
start_pass_huff_decoder(cinfo);
}
@Override
boolean decode_mcu(jpeg_decompress_struct cinfo, short[][] MCU_data) {
huff_entropy_decoder entropy = this;
int blkn;
// BITREAD_STATE_VARS;
int get_buffer;
int bits_left;
// bitread_working_state br_state = new bitread_working_state();
// savable_state state = new savable_state();
bitread_working_state br_state = br_state_local;
savable_state state = state_local;
/* Process restart marker if needed; may have to suspend */
if (cinfo.restart_interval != 0) {
if (entropy.restarts_to_go == 0) {
if (!process_restart(cinfo)) {
return false;
}
}
}
/*
* If we've run out of data, just leave the MCU set to zeroes. This
* way, we return uniform gray for the remainder of the segment.
*/
if (!entropy.insufficient_data) {
/* Load up working state */
// BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
br_state.cinfo = cinfo;
br_state.buffer = cinfo.buffer;
br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
br_state.bytes_offset = cinfo.bytes_offset;
get_buffer = entropy.bitstate.get_buffer;
bits_left = entropy.bitstate.bits_left;
// ASSIGN_STATE(state, entropy.saved);
state.last_dc_val[0] = entropy.saved.last_dc_val[0];
state.last_dc_val[1] = entropy.saved.last_dc_val[1];
state.last_dc_val[2] = entropy.saved.last_dc_val[2];
state.last_dc_val[3] = entropy.saved.last_dc_val[3];
/* Outer loop handles each block in the MCU */
for (blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) {
short[] block = MCU_data[blkn];
d_derived_tbl dctbl = entropy.dc_cur_tbls[blkn];
d_derived_tbl actbl = entropy.ac_cur_tbls[blkn];
int s = 0, k, r;
/* Decode a single block's worth of coefficients */
/* Section F.2.2.1: decode the DC coefficient difference */
// HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
{
int nb = 0, look;
if (bits_left < HUFF_LOOKAHEAD) {
if (!jpeg_fill_bit_buffer(br_state, get_buffer,
bits_left, 0)) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
if (bits_left < HUFF_LOOKAHEAD) {
nb = 1;
// goto slowlabel;
if ((s = jpeg_huff_decode(br_state, get_buffer,
bits_left, dctbl, nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
// look = PEEK_BITS(HUFF_LOOKAHEAD);
if (nb != 1) {
look = (((get_buffer >> (bits_left - (HUFF_LOOKAHEAD)))) & ((1 << (HUFF_LOOKAHEAD)) - 1));
if ((nb = dctbl.look_nbits[look]) != 0) {
// DROP_BITS(nb);
bits_left -= nb;
s = dctbl.look_sym[look] & 0xFF;
} else {
nb = HUFF_LOOKAHEAD + 1;
// slowlabel:
if ((s = jpeg_huff_decode(br_state, get_buffer,
bits_left, dctbl, nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
}
if (s != 0) {
// CHECK_BIT_BUFFER(br_state, s, return FALSE);
{
if (bits_left < (s)) {
if (!jpeg_fill_bit_buffer(br_state, get_buffer,
bits_left, s)) {
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// r = GET_BITS(s);
r = (((get_buffer >> (bits_left -= (s)))) & ((1 << (s)) - 1));
// s = HUFF_EXTEND(r, s);
s = ((r) < extend_test[s] ? (r) + extend_offset[s]
: (r));
}
if (entropy.dc_needed[blkn]) {
/*
* Convert DC difference to actual value, update
* last_dc_val
*/
int ci = cinfo.MCU_membership[blkn];
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
/*
* Output the DC coefficient (assumes
* jpeg_natural_order[0] = 0)
*/
block[0] = (short) s;
}
if (entropy.ac_needed[blkn]) {
/* Section F.2.2.2: decode the AC coefficients */
/*
* Since zeroes are skipped, output area must be cleared
* beforehand
*/
for (k = 1; k < DCTSIZE2; k++) {
// HUFF_DECODE(s, br_state, actbl, return FALSE,
// label2);
{
int nb = 0, look;
if (bits_left < HUFF_LOOKAHEAD) {
if (!jpeg_fill_bit_buffer(br_state,
get_buffer, bits_left, 0)) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
if (bits_left < HUFF_LOOKAHEAD) {
nb = 1;
// goto slowlabel;
if ((s = jpeg_huff_decode(br_state,
get_buffer, bits_left, actbl,
nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
if (nb != 1) {
// look = PEEK_BITS(HUFF_LOOKAHEAD);
look = (((get_buffer >> (bits_left - (HUFF_LOOKAHEAD)))) & ((1 << (HUFF_LOOKAHEAD)) - 1));
if ((nb = actbl.look_nbits[look]) != 0) {
// DROP_BITS(nb);
bits_left -= (nb);
s = actbl.look_sym[look] & 0xFF;
} else {
nb = HUFF_LOOKAHEAD + 1;
// slowlabel:
if ((s = jpeg_huff_decode(br_state,
get_buffer, bits_left, actbl,
nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
}
r = s >> 4;
s &= 15;
if (s != 0) {
k += r;
// CHECK_BIT_BUFFER(br_state, s, return FALSE);
{
if (bits_left < (s)) {
if (!jpeg_fill_bit_buffer(br_state,
get_buffer, bits_left, s)) {
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// r = GET_BITS(s);
r = (((get_buffer >> (bits_left -= (s)))) & ((1 << (s)) - 1));
// s = HUFF_EXTEND(r, s);
s = ((r) < extend_test[s] ? (r)
+ extend_offset[s] : (r));
/*
* Output coefficient in natural (dezigzagged)
* order. Note: the extra entries in
* jpeg_natural_order[] will save us if k >=
* DCTSIZE2, which could happen if the data is
* corrupted.
*/
block[jpeg_natural_order[k]] = (short) s;
} else {
if (r != 15) {
break;
}
k += 15;
}
}
} else {
/* Section F.2.2.2: decode the AC coefficients */
/* In this path we just discard the values */
for (k = 1; k < DCTSIZE2; k++) {
// HUFF_DECODE(s, br_state, actbl, return FALSE,
// label3);
{
int nb = 0, look;
if (bits_left < HUFF_LOOKAHEAD) {
if (!jpeg_fill_bit_buffer(br_state,
get_buffer, bits_left, 0)) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
if (bits_left < HUFF_LOOKAHEAD) {
nb = 1;
// goto slowlabel;
if ((s = jpeg_huff_decode(br_state,
get_buffer, bits_left, actbl,
nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
if (nb != 1) {
// look = PEEK_BITS(HUFF_LOOKAHEAD);
look = (((get_buffer >> (bits_left - (HUFF_LOOKAHEAD)))) & ((1 << (HUFF_LOOKAHEAD)) - 1));
if ((nb = actbl.look_nbits[look]) != 0) {
// DROP_BITS(nb);
bits_left -= (nb);
s = actbl.look_sym[look] & 0xFF;
} else {
nb = HUFF_LOOKAHEAD + 1;
// slowlabel:
if ((s = jpeg_huff_decode(br_state,
get_buffer, bits_left, actbl,
nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
}
r = s >> 4;
s &= 15;
if (s != 0) {
k += r;
// CHECK_BIT_BUFFER(br_state, s, return FALSE);
{
if (bits_left < (s)) {
if (!jpeg_fill_bit_buffer((br_state),
get_buffer, bits_left, s)) {
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// DROP_BITS(s);
bits_left -= s;
} else {
if (r != 15) {
break;
}
k += 15;
}
}
}
}
/* Completed MCU, so update state */
// BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
cinfo.buffer = br_state.buffer;
cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
cinfo.bytes_offset = br_state.bytes_offset;
entropy.bitstate.get_buffer = get_buffer;
entropy.bitstate.bits_left = bits_left;
// ASSIGN_STATE(entropy.saved, state);
entropy.saved.last_dc_val[0] = state.last_dc_val[0];
entropy.saved.last_dc_val[1] = state.last_dc_val[1];
entropy.saved.last_dc_val[2] = state.last_dc_val[2];
entropy.saved.last_dc_val[3] = state.last_dc_val[3];
}
/* Account for restart interval (no-op if not using restarts) */
entropy.restarts_to_go--;
return true;
}
void start_pass_huff_decoder(jpeg_decompress_struct cinfo) {
huff_entropy_decoder entropy = this;
int ci, blkn, dctbl, actbl;
jpeg_component_info compptr;
/*
* Check that the scan parameters Ss, Se, Ah/Al are OK for
* sequential JPEG. This ought to be an error condition, but we make
* it a warning because there are some baseline files out there with
* all zeroes in these bytes.
*/
if (cinfo.Ss != 0 || cinfo.Se != DCTSIZE2 - 1 || cinfo.Ah != 0
|| cinfo.Al != 0) {
// WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
}
for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
compptr = cinfo.cur_comp_info[ci];
dctbl = compptr.dc_tbl_no;
actbl = compptr.ac_tbl_no;
/* Compute derived values for Huffman tables */
/*
* We may do this more than once for a table, but it's not
* expensive
*/
jpeg_make_d_derived_tbl(cinfo, true, dctbl,
entropy.dc_derived_tbls[dctbl] = new d_derived_tbl());
jpeg_make_d_derived_tbl(cinfo, false, actbl,
entropy.ac_derived_tbls[actbl] = new d_derived_tbl());
/* Initialize DC predictions to 0 */
entropy.saved.last_dc_val[ci] = 0;
}
/* Precalculate decoding info for each block in an MCU of this scan */
for (blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) {
ci = cinfo.MCU_membership[blkn];
compptr = cinfo.cur_comp_info[ci];
/* Precalculate which table to use for each block */
entropy.dc_cur_tbls[blkn] = entropy.dc_derived_tbls[compptr.dc_tbl_no];
entropy.ac_cur_tbls[blkn] = entropy.ac_derived_tbls[compptr.ac_tbl_no];
/* Decide whether we really care about the coefficient values */
if (compptr.component_needed) {
entropy.dc_needed[blkn] = true;
/* we don't need the ACs if producing a 1/8th-size image */
entropy.ac_needed[blkn] = (compptr.DCT_scaled_size > 1);
} else {
entropy.dc_needed[blkn] = entropy.ac_needed[blkn] = false;
}
}
/* Initialize bitread state variables */
entropy.bitstate.bits_left = 0;
entropy.bitstate.get_buffer = 0; /*
* unnecessary, but keeps Purify
* quiet
*/
entropy.insufficient_data = false;
/* Initialize restart counter */
entropy.restarts_to_go = cinfo.restart_interval;
}
boolean process_restart(jpeg_decompress_struct cinfo) {
huff_entropy_decoder entropy = this;
int ci;
/* Throw away any unused bits remaining in bit buffer; */
/* include any full bytes in next_marker's count of discarded bytes */
cinfo.marker.discarded_bytes += entropy.bitstate.bits_left / 8;
entropy.bitstate.bits_left = 0;
/* Advance past the RSTn marker */
if (!read_restart_marker(cinfo)) {
return false;
}
/* Re-initialize DC predictions to 0 */
for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
entropy.saved.last_dc_val[ci] = 0;
}
/* Reset restart counter */
entropy.restarts_to_go = cinfo.restart_interval;
/*
* Reset out-of-data flag, unless read_restart_marker left us smack
* up against a marker. In that case we will end up treating the
* next data segment as empty, and we can avoid producing bogus
* output pixels by leaving the flag set.
*/
if (cinfo.unread_marker == 0) {
entropy.insufficient_data = false;
}
return true;
}
}
static final class phuff_entropy_decoder extends jpeg_entropy_decoder {
/*
* These fields are loaded into local variables at start of each MCU. In
* case of suspension, we exit WITHOUT updating them.
*/
bitread_perm_state bitstate = new bitread_perm_state(); /*
* Bit buffer at
* start of MCU
*/
savable_state saved = new savable_state(); /*
* Other state at start of
* MCU
*/
/* These fields are NOT loaded into local working state. */
int restarts_to_go; /* MCUs left in this restart interval */
/* Pointers to derived tables (these workspaces have image lifespan) */
d_derived_tbl[] derived_tbls = new d_derived_tbl[NUM_HUFF_TBLS];
d_derived_tbl ac_derived_tbl; /* active table during an AC scan */
int[] newnz_pos = new int[DCTSIZE2];
@Override
void start_pass(jpeg_decompress_struct cinfo) {
start_pass_phuff_decoder(cinfo);
}
@Override
boolean decode_mcu(jpeg_decompress_struct cinfo, short[][] MCU_data) {
boolean is_DC_band = (cinfo.Ss == 0);
if (cinfo.Ah == 0) {
if (is_DC_band) {
return decode_mcu_DC_first(cinfo, MCU_data);
} else {
return decode_mcu_AC_first(cinfo, MCU_data);
}
} else {
if (is_DC_band) {
return decode_mcu_DC_refine(cinfo, MCU_data);
} else {
return decode_mcu_AC_refine(cinfo, MCU_data);
}
}
}
boolean decode_mcu_DC_refine(jpeg_decompress_struct cinfo,
short[][] MCU_data) {
phuff_entropy_decoder entropy = this;
int p1 = 1 << cinfo.Al; /* 1 in the bit position being coded */
int blkn;
short[] block;
// BITREAD_STATE_VARS;
int get_buffer;
int bits_left;
// bitread_working_state br_state = new bitread_working_state();
bitread_working_state br_state = br_state_local;
/* Process restart marker if needed; may have to suspend */
if (cinfo.restart_interval != 0) {
if (entropy.restarts_to_go == 0) {
if (!process_restart(cinfo)) {
return false;
}
}
}
/*
* Not worth the cycles to check insufficient_data here, since we
* will not change the data anyway if we read zeroes.
*/
/* Load up working state */
// BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
br_state.cinfo = cinfo;
br_state.buffer = cinfo.buffer;
br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
br_state.bytes_offset = cinfo.bytes_offset;
get_buffer = entropy.bitstate.get_buffer;
bits_left = entropy.bitstate.bits_left;
/* Outer loop handles each block in the MCU */
for (blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) {
block = MCU_data[blkn];
/*
* Encoded data is simply the next bit of the two's-complement
* DC value
*/
// CHECK_BIT_BUFFER(br_state, 1, return FALSE);
{
if (bits_left < (1)) {
if (!jpeg_fill_bit_buffer(br_state, get_buffer,
bits_left, 1)) {
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// if (GET_BITS(1))
if ((((get_buffer >> (bits_left -= (1)))) & ((1 << (1)) - 1)) != 0) {
block[0] |= p1;
/* Note: since we use |=, repeating the assignment later is safe */
}
}
/* Completed MCU, so update state */
// BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
cinfo.buffer = br_state.buffer;
cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
cinfo.bytes_offset = br_state.bytes_offset;
entropy.bitstate.get_buffer = get_buffer;
entropy.bitstate.bits_left = bits_left;
/* Account for restart interval (no-op if not using restarts) */
entropy.restarts_to_go--;
return true;
}
boolean decode_mcu_AC_refine(jpeg_decompress_struct cinfo,
short[][] MCU_data) {
phuff_entropy_decoder entropy = this;
int Se = cinfo.Se;
int p1 = 1 << cinfo.Al; /* 1 in the bit position being coded */
int m1 = (-1) << cinfo.Al; /* -1 in the bit position being coded */
int s = 0, k, r;
int EOBRUN;
short[] block;
short[] thiscoef;
// BITREAD_STATE_VARS;
int get_buffer;
int bits_left;
// bitread_working_state br_state = new bitread_working_state();
bitread_working_state br_state = br_state_local;
d_derived_tbl tbl;
int num_newnz;
int[] newnz_pos = entropy.newnz_pos;
/* Process restart marker if needed; may have to suspend */
if (cinfo.restart_interval != 0) {
if (entropy.restarts_to_go == 0) {
if (!process_restart(cinfo)) {
return false;
}
}
}
/*
* If we've run out of data, don't modify the MCU.
*/
if (!entropy.insufficient_data) {
/* Load up working state */
// BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
br_state.cinfo = cinfo;
br_state.buffer = cinfo.buffer;
br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
br_state.bytes_offset = cinfo.bytes_offset;
get_buffer = entropy.bitstate.get_buffer;
bits_left = entropy.bitstate.bits_left;
EOBRUN = entropy.saved.EOBRUN; /*
* only part of saved state we
* need
*/
/* There is always only one block per MCU */
block = MCU_data[0];
tbl = entropy.ac_derived_tbl;
/*
* If we are forced to suspend, we must undo the assignments to
* any newly nonzero coefficients in the block, because
* otherwise we'd get confused next time about which
* coefficients were already nonzero. But we need not undo
* addition of bits to already-nonzero coefficients; instead, we
* can test the current bit to see if we already did it.
*/
num_newnz = 0;
/* initialize coefficient loop counter to start of band */
k = cinfo.Ss;
if (EOBRUN == 0) {
for (; k <= Se; k++) {
// HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
{
int nb = 0, look;
if (bits_left < HUFF_LOOKAHEAD) {
if (!jpeg_fill_bit_buffer(br_state, get_buffer,
bits_left, 0)) {
// failaction;
while (num_newnz > 0) {
block[newnz_pos[--num_newnz]] = 0;
}
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
if (bits_left < HUFF_LOOKAHEAD) {
nb = 1;
// goto slowlabel;
if ((s = jpeg_huff_decode(br_state,
get_buffer, bits_left, tbl, nb)) < 0) {
// failaction;
while (num_newnz > 0) {
block[newnz_pos[--num_newnz]] = 0;
}
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
if (nb != 1) {
// look = PEEK_BITS(HUFF_LOOKAHEAD);
look = (((get_buffer >> (bits_left - (HUFF_LOOKAHEAD)))) & ((1 << (HUFF_LOOKAHEAD)) - 1));
if ((nb = tbl.look_nbits[look]) != 0) {
// DROP_BITS(nb);
bits_left -= nb;
s = tbl.look_sym[look] & 0xFF;
} else {
nb = HUFF_LOOKAHEAD + 1;
// slowlabel:
if ((s = jpeg_huff_decode(br_state,
get_buffer, bits_left, tbl, nb)) < 0) {
// failaction;
while (num_newnz > 0) {
block[newnz_pos[--num_newnz]] = 0;
}
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
}
r = s >> 4;
s &= 15;
if (s != 0) {
if (s != 1) { /*
* size of new coef should always be
* 1
*/
// WARNMS(cinfo, JWRN_HUFF_BAD_CODE);
}
// CHECK_BIT_BUFFER(br_state, 1, goto undoit);
{
if (bits_left < (1)) {
if (!jpeg_fill_bit_buffer(br_state,
get_buffer, bits_left, 1)) {
// failaction;
while (num_newnz > 0) {
block[newnz_pos[--num_newnz]] = 0;
}
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// if (GET_BITS(1))
if ((((get_buffer >> (bits_left -= (1)))) & ((1 << (1)) - 1)) != 0) {
s = p1; /* newly nonzero coef is positive */
} else {
s = m1; /* newly nonzero coef is negative */
}
} else {
if (r != 15) {
EOBRUN = 1 << r; /*
* EOBr, run length is 2^r +
* appended bits
*/
if (r != 0) {
// CHECK_BIT_BUFFER(br_state, r, goto
// undoit);
{
if (bits_left < (r)) {
if (!jpeg_fill_bit_buffer(br_state,
get_buffer, bits_left, r)) {
// failaction;
while (num_newnz > 0) {
block[newnz_pos[--num_newnz]] = 0;
}
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// r = GET_BITS(r);
r = (((get_buffer >> (bits_left -= (r)))) & ((1 << (r)) - 1));
EOBRUN += r;
}
break; /* rest of block is handled by EOB logic */
}
/* note s = 0 for processing ZRL */
}
/*
* Advance over already-nonzero coefs and r still-zero
* coefs, appending correction bits to the nonzeroes. A
* correction bit is 1 if the absolute value of the
* coefficient must be increased.
*/
do {
thiscoef = block;
int thiscoef_offset = jpeg_natural_order[k];
if (thiscoef[thiscoef_offset] != 0) {
// CHECK_BIT_BUFFER(br_state, 1, goto undoit);
{
if (bits_left < (1)) {
if (!jpeg_fill_bit_buffer(br_state,
get_buffer, bits_left, 1)) {
// failaction;
while (num_newnz > 0) {
block[newnz_pos[--num_newnz]] = 0;
}
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// if (GET_BITS(1)) {
if ((((get_buffer >> (bits_left -= (1)))) & ((1 << (1)) - 1)) != 0) {
if ((thiscoef[thiscoef_offset] & p1) == 0) { /*
* do
* nothing
* if
* already
* set
* it
*/
if (thiscoef[thiscoef_offset] >= 0) {
thiscoef[thiscoef_offset] += p1;
} else {
thiscoef[thiscoef_offset] += m1;
}
}
}
} else {
if (--r < 0) {
break; /* reached target zero coefficient */
}
}
k++;
} while (k <= Se);
if (s != 0) {
int pos = jpeg_natural_order[k];
/* Output newly nonzero coefficient */
block[pos] = (short) s;
/* Remember its position in case we have to suspend */
newnz_pos[num_newnz++] = pos;
}
}
}
if (EOBRUN > 0) {
/*
* Scan any remaining coefficient positions after the
* end-of-band (the last newly nonzero coefficient, if any).
* Append a correction bit to each already-nonzero
* coefficient. A correction bit is 1 if the absolute value
* of the coefficient must be increased.
*/
for (; k <= Se; k++) {
thiscoef = block;
int thiscoef_offset = jpeg_natural_order[k];
if (thiscoef[thiscoef_offset] != 0) {
// CHECK_BIT_BUFFER(br_state, 1, goto undoit);
{
if (bits_left < (1)) {
if (!jpeg_fill_bit_buffer(br_state,
get_buffer, bits_left, 1)) {
// failaction;
while (num_newnz > 0) {
block[newnz_pos[--num_newnz]] = 0;
}
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// if (GET_BITS(1)) {
if ((((get_buffer >> (bits_left -= (1)))) & ((1 << (1)) - 1)) != 0) {
if ((thiscoef[thiscoef_offset] & p1) == 0) { /*
* do
* nothing
* if
* already
* changed
* it
*/
if (thiscoef[thiscoef_offset] >= 0) {
thiscoef[thiscoef_offset] += p1;
} else {
thiscoef[thiscoef_offset] += m1;
}
}
}
}
}
/* Count one block completed in EOB run */
EOBRUN--;
}
/* Completed MCU, so update state */
// BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
cinfo.buffer = br_state.buffer;
cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
cinfo.bytes_offset = br_state.bytes_offset;
entropy.bitstate.get_buffer = get_buffer;
entropy.bitstate.bits_left = bits_left;
entropy.saved.EOBRUN = EOBRUN; /*
* only part of saved state we
* need
*/
}
/* Account for restart interval (no-op if not using restarts) */
entropy.restarts_to_go--;
return true;
// undoit:
// /* Re-zero any output coefficients that we made newly nonzero */
// while (num_newnz > 0)
// (*block)[newnz_pos[--num_newnz]] = 0;
//
// return false;
}
boolean decode_mcu_AC_first(jpeg_decompress_struct cinfo,
short[][] MCU_data) {
phuff_entropy_decoder entropy = this;
int Se = cinfo.Se;
int Al = cinfo.Al;
int s = 0, k, r;
int EOBRUN;
short[] block;
// BITREAD_STATE_VARS;
int get_buffer;
int bits_left;
// bitread_working_state br_state = new bitread_working_state();
bitread_working_state br_state = br_state_local;
d_derived_tbl tbl;
/* Process restart marker if needed; may have to suspend */
if (cinfo.restart_interval != 0) {
if (entropy.restarts_to_go == 0) {
if (!process_restart(cinfo)) {
return false;
}
}
}
/*
* If we've run out of data, just leave the MCU set to zeroes. This
* way, we return uniform gray for the remainder of the segment.
*/
if (!entropy.insufficient_data) {
/*
* Load up working state. We can avoid loading/saving bitread
* state if in an EOB run.
*/
EOBRUN = entropy.saved.EOBRUN; /*
* only part of saved state we
* need
*/
/* There is always only one block per MCU */
if (EOBRUN > 0) {
EOBRUN--; /* ...process it now (we do nothing) */
} else {
// BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
br_state.cinfo = cinfo;
br_state.buffer = cinfo.buffer;
br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
br_state.bytes_offset = cinfo.bytes_offset;
get_buffer = entropy.bitstate.get_buffer;
bits_left = entropy.bitstate.bits_left;
block = MCU_data[0];
tbl = entropy.ac_derived_tbl;
for (k = cinfo.Ss; k <= Se; k++) {
// HUFF_DECODE(s, br_state, tbl, return FALSE, label2);
{
int nb = 0, look;
if (bits_left < HUFF_LOOKAHEAD) {
if (!jpeg_fill_bit_buffer(br_state, get_buffer,
bits_left, 0)) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
if (bits_left < HUFF_LOOKAHEAD) {
nb = 1;
// goto slowlabel;
if ((s = jpeg_huff_decode(br_state,
get_buffer, bits_left, tbl, nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
if (nb != 1) {
// look = PEEK_BITS(HUFF_LOOKAHEAD);
look = (((get_buffer >> (bits_left - (HUFF_LOOKAHEAD)))) & ((1 << (HUFF_LOOKAHEAD)) - 1));
if ((nb = tbl.look_nbits[look]) != 0) {
// DROP_BITS(nb);
bits_left -= nb;
s = tbl.look_sym[look] & 0xFF;
} else {
nb = HUFF_LOOKAHEAD + 1;
// slowlabel:
if ((s = jpeg_huff_decode(br_state,
get_buffer, bits_left, tbl, nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
}
r = s >> 4;
s &= 15;
if (s != 0) {
k += r;
// CHECK_BIT_BUFFER(br_state, s, return FALSE);
{
if (bits_left < (s)) {
if (!jpeg_fill_bit_buffer(br_state,
get_buffer, bits_left, s)) {
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// r = GET_BITS(s);
r = (((get_buffer >> (bits_left -= (s)))) & ((1 << (s)) - 1));
// s = HUFF_EXTEND(r, s);
s = ((r) < extend_test[s] ? (r) + extend_offset[s]
: (r));
/*
* Scale and output coefficient in natural
* (dezigzagged) order
*/
block[jpeg_natural_order[k]] = (short) (s << Al);
} else {
if (r == 15) { /* ZRL */
k += 15; /* skip 15 zeroes in band */
} else { /*
* EOBr, run length is 2^r + appended
* bits
*/
EOBRUN = 1 << r;
if (r != 0) { /* EOBr, r > 0 */
// CHECK_BIT_BUFFER(br_state, r, return
// FALSE);
{
if (bits_left < (r)) {
if (!jpeg_fill_bit_buffer(br_state,
get_buffer, bits_left, r)) {
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// r = GET_BITS(r);
r = (((get_buffer >> (bits_left -= (r)))) & ((1 << (r)) - 1));
EOBRUN += r;
}
EOBRUN--; /*
* this band is processed at this
* moment
*/
break; /* force end-of-band */
}
}
}
// BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
cinfo.buffer = br_state.buffer;
cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
cinfo.bytes_offset = br_state.bytes_offset;
entropy.bitstate.get_buffer = get_buffer;
entropy.bitstate.bits_left = bits_left;
}
/* Completed MCU, so update state */
entropy.saved.EOBRUN = EOBRUN; /*
* only part of saved state we
* need
*/
}
/* Account for restart interval (no-op if not using restarts) */
entropy.restarts_to_go--;
return true;
}
boolean decode_mcu_DC_first(jpeg_decompress_struct cinfo,
short[][] MCU_data) {
phuff_entropy_decoder entropy = this;
int Al = cinfo.Al;
int s = 0, r;
int blkn, ci;
short[] block;
// BITREAD_STATE_VARS;
int get_buffer;
int bits_left;
// bitread_working_state br_state = new bitread_working_state();
bitread_working_state br_state = br_state_local;
// savable_state state = new savable_state();
savable_state state = state_local;
d_derived_tbl tbl;
jpeg_component_info compptr;
/* Process restart marker if needed; may have to suspend */
if (cinfo.restart_interval != 0) {
if (entropy.restarts_to_go == 0) {
if (!process_restart(cinfo)) {
return false;
}
}
}
/*
* If we've run out of data, just leave the MCU set to zeroes. This
* way, we return uniform gray for the remainder of the segment.
*/
if (!entropy.insufficient_data) {
/* Load up working state */
// BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
br_state.cinfo = cinfo;
br_state.buffer = cinfo.buffer;
br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
br_state.bytes_offset = cinfo.bytes_offset;
get_buffer = entropy.bitstate.get_buffer;
bits_left = entropy.bitstate.bits_left;
// ASSIGN_STATE(state, entropy.saved);
state.EOBRUN = entropy.saved.EOBRUN;
state.last_dc_val[0] = entropy.saved.last_dc_val[0];
state.last_dc_val[1] = entropy.saved.last_dc_val[1];
state.last_dc_val[2] = entropy.saved.last_dc_val[2];
state.last_dc_val[3] = entropy.saved.last_dc_val[3];
/* Outer loop handles each block in the MCU */
for (blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) {
block = MCU_data[blkn];
ci = cinfo.MCU_membership[blkn];
compptr = cinfo.cur_comp_info[ci];
tbl = entropy.derived_tbls[compptr.dc_tbl_no];
/* Decode a single block's worth of coefficients */
/* Section F.2.2.1: decode the DC coefficient difference */
// HUFF_DECODE(s, br_state, tbl, return FALSE, label1);
{
int nb = 0, look;
if (bits_left < HUFF_LOOKAHEAD) {
if (!jpeg_fill_bit_buffer(br_state, get_buffer,
bits_left, 0)) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
if (bits_left < HUFF_LOOKAHEAD) {
nb = 1;
// goto slowlabel;
if ((s = jpeg_huff_decode(br_state, get_buffer,
bits_left, tbl, nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
if (nb != 1) {
// look = PEEK_BITS(HUFF_LOOKAHEAD);
look = (((get_buffer >> (bits_left - (HUFF_LOOKAHEAD)))) & ((1 << (HUFF_LOOKAHEAD)) - 1));
if ((nb = tbl.look_nbits[look]) != 0) {
// DROP_BITS(nb);
bits_left -= nb;
s = tbl.look_sym[look] & 0xFF;
} else {
nb = HUFF_LOOKAHEAD + 1;
// slowlabel:
if ((s = jpeg_huff_decode(br_state, get_buffer,
bits_left, tbl, nb)) < 0) {
return false;
}
get_buffer = br_state.get_buffer;
bits_left = br_state.bits_left;
}
}
}
if (s != 0) {
// CHECK_BIT_BUFFER(br_state, s, return FALSE);
{
if (bits_left < (s)) {
if (!jpeg_fill_bit_buffer(br_state, get_buffer,
bits_left, s)) {
return false;
}
get_buffer = (br_state).get_buffer;
bits_left = (br_state).bits_left;
}
}
// r = GET_BITS(s);
r = (((get_buffer >> (bits_left -= (s)))) & ((1 << (s)) - 1));
// s = HUFF_EXTEND(r, s);
s = ((r) < extend_test[s] ? (r) + extend_offset[s]
: (r));
}
/* Convert DC difference to actual value, update last_dc_val */
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
/*
* Scale and output the coefficient (assumes
* jpeg_natural_order[0]=0)
*/
block[0] = (short) (s << Al);
}
/* Completed MCU, so update state */
// BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
cinfo.buffer = br_state.buffer;
cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
cinfo.bytes_offset = br_state.bytes_offset;
entropy.bitstate.get_buffer = get_buffer;
entropy.bitstate.bits_left = bits_left;
// ASSIGN_STATE(entropy.saved, state);
entropy.saved.EOBRUN = state.EOBRUN;
entropy.saved.last_dc_val[0] = state.last_dc_val[0];
entropy.saved.last_dc_val[1] = state.last_dc_val[1];
entropy.saved.last_dc_val[2] = state.last_dc_val[2];
entropy.saved.last_dc_val[3] = state.last_dc_val[3];
}
/* Account for restart interval (no-op if not using restarts) */
entropy.restarts_to_go--;
return true;
}
boolean process_restart(jpeg_decompress_struct cinfo) {
phuff_entropy_decoder entropy = this;
int ci;
/* Throw away any unused bits remaining in bit buffer; */
/* include any full bytes in next_marker's count of discarded bytes */
cinfo.marker.discarded_bytes += entropy.bitstate.bits_left / 8;
entropy.bitstate.bits_left = 0;
/* Advance past the RSTn marker */
if (!read_restart_marker(cinfo)) {
return false;
}
/* Re-initialize DC predictions to 0 */
for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
entropy.saved.last_dc_val[ci] = 0;
}
/* Re-init EOB run count, too */
entropy.saved.EOBRUN = 0;
/* Reset restart counter */
entropy.restarts_to_go = cinfo.restart_interval;
/*
* Reset out-of-data flag, unless read_restart_marker left us smack
* up against a marker. In that case we will end up treating the
* next data segment as empty, and we can avoid producing bogus
* output pixels by leaving the flag set.
*/
if (cinfo.unread_marker == 0) {
entropy.insufficient_data = false;
}
return true;
}
void start_pass_phuff_decoder(jpeg_decompress_struct cinfo) {
phuff_entropy_decoder entropy = this;
boolean is_DC_band, bad;
int ci, coefi, tbl;
int[] coef_bit_ptr;
jpeg_component_info compptr;
is_DC_band = (cinfo.Ss == 0);
/* Validate scan parameters */
bad = false;
if (is_DC_band) {
if (cinfo.Se != 0) {
bad = true;
}
} else {
/* need not check Ss/Se < 0 since they came from unsigned bytes */
if (cinfo.Ss > cinfo.Se || cinfo.Se >= DCTSIZE2) {
bad = true;
}
/* AC scans may have only one component */
if (cinfo.comps_in_scan != 1) {
bad = true;
}
}
if (cinfo.Ah != 0) {
/*
* Successive approximation refinement scan: must have Al =
* Ah-1.
*/
if (cinfo.Al != cinfo.Ah - 1) {
bad = true;
}
}
if (cinfo.Al > 13) {
bad = true;
}
/*
* Arguably the maximum Al value should be less than 13 for 8-bit
* precision, but the spec doesn't say so, and we try to be liberal
* about what we accept. Note: large Al values could result in
* out-of-range DC coefficients during early scans, leading to
* bizarre displays due to overflows in the IDCT math. But we won't
* crash.
*/
if (bad) {
error();
}
// ERREXIT4(cinfo, JERR_BAD_PROGRESSION, cinfo.Ss, cinfo.Se,
// cinfo.Ah, cinfo.Al);
/*
* Update progression status, and verify that scan order is legal.
* Note that inter-scan inconsistencies are treated as warnings not
* fatal errors ... not clear if this is right way to behave.
*/
for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
int cindex = cinfo.cur_comp_info[ci].component_index;
coef_bit_ptr = cinfo.coef_bits[cindex];
if (!is_DC_band && coef_bit_ptr[0] < 0) {/*
* AC without prior
* DC scan
*/
// WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
}
for (coefi = cinfo.Ss; coefi <= cinfo.Se; coefi++) {
int expected = (coef_bit_ptr[coefi] < 0) ? 0
: coef_bit_ptr[coefi];
if (cinfo.Ah != expected) {
// WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex,
// coefi);
}
coef_bit_ptr[coefi] = cinfo.Al;
}
}
/* Select MCU decoding routine */
// if (cinfo.Ah == 0) {
// if (is_DC_band)
// entropy.pub.decode_mcu = decode_mcu_DC_first;
// else
// entropy.pub.decode_mcu = decode_mcu_AC_first;
// } else {
// if (is_DC_band)
// entropy.pub.decode_mcu = decode_mcu_DC_refine;
// else
// entropy.pub.decode_mcu = decode_mcu_AC_refine;
// }
for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
compptr = cinfo.cur_comp_info[ci];
/*
* Make sure requested tables are present, and compute derived
* tables. We may build same derived table more than once, but
* it's not expensive.
*/
if (is_DC_band) {
if (cinfo.Ah == 0) { /* DC refinement needs no table */
tbl = compptr.dc_tbl_no;
jpeg_make_d_derived_tbl(cinfo, true, tbl,
entropy.derived_tbls[tbl] = new d_derived_tbl());
}
} else {
tbl = compptr.ac_tbl_no;
jpeg_make_d_derived_tbl(cinfo, false, tbl,
entropy.derived_tbls[tbl] = new d_derived_tbl());
/* remember the single active table */
entropy.ac_derived_tbl = entropy.derived_tbls[tbl];
}
/* Initialize DC predictions to 0 */
entropy.saved.last_dc_val[ci] = 0;
}
/* Initialize bitread state variables */
entropy.bitstate.bits_left = 0;
entropy.bitstate.get_buffer = 0; /*
* unnecessary, but keeps Purify
* quiet
*/
entropy.insufficient_data = false;
/* Initialize private state variables */
entropy.saved.EOBRUN = 0;
/* Initialize restart counter */
entropy.restarts_to_go = cinfo.restart_interval;
}
}
static final class jpeg_component_info {
/* These values are fixed over the whole image. */
/* For compression, they must be supplied by parameter setup; */
/* for decompression, they are read from the SOF marker. */
int component_id; /* identifier for this component (0..255) */
int component_index; /* its index in SOF or cinfo.comp_info[] */
int h_samp_factor; /* horizontal sampling factor (1..4) */
int v_samp_factor; /* vertical sampling factor (1..4) */
int quant_tbl_no; /* quantization table selector (0..3) */
/* These values may vary between scans. */
/* For compression, they must be supplied by parameter setup; */
/* for decompression, they are read from the SOS marker. */
/* The decompressor output side may not use these variables. */
int dc_tbl_no; /* DC entropy table selector (0..3) */
int ac_tbl_no; /* AC entropy table selector (0..3) */
/* Remaining fields should be treated as private by applications. */
/*
* These values are computed during compression or decompression
* startup:
*/
/*
* Component's size in DCT blocks. Any dummy blocks added to complete an
* MCU are not counted; therefore these values do not depend on whether
* a scan is interleaved or not.
*/
int width_in_blocks;
int height_in_blocks;
/*
* Size of a DCT block in samples. Always DCTSIZE for compression. For
* decompression this is the size of the output from one DCT block,
* reflecting any scaling we choose to apply during the IDCT step.
* Values of 1,2,4,8 are likely to be supported. Note that different
* components may receive different IDCT scalings.
*/
int DCT_scaled_size;
/*
* The downsampled dimensions are the component's actual, unpadded
* number of samples at the main buffer (preprocessing/compression
* interface), thus downsampled_width = ceil(image_width * Hi/Hmax) and
* similarly for height. For decompression, IDCT scaling is included, so
* downsampled_width = ceil(image_width * Hi/Hmax *
* DCT_scaled_size/DCTSIZE)
*/
int downsampled_width; /* actual width in samples */
int downsampled_height; /* actual height in samples */
/*
* This flag is used only for decompression. In cases where some of the
* components will be ignored (eg grayscale output from YCbCr image), we
* can skip most computations for the unused components.
*/
boolean component_needed; /* do we need the value of this component? */
/* These values are computed before starting a scan of the component. */
/* The decompressor output side may not use these variables. */
int MCU_width; /* number of blocks per MCU, horizontally */
int MCU_height; /* number of blocks per MCU, vertically */
int MCU_blocks; /* MCU_width * MCU_height */
int MCU_sample_width; /*
* MCU width in samples,
* MCU_width*DCT_scaled_size
*/
int last_col_width; /* # of non-dummy blocks across in last MCU */
int last_row_height; /* # of non-dummy blocks down in last MCU */
/*
* Saved quantization table for component; null if none yet saved. See
* jdinput.c comments about the need for this information. This field is
* currently used only for decompression.
*/
JQUANT_TBL quant_table;
/* Private per-component storage for DCT or IDCT subsystem. */
int[] dct_table;
}
static final class jpeg_color_quantizer {
// JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean
// is_pre_scan));
// JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
// JSAMPARRAY input_buf, JSAMPARRAY output_buf,
// int num_rows));
// JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
// JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
/* Initially allocated colormap is saved here */
int[][] sv_colormap; /* The color map as a 2-D pixel array */
int sv_actual; /* number of entries in use */
int[][] colorindex; /* Precomputed mapping for speed */
/*
* colorindex[i][j] = index of color closest to pixel value j in
* component i, premultiplied as described above. Since colormap indexes
* must fit into JSAMPLEs, the entries of this array will too.
*/
boolean is_padded; /* is the colorindex padded for odither? */
int[] Ncolors = new int[MAX_Q_COMPS]; /*
* # of values alloced to each
* component
*/
/* Variables for ordered dithering */
int row_index; /* cur row's vertical index in dither matrix */
// ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per
// component */
/* Variables for Floyd-Steinberg dithering */
// FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
boolean on_odd_row;
void start_pass(jpeg_decompress_struct cinfo, boolean is_pre_scan) {
error();
}
}
static final class jpeg_upsampler {
// JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
// JMETHOD(void, upsample, (j_decompress_ptr cinfo,
// JSAMPIMAGE input_buf,
// JDIMENSION *in_row_group_ctr,
// JDIMENSION in_row_groups_avail,
// JSAMPARRAY output_buf,
// JDIMENSION *out_row_ctr,
// JDIMENSION out_rows_avail));
boolean need_context_rows; /* TRUE if need rows above & below */
/*
* Color conversion buffer. When using separate upsampling and color
* conversion steps, this buffer holds one upsampled row group until it
* has been color converted and output. Note: we do not allocate any
* storage for component(s) which are full-size, ie do not need
* rescaling. The corresponding entry of color_buf[] is simply set to
* point to the input data array, thereby avoiding copying.
*/
byte[][][] color_buf = new byte[MAX_COMPONENTS][][];
int[] color_buf_offset = new int[MAX_COMPONENTS];
/* Per-component upsampling method pointers */
int[] methods = new int[MAX_COMPONENTS];
int next_row_out; /* counts rows emitted from color_buf */
int rows_to_go; /* counts rows remaining in image */
/* Height of an input row group for each component. */
int[] rowgroup_height = new int[MAX_COMPONENTS];
/*
* These arrays save pixel expansion factors so that int_expand need not
* recompute them each time. They are unused for other upsampling
* methods.
*/
byte[] h_expand = new byte[MAX_COMPONENTS];
byte[] v_expand = new byte[MAX_COMPONENTS];
void start_pass(jpeg_decompress_struct cinfo) {
jpeg_upsampler upsample = cinfo.upsample;
/* Mark the conversion buffer empty */
upsample.next_row_out = cinfo.max_v_samp_factor;
/* Initialize total-height counter for detecting bottom of image */
upsample.rows_to_go = cinfo.output_height;
}
}
static final class jpeg_marker_reader {
/* Read a restart marker --- exported for use by entropy decoder only */
// jpeg_marker_parser_method read_restart_marker;
/*
* State of marker reader --- nominally internal, but applications
* supplying COM or APPn handlers might like to know the state.
*/
boolean saw_SOI; /* found SOI? */
boolean saw_SOF; /* found SOF? */
int next_restart_num; /* next restart number expected (0-7) */
int discarded_bytes; /* # of bytes skipped looking for a marker */
/* Application-overridable marker processing methods */
// jpeg_marker_parser_method process_COM;
// jpeg_marker_parser_method process_APPn[16];
/* Limit on marker data length to save for each marker type */
int length_limit_COM;
int[] length_limit_APPn = new int[16];
/* Status of COM/APPn marker saving */
// jpeg_marker_reader cur_marker; /* null if not processing a marker */
// int bytes_read; /* data bytes read so far in marker */
/* Note: cur_marker is not linked into marker_list until it's all read. */
}
static final class jpeg_d_main_controller {
// JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE
// pass_mode));
int process_data;
/* Pointer to allocated workspace (M or M+2 row groups). */
byte[][][] buffer = new byte[MAX_COMPONENTS][][];
int[] buffer_offset = new int[MAX_COMPONENTS];
boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
int[] rowgroup_ctr = new int[1]; /*
* counts row groups output to
* postprocessor
*/
/* Remaining fields are only used in the context case. */
/* These are the master pointers to the funny-order pointer lists. */
byte[][][][] xbuffer = new byte[2][][][]; /*
* pointers to weird pointer
* lists
*/
int[][] xbuffer_offset = new int[2][];
int whichptr; /* indicates which pointer set is now in use */
int context_state; /* process_data state machine status */
int rowgroups_avail; /* row groups available to postprocessor */
int iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
void start_pass(jpeg_decompress_struct cinfo, int pass_mode) {
jpeg_d_main_controller main = cinfo.main;
switch (pass_mode) {
case JBUF_PASS_THRU:
if (cinfo.upsample.need_context_rows) {
main.process_data = PROCESS_DATA_CONTEXT_MAIN;
make_funny_pointers(cinfo); /*
* Create the xbuffer[]
* lists
*/
main.whichptr = 0; /*
* Read first iMCU row into
* xbuffer[0]
*/
main.context_state = CTX_PREPARE_FOR_IMCU;
main.iMCU_row_ctr = 0;
} else {
/* Simple case with no context needed */
main.process_data = PROCESS_DATA_SIMPLE_MAIN;
}
main.buffer_full = false; /* Mark buffer empty */
main.rowgroup_ctr[0] = 0;
break;
// #ifdef QUANT_2PASS_SUPPORTED
// case JBUF_CRANK_DEST:
// /* For last pass of 2-pass quantization, just crank the
// postprocessor */
// main.process_data = PROCESS_DATA_CRANK_POST;
// break;
// #endif
default:
error();
// ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
}
}
static final class jpeg_decomp_master {
// JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
// JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
/* State variables made visible to other modules */
boolean is_dummy_pass;
int pass_number; /* # of passes completed */
boolean using_merged_upsample; /*
* true if using merged
* upsample/cconvert
*/
/*
* Saved references to initialized quantizer modules, in case we need to
* switch modes.
*/
jpeg_color_quantizer quantizer_1pass;
jpeg_color_quantizer quantizer_2pass;
}
static final class jpeg_inverse_dct {
// JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
// /* It is useful to allow each component to have a separate IDCT
// method. */
// inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
int[] cur_method = new int[MAX_COMPONENTS];
void start_pass(jpeg_decompress_struct cinfo) {
jpeg_inverse_dct idct = cinfo.idct;
int ci, i;
jpeg_component_info compptr;
int method = 0;
// inverse_DCT_method_ptr method_ptr = NULL;
JQUANT_TBL qtbl;
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
/* Select the proper IDCT routine for this component's scaling */
switch (compptr.DCT_scaled_size) {
// #ifdef IDCT_SCALING_SUPPORTED
// case 1:
// method_ptr = jpeg_idct_1x1;
// method = JDCT_ISLOW; /* jidctred uses islow-style table
// */
// break;
// case 2:
// method_ptr = jpeg_idct_2x2;
// method = JDCT_ISLOW; /* jidctred uses islow-style table
// */
// break;
// case 4:
// method_ptr = jpeg_idct_4x4;
// method = JDCT_ISLOW; /* jidctred uses islow-style table
// */
// break;
// #endif
case DCTSIZE:
switch (cinfo.dct_method) {
// #ifdef DCT_ISLOW_SUPPORTED
case JDCT_ISLOW:
// method_ptr = jpeg_idct_islow;
method = JDCT_ISLOW;
break;
// #endif
// #ifdef DCT_IFAST_SUPPORTED
// case JDCT_IFAST:
// method_ptr = jpeg_idct_ifast;
// method = JDCT_IFAST;
// break;
// #endif
// #ifdef DCT_FLOAT_SUPPORTED
// case JDCT_FLOAT:
// method_ptr = jpeg_idct_float;
// method = JDCT_FLOAT;
// break;
// #endif
default:
error();
// ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
break;
default:
error();
// ERREXIT1(cinfo, JERR_BAD_DCTSIZE,
// compptr.DCT_scaled_size);
break;
}
// idct.inverse_DCT[ci] = method_ptr;
/*
* Create multiplier table from quant table. However, we can
* skip this if the component is uninteresting or if we already
* built the table. Also, if no quant table has yet been saved
* for the component, we leave the multiplier table all-zero;
* we'll be reading zeroes from the coefficient controller's
* buffer anyway.
*/
if (!compptr.component_needed || idct.cur_method[ci] == method) {
continue;
}
qtbl = compptr.quant_table;
if (qtbl == null) {
continue;
}
idct.cur_method[ci] = method;
switch (method) {
// #ifdef PROVIDE_ISLOW_TABLES
case JDCT_ISLOW: {
/*
* For LL&M IDCT method, multipliers are equal to raw
* quantization coefficients, but are stored as ints to
* ensure access efficiency.
*/
int[] ismtbl = compptr.dct_table;
for (i = 0; i < DCTSIZE2; i++) {
ismtbl[i] = qtbl.quantval[i];
}
}
break;
// #endif
// #ifdef DCT_IFAST_SUPPORTED
// case JDCT_IFAST:
// {
// /* For AA&N IDCT method, multipliers are equal to
// quantization
// * coefficients scaled by
// scalefactor[row]*scalefactor[col], where
// * scalefactor[0] = 1
// * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
// * For integer operation, the multiplier table is to be
// scaled by
// * IFAST_SCALE_BITS.
// */
// int[] ifmtbl = compptr.dct_table;
// short aanscales[] = {
// /* precomputed values scaled up by 14 bits */
// 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
// 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
// 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
// 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
// 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
// 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
// 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
// 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
// };
// SHIFT_TEMPS
//
// for (i = 0; i < DCTSIZE2; i++) {
// ifmtbl[i] = DESCALE(MULTIPLY16V16( qtbl.quantval[i],
// aanscales[i]), CONST_BITS-IFAST_SCALE_BITS);
// }
// }
// break;
// #endif
// #ifdef DCT_FLOAT_SUPPORTED
// case JDCT_FLOAT:
// {
// /* For float AA&N IDCT method, multipliers are equal to
// quantization
// * coefficients scaled by
// scalefactor[row]*scalefactor[col], where
// * scalefactor[0] = 1
// * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
// */
// FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *)
// compptr.dct_table;
// int row, col;
// static const double aanscalefactor[DCTSIZE] = {
// 1.0, 1.387039845, 1.306562965, 1.175875602,
// 1.0, 0.785694958, 0.541196100, 0.275899379
// };
//
// i = 0;
// for (row = 0; row < DCTSIZE; row++) {
// for (col = 0; col < DCTSIZE; col++) {
// fmtbl[i] = (FLOAT_MULT_TYPE)
// ((double) qtbl.quantval[i] *
// aanscalefactor[row] * aanscalefactor[col]);
// i++;
// }
// }
// }
// break;
// #endif
default:
error();
// ERREXIT(cinfo, JERR_NOT_COMPILED);
break;
}
}
}
}
static final class jpeg_input_controller {
int consume_input;
boolean has_multiple_scans; /* True if file has multiple scans */
boolean eoi_reached;
boolean inheaders; /* true until first SOS is reached */
}
static final class jpeg_color_deconverter {
// JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
int color_convert;
/* Private state for YCC.RGB conversion */
int[] Cr_r_tab; /* => table for Cr to R conversion */
int[] Cb_b_tab; /* => table for Cb to B conversion */
int[] Cr_g_tab; /* => table for Cr to G conversion */
int[] Cb_g_tab; /* => table for Cb to G conversion */
void start_pass(jpeg_decompress_struct cinfo) {
/* no work needed */
}
}
static final class jpeg_d_post_controller {
// JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE
// pass_mode));
int post_process_data;
/*
* Color quantization source buffer: this holds output data from the
* upsample/color conversion step to be passed to the quantizer. For
* two-pass color quantization, we need a full-image buffer; for
* one-pass operation, a strip buffer is sufficient.
*/
int[] whole_image; /* virtual array, or NULL if one-pass */
int[][] buffer; /* strip buffer, or current strip of virtual */
int strip_height; /* buffer size in rows */
/* for two-pass mode only: */
int starting_row; /* row # of first row in current strip */
int next_row; /* index of next row to fill/empty in strip */
void start_pass(jpeg_decompress_struct cinfo, int pass_mode) {
jpeg_d_post_controller post = cinfo.post;
switch (pass_mode) {
case JBUF_PASS_THRU:
if (cinfo.quantize_colors) {
error(JPEGError.ERROR_NOT_IMPLEMENTED);
// /* Single-pass processing with color quantization. */
// post.post_process_data = POST_PROCESS_1PASS;
// /* We could be doing buffered-image output before
// starting a 2-pass
// * color quantization; in that case,
// jinit_d_post_controller did not
// * allocate a strip buffer. Use the virtual-array
// buffer as workspace.
// */
// if (post.buffer == null) {
// post.buffer = (*cinfo.mem.access_virt_sarray)
// ((j_common_ptr) cinfo, post.whole_image,
// (JDIMENSION) 0, post.strip_height, TRUE);
// }
} else {
/*
* For single-pass processing without color
* quantization, I have no work to do; just call the
* upsampler directly.
*/
post.post_process_data = POST_PROCESS_DATA_UPSAMPLE;
}
break;
// #ifdef QUANT_2PASS_SUPPORTED
// case JBUF_SAVE_AND_PASS:
// /* First pass of 2-pass quantization */
// if (post.whole_image == NULL)
// ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
// post.pub.post_process_data = post_process_prepass;
// break;
// case JBUF_CRANK_DEST:
// /* Second pass of 2-pass quantization */
// if (post.whole_image == NULL)
// ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
// post.pub.post_process_data = post_process_2pass;
// break;
// #endif /* QUANT_2PASS_SUPPORTED */
default:
error();
// ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
break;
}
post.starting_row = post.next_row = 0;
}
}
static final class jpeg_decompress_struct {
// jpeg_error_mgr * err; /* Error handler module */\
// struct jpeg_memory_mgr * mem; /* Memory manager module */\
// struct jpeg_progress_mgr * progress; /* Progress monitor, or null if
// none */\
// void * client_data; /* Available for use by application */\
boolean is_decompressor; /* So common code can tell which is which */
int global_state; /* For checking call sequence validity */
// /* Source of compressed data */
// struct jpeg_source_mgr * src;
InputStream inputStream;
byte[] buffer;
int bytes_in_buffer;
int bytes_offset;
boolean start_of_file;
/* Basic description of image --- filled in by jpeg_read_header(). */
/* Application may inspect these values to decide how to process image. */
int image_width; /* nominal image width (from SOF marker) */
int image_height; /* nominal image height */
int num_components; /* # of color components in JPEG image */
int jpeg_color_space; /* colorspace of JPEG image */
/*
* Decompression processing parameters --- these fields must be set
* before calling jpeg_start_decompress(). Note that jpeg_read_header()
* initializes them to default values.
*/
int out_color_space; /* colorspace for output */
int scale_num, scale_denom; /* fraction by which to scale image */
double output_gamma; /* image gamma wanted in output */
boolean buffered_image; /* true=multiple output passes */
boolean raw_data_out; /* true=downsampled data wanted */
int dct_method; /* IDCT algorithm selector */
boolean do_fancy_upsampling; /* true=apply fancy upsampling */
boolean do_block_smoothing; /* true=apply interblock smoothing */
boolean quantize_colors; /* true=colormapped output wanted */
/* the following are ignored if not quantize_colors: */
int dither_mode; /* type of color dithering to use */
boolean two_pass_quantize; /* true=use two-pass color quantization */
int desired_number_of_colors; /*
* max # colors to use in created
* colormap
*/
/* these are significant only in buffered-image mode: */
boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */
boolean enable_external_quant;/*
* enable future use of external
* colormap
*/
boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */
/*
* Description of actual output image that will be returned to
* application. These fields are computed by jpeg_start_decompress().
* You can also use jpeg_calc_output_dimensions() to determine these
* values in advance of calling jpeg_start_decompress().
*/
int output_width; /* scaled image width */
int output_height; /* scaled image height */
int out_color_components; /* # of color components in out_color_space */
int output_components; /* # of color components returned */
/*
* output_components is 1 (a colormap index) when quantizing colors;
* otherwise it equals out_color_components.
*/
int rec_outbuf_height; /* min recommended height of scanline buffer */
/*
* If the buffer passed to jpeg_read_scanlines() is less than this many
* rows high, space and time will be wasted due to unnecessary data
* copying. Usually rec_outbuf_height will be 1 or 2, at most 4.
*/
/*
* When quantizing colors, the output colormap is described by these
* fields. The application can supply a colormap by setting colormap
* non-null before calling jpeg_start_decompress; otherwise a colormap
* is created during jpeg_start_decompress or jpeg_start_output. The map
* has out_color_components rows and actual_number_of_colors columns.
*/
int actual_number_of_colors; /* number of entries in use */
int[] colormap; /* The color map as a 2-D pixel array */
/*
* State variables: these variables indicate the progress of
* decompression. The application may examine these but must not modify
* them.
*/
/*
* Row index of next scanline to be read from jpeg_read_scanlines().
* Application may use this to control its processing loop, e.g., "while
* (output_scanline < output_height)".
*/
int output_scanline; /* 0 .. output_height-1 */
/*
* Current input scan number and number of iMCU rows completed in scan.
* These indicate the progress of the decompressor input side.
*/
int input_scan_number; /* Number of SOS markers seen so far */
int input_iMCU_row; /* Number of iMCU rows completed */
/*
* The "output scan number" is the notional scan being displayed by the
* output side. The decompressor will not allow output scan/row number
* to get ahead of input scan/row, but it can fall arbitrarily far
* behind.
*/
int output_scan_number; /* Nominal scan number being displayed */
int output_iMCU_row; /* Number of iMCU rows read */
/*
* Current progression status. coef_bits[c][i] indicates the precision
* with which component c's DCT coefficient i (in zigzag order) is
* known. It is -1 when no data has yet been received, otherwise it is
* the point transform (shift) value for the most recent scan of the
* coefficient (thus, 0 at completion of the progression). This pointer
* is null when reading a non-progressive file.
*/
int[][] coef_bits; /* -1 or current Al value for each coef */
/*
* Internal JPEG parameters --- the application usually need not look at
* these fields. Note that the decompressor output side may not use any
* parameters that can change between scans.
*/
/*
* Quantization and Huffman tables are carried forward across input
* datastreams when processing abbreviated JPEG datastreams.
*/
JQUANT_TBL[] quant_tbl_ptrs = new JQUANT_TBL[NUM_QUANT_TBLS];
/* ptrs to coefficient quantization tables, or null if not defined */
JHUFF_TBL[] dc_huff_tbl_ptrs = new JHUFF_TBL[NUM_HUFF_TBLS];
JHUFF_TBL[] ac_huff_tbl_ptrs = new JHUFF_TBL[NUM_HUFF_TBLS];
/* ptrs to Huffman coding tables, or null if not defined */
/*
* These parameters are never carried across datastreams, since they are
* given in SOF/SOS markers or defined to be reset by SOI.
*/
int data_precision; /* bits of precision in image data */
jpeg_component_info[] comp_info;
/* comp_info[i] describes component that appears i'th in SOF */
boolean progressive_mode; /* true if SOFn specifies progressive mode */
boolean arith_code; /* true=arithmetic coding, false=Huffman */
byte[] arith_dc_L = new byte[NUM_ARITH_TBLS]; /*
* L values for DC
* arith-coding tables
*/
byte[] arith_dc_U = new byte[NUM_ARITH_TBLS]; /*
* U values for DC
* arith-coding tables
*/
byte[] arith_ac_K = new byte[NUM_ARITH_TBLS]; /*
* Kx values for AC
* arith-coding tables
*/
int restart_interval; /*
* MCUs per restart interval, or 0 for no
* restart
*/
/*
* These fields record data obtained from optional markers recognized by
* the JPEG library.
*/
boolean saw_JFIF_marker; /* true iff a JFIF APP0 marker was found */
/* Data copied from JFIF marker; only valid if saw_JFIF_marker is true: */
byte JFIF_major_version; /* JFIF version number */
byte JFIF_minor_version;
byte density_unit; /* JFIF code for pixel size units */
short X_density; /* Horizontal pixel density */
short Y_density; /* Vertical pixel density */
boolean saw_Adobe_marker; /* true iff an Adobe APP14 marker was found */
byte Adobe_transform; /* Color transform code from Adobe marker */
boolean CCIR601_sampling; /* true=first samples are cosited */
/*
* Aside from the specific data retained from APPn markers known to the
* library, the uninterpreted contents of any or all APPn and COM
* markers can be saved in a list for examination by the application.
*/
jpeg_marker_reader marker_list; /* Head of list of saved markers */
/*
* Remaining fields are known throughout decompressor, but generally
* should not be touched by a surrounding application.
*/
/*
* These fields are computed during decompression startup
*/
int max_h_samp_factor; /* largest h_samp_factor */
int max_v_samp_factor; /* largest v_samp_factor */
int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */
int total_iMCU_rows; /* # of iMCU rows in image */
/*
* The coefficient controller's input and output progress is measured in
* units of "iMCU" (interleaved MCU) rows. These are the same as MCU
* rows in fully interleaved JPEG scans, but are used whether the scan
* is interleaved or not. We define an iMCU row as v_samp_factor DCT
* block rows of each component. Therefore, the IDCT output contains
* v_samp_factor*DCT_scaled_size sample rows of a component per iMCU
* row.
*/
byte[] sample_range_limit; /* table for fast range-limiting */
int sample_range_limit_offset;
/*
* These fields are valid during any one scan. They describe the
* components and MCUs actually appearing in the scan. Note that the
* decompressor output side must not use these fields.
*/
int comps_in_scan; /* # of JPEG components in this scan */
jpeg_component_info[] cur_comp_info = new jpeg_component_info[MAX_COMPS_IN_SCAN];
/* *cur_comp_info[i] describes component that appears i'th in SOS */
int MCUs_per_row; /* # of MCUs across the image */
int MCU_rows_in_scan; /* # of MCU rows in the image */
int blocks_in_MCU; /* # of DCT blocks per MCU */
int[] MCU_membership = new int[D_MAX_BLOCKS_IN_MCU];
/* MCU_membership[i] is index in cur_comp_info of component owning */
/* i'th block in an MCU */
int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
/*
* This field is shared between entropy decoder and marker parser. It is
* either zero or the code of a JPEG marker that has been read from the
* data source, but has not yet been processed.
*/
int unread_marker;
int[] workspace = new int[DCTSIZE2];
int[] row_ctr = new int[1];
/*
* Links to decompression subobjects (methods, private variables of
* modules)
*/
jpeg_decomp_master master;
jpeg_d_main_controller main;
jpeg_d_coef_controller coef;
jpeg_d_post_controller post;
jpeg_input_controller inputctl;
jpeg_marker_reader marker;
jpeg_entropy_decoder entropy;
jpeg_inverse_dct idct;
jpeg_upsampler upsample;
jpeg_color_deconverter cconvert;
jpeg_color_quantizer cquantize;
}
static void error() {
JPEGError.error(JPEGError.ERROR_INVALID_IMAGE);
}
static void error(int code) {
JPEGError.error(code);
}
static void error(String msg) {
JPEGError.error(JPEGError.ERROR_INVALID_IMAGE, null, msg);
}
static void jinit_marker_reader(jpeg_decompress_struct cinfo) {
jpeg_marker_reader marker = cinfo.marker = new jpeg_marker_reader();
// int i;
/*
* Initialize COM/APPn processing. By default, we examine and then
* discard APP0 and APP14, but simply discard COM and all other APPn.
*/
// marker.process_COM = skip_variable;
marker.length_limit_COM = 0;
// for (i = 0; i < 16; i++) {
// marker.process_APPn[i] = skip_variable;
// marker.length_limit_APPn[i] = 0;
// }
// marker.process_APPn[0] = get_interesting_appn;
// marker.process_APPn[14] = get_interesting_appn;
/* Reset marker processing state */
reset_marker_reader(cinfo);
}
static void jinit_d_coef_controller(jpeg_decompress_struct cinfo,
boolean need_full_buffer) {
jpeg_d_coef_controller coef = new jpeg_d_coef_controller();
cinfo.coef = coef;
// coef.pub.start_input_pass = start_input_pass;
// coef.pub.start_output_pass = start_output_pass;
coef.coef_bits_latch = null;
/* Create the coefficient buffer. */
if (need_full_buffer) {
// #ifdef D_MULTISCAN_FILES_SUPPORTED
/* Allocate a full-image virtual array for each component, */
/* padded to a multiple of samp_factor DCT blocks in each direction. */
/* Note we ask for a pre-zeroed array. */
int ci;
jpeg_component_info compptr;
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
coef.whole_image[ci] = new short[(int) jround_up(
compptr.height_in_blocks, compptr.v_samp_factor)][(int) jround_up(
compptr.width_in_blocks, compptr.h_samp_factor)][DCTSIZE2];
}
// coef.consume_data = consume_data;
coef.decompress_data = DECOMPRESS_DATA;
coef.coef_arrays = coef.whole_image[0]; /* link to virtual arrays */
// #else
// ERREXIT(cinfo, JERR_NOT_COMPILED);
// #endif
} else {
/* We only need a single-MCU buffer. */
coef.MCU_buffer = new short[D_MAX_BLOCKS_IN_MCU][DCTSIZE2];
// coef.consume_data = dummy_consume_data;
coef.decompress_data = DECOMPRESS_ONEPASS;
coef.coef_arrays = null; /* flag for no virtual arrays */
}
}
static void start_output_pass(jpeg_decompress_struct cinfo) {
// #ifdef BLOCK_SMOOTHING_SUPPORTED
jpeg_d_coef_controller coef = cinfo.coef;
/*
* If multipass, check to see whether to use block smoothing on this
* pass
*/
if (coef.coef_arrays != null) {
if (cinfo.do_block_smoothing && smoothing_ok(cinfo)) {
coef.decompress_data = DECOMPRESS_SMOOTH_DATA;
} else {
coef.decompress_data = DECOMPRESS_DATA;
}
}
// #endif
cinfo.output_iMCU_row = 0;
}
static void jpeg_create_decompress(jpeg_decompress_struct cinfo) {
cinfo.is_decompressor = true;
/*
* Initialize marker processor so application can override methods for
* COM, APPn markers before calling jpeg_read_header.
*/
cinfo.marker_list = null;
jinit_marker_reader(cinfo);
/* And initialize the overall input controller. */
jinit_input_controller(cinfo);
/* OK, I'm ready */
cinfo.global_state = DSTATE_START;
}
static void jpeg_calc_output_dimensions(jpeg_decompress_struct cinfo)
/* Do computations that are needed before master selection phase */
{
// #ifdef IDCT_SCALING_SUPPORTED
// int ci;
// jpeg_component_info compptr;
// #endif
/* Prevent application from calling me at wrong times */
if (cinfo.global_state != DSTATE_READY)
{
error();
// ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
}
// #ifdef IDCT_SCALING_SUPPORTED
//
// /* Compute actual output image dimensions and DCT scaling choices. */
// if (cinfo.scale_num * 8 <= cinfo.scale_denom) {
// /* Provide 1/8 scaling */
// cinfo.output_width = (int)
// jdiv_round_up(cinfo.image_width, 8L);
// cinfo.output_height = (int)
// jdiv_round_up(cinfo.image_height, 8L);
// cinfo.min_DCT_scaled_size = 1;
// } else if (cinfo.scale_num * 4 <= cinfo.scale_denom) {
// /* Provide 1/4 scaling */
// cinfo.output_width = (int)
// jdiv_round_up(cinfo.image_width, 4L);
// cinfo.output_height = (int)
// jdiv_round_up(cinfo.image_height, 4L);
// cinfo.min_DCT_scaled_size = 2;
// } else if (cinfo.scale_num * 2 <= cinfo.scale_denom) {
// /* Provide 1/2 scaling */
// cinfo.output_width = (int)
// jdiv_round_up(cinfo.image_width, 2L);
// cinfo.output_height = (int)
// jdiv_round_up(cinfo.image_height, 2L);
// cinfo.min_DCT_scaled_size = 4;
// } else {
// /* Provide 1/1 scaling */
// cinfo.output_width = cinfo.image_width;
// cinfo.output_height = cinfo.image_height;
// cinfo.min_DCT_scaled_size = DCTSIZE;
// }
// /* In selecting the actual DCT scaling for each component, we try to
// * scale up the chroma components via IDCT scaling rather than
// upsampling.
// * This saves time if the upsampler gets to use 1:1 scaling.
// * Note this code assumes that the supported DCT scalings are powers
// of 2.
// */
// for (ci = 0; ci < cinfo.num_components; ci++) {
// compptr = cinfo.comp_info[ci];
// int ssize = cinfo.min_DCT_scaled_size;
// while (ssize < DCTSIZE &&
// (compptr.h_samp_factor * ssize * 2 <= cinfo.max_h_samp_factor *
// cinfo.min_DCT_scaled_size) &&
// (compptr.v_samp_factor * ssize * 2 <= cinfo.max_v_samp_factor *
// cinfo.min_DCT_scaled_size))
// {
// ssize = ssize * 2;
// }
// compptr.DCT_scaled_size = ssize;
// }
//
// /* Recompute downsampled dimensions of components;
// * application needs to know these if using raw downsampled data.
// */
// for (ci = 0; ci < cinfo.num_components; ci++) {
// compptr = cinfo.comp_info[ci];
// /* Size in samples, after IDCT scaling */
// compptr.downsampled_width = (int)
// jdiv_round_up((long) cinfo.image_width * (long)
// (compptr.h_samp_factor * compptr.DCT_scaled_size),
// (cinfo.max_h_samp_factor * DCTSIZE));
// compptr.downsampled_height = (int)
// jdiv_round_up((long) cinfo.image_height * (long)
// (compptr.v_samp_factor * compptr.DCT_scaled_size),
// (cinfo.max_v_samp_factor * DCTSIZE));
// }
//
// #else /* !IDCT_SCALING_SUPPORTED */
/* Hardwire it to "no scaling" */
cinfo.output_width = cinfo.image_width;
cinfo.output_height = cinfo.image_height;
/*
* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, and has
* computed unscaled downsampled_width and downsampled_height.
*/
// #endif /* IDCT_SCALING_SUPPORTED */
/* Report number of components in selected colorspace. */
/* Probably this should be in the color conversion module... */
switch (cinfo.out_color_space) {
case JCS_GRAYSCALE:
cinfo.out_color_components = 1;
break;
case JCS_RGB:
case JCS_YCbCr:
cinfo.out_color_components = 3;
break;
case JCS_CMYK:
case JCS_YCCK:
cinfo.out_color_components = 4;
break;
default: /* else must be same colorspace as in file */
cinfo.out_color_components = cinfo.num_components;
break;
}
cinfo.output_components = (cinfo.quantize_colors ? 1
: cinfo.out_color_components);
/* See if upsampler will want to emit more than one row at a time */
if (use_merged_upsample(cinfo)) {
cinfo.rec_outbuf_height = cinfo.max_v_samp_factor;
} else {
cinfo.rec_outbuf_height = 1;
}
}
static boolean use_merged_upsample(jpeg_decompress_struct cinfo) {
// #ifdef UPSAMPLE_MERGING_SUPPORTED
/* Merging is the equivalent of plain box-filter upsampling */
if (cinfo.do_fancy_upsampling || cinfo.CCIR601_sampling) {
return false;
}
/* jdmerge.c only supports YCC=>RGB color conversion */
if (cinfo.jpeg_color_space != JCS_YCbCr || cinfo.num_components != 3
|| cinfo.out_color_space != JCS_RGB
|| cinfo.out_color_components != RGB_PIXELSIZE) {
return false;
}
/* and it only handles 2h1v or 2h2v sampling ratios */
if (cinfo.comp_info[0].h_samp_factor != 2
|| cinfo.comp_info[1].h_samp_factor != 1
|| cinfo.comp_info[2].h_samp_factor != 1
|| cinfo.comp_info[0].v_samp_factor > 2
|| cinfo.comp_info[1].v_samp_factor != 1
|| cinfo.comp_info[2].v_samp_factor != 1) {
return false;
}
/* furthermore, it doesn't work if we've scaled the IDCTs differently */
if (cinfo.comp_info[0].DCT_scaled_size != cinfo.min_DCT_scaled_size
|| cinfo.comp_info[1].DCT_scaled_size != cinfo.min_DCT_scaled_size
|| cinfo.comp_info[2].DCT_scaled_size != cinfo.min_DCT_scaled_size) {
return false;
}
/*
* ??? also need to test for upsample-time rescaling, when & if
* supported
*/
return true; /* by golly, it'll work... */
// #else
// return false;
// #endif
}
static void prepare_range_limit_table(jpeg_decompress_struct cinfo)
/* Allocate and fill in the sample_range_limit table */
{
byte[] table;
int i;
table = new byte[5 * (MAXJSAMPLE + 1) + CENTERJSAMPLE];
int offset = (MAXJSAMPLE + 1); /*
* allow negative subscripts of simple
* table
*/
cinfo.sample_range_limit_offset = offset;
cinfo.sample_range_limit = table;
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
/* Main part of "simple" table: limit[x] = x */
for (i = 0; i <= MAXJSAMPLE; i++) {
table[i + offset] = (byte) i;
}
offset += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
/* End of simple table, rest of first half of post-IDCT table */
for (i = CENTERJSAMPLE; i < 2 * (MAXJSAMPLE + 1); i++) {
table[i + offset] = (byte) MAXJSAMPLE;
}
/* Second half of post-IDCT table */
System
.arraycopy(cinfo.sample_range_limit,
cinfo.sample_range_limit_offset, table, offset
+ (4 * (MAXJSAMPLE + 1) - CENTERJSAMPLE),
CENTERJSAMPLE);
}
static void build_ycc_rgb_table(jpeg_decompress_struct cinfo) {
jpeg_color_deconverter cconvert = cinfo.cconvert;
int i;
int x;
// SHIFT_TEMPS
cconvert.Cr_r_tab = new int[MAXJSAMPLE + 1];
cconvert.Cb_b_tab = new int[MAXJSAMPLE + 1];
cconvert.Cr_g_tab = new int[MAXJSAMPLE + 1];
cconvert.Cb_g_tab = new int[MAXJSAMPLE + 1];
for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
/* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
/* Cr=>R value is nearest int to 1.40200 * x */
cconvert.Cr_r_tab[i] = ((int) (1.40200f * (1 << SCALEBITS) + 0.5f)
* x + ONE_HALF) >> SCALEBITS;
/* Cb=>B value is nearest int to 1.77200 * x */
cconvert.Cb_b_tab[i] = ((int) (1.77200f * (1 << SCALEBITS) + 0.5f)
* x + ONE_HALF) >> SCALEBITS;
/* Cr=>G value is scaled-up -0.71414 * x */
cconvert.Cr_g_tab[i] = ((int) (-(0.71414f * (1 << SCALEBITS) + 0.5f)) * x);
/* Cb=>G value is scaled-up -0.34414 * x */
/* We also add in ONE_HALF so that need not do it in inner loop */
cconvert.Cb_g_tab[i] = ((int) (-(0.34414f * (1 << SCALEBITS) + 0.5f))
* x + ONE_HALF);
}
}
static void jinit_color_deconverter(jpeg_decompress_struct cinfo) {
jpeg_color_deconverter cconvert = cinfo.cconvert = new jpeg_color_deconverter();
// cconvert.start_pass = start_pass_dcolor;
/* Make sure num_components agrees with jpeg_color_space */
switch (cinfo.jpeg_color_space) {
case JCS_GRAYSCALE:
if (cinfo.num_components != 1) {
error();
}
// ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
case JCS_RGB:
case JCS_YCbCr:
if (cinfo.num_components != 3) {
error();
}
// ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
case JCS_CMYK:
case JCS_YCCK:
if (cinfo.num_components != 4) {
error();
}
// ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
default: /* JCS_UNKNOWN can be anything */
if (cinfo.num_components < 1) {
error();
}
// ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
}
/*
* Set out_color_components and conversion method based on requested
* space. Also clear the component_needed flags for any unused
* components, so that earlier pipeline stages can avoid useless
* computation.
*/
int ci;
switch (cinfo.out_color_space) {
case JCS_GRAYSCALE:
cinfo.out_color_components = 1;
if (cinfo.jpeg_color_space == JCS_GRAYSCALE
|| cinfo.jpeg_color_space == JCS_YCbCr) {
cconvert.color_convert = GRAYSCALE_CONVERT;
/*
* For color.grayscale conversion, only the Y (0) component
* is needed
*/
for (ci = 1; ci < cinfo.num_components; ci++) {
cinfo.comp_info[ci].component_needed = false;
}
} else {
error();
}
// ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case JCS_RGB:
cinfo.out_color_components = RGB_PIXELSIZE;
if (cinfo.jpeg_color_space == JCS_YCbCr) {
cconvert.color_convert = YCC_RGB_CONVERT;
build_ycc_rgb_table(cinfo);
} else if (cinfo.jpeg_color_space == JCS_GRAYSCALE) {
cconvert.color_convert = GRAY_RGB_CONVERT;
} else if (cinfo.jpeg_color_space == JCS_RGB) {
cconvert.color_convert = NULL_CONVERT;
} else {
error();
}
// ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
case JCS_CMYK:
cinfo.out_color_components = 4;
if (cinfo.jpeg_color_space == JCS_YCCK) {
cconvert.color_convert = YCCK_CMYK_CONVERT;
build_ycc_rgb_table(cinfo);
} else if (cinfo.jpeg_color_space == JCS_CMYK) {
cconvert.color_convert = NULL_CONVERT;
} else {
error();
}
// ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
default:
/* Permit null conversion to same output space */
if (cinfo.out_color_space == cinfo.jpeg_color_space) {
cinfo.out_color_components = cinfo.num_components;
cconvert.color_convert = NULL_CONVERT;
} else {
/* unsupported non-null conversion */
error();
}
// ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
break;
}
if (cinfo.quantize_colors) {
cinfo.output_components = 1; /*
* single colormapped output
* component
*/
} else {
cinfo.output_components = cinfo.out_color_components;
}
}
static void jinit_d_post_controller(jpeg_decompress_struct cinfo,
boolean need_full_buffer) {
jpeg_d_post_controller post = cinfo.post = new jpeg_d_post_controller();
// post.pub.start_pass = start_pass_dpost;
post.whole_image = null; /* flag for no virtual arrays */
post.buffer = null; /* flag for no strip buffer */
/* Create the quantization buffer, if needed */
if (cinfo.quantize_colors) {
error(JPEGError.ERROR_NOT_IMPLEMENTED);
// /* The buffer strip height is max_v_samp_factor, which is
// typically
// * an efficient number of rows for upsampling to return.
// * (In the presence of output rescaling, we might want to be
// smarter?)
// */
// post.strip_height = cinfo.max_v_samp_factor;
// if (need_full_buffer) {
// /* Two-pass color quantization: need full-image storage. */
// /* We round up the number of rows to a multiple of the strip
// height. */
// #ifdef QUANT_2PASS_SUPPORTED
// post.whole_image = (*cinfo.mem.request_virt_sarray)
// ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
// cinfo.output_width * cinfo.out_color_components,
// (JDIMENSION) jround_up((long) cinfo.output_height,
// (long) post.strip_height),
// post.strip_height);
// #else
// ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
// #endif /* QUANT_2PASS_SUPPORTED */
// } else {
// /* One-pass color quantization: just make a strip buffer. */
// post.buffer = (*cinfo.mem.alloc_sarray)
// ((j_common_ptr) cinfo, JPOOL_IMAGE,
// cinfo.output_width * cinfo.out_color_components,
// post.strip_height);
// }
}
}
static void make_funny_pointers(jpeg_decompress_struct cinfo)
/*
* Create the funny pointer lists discussed in the comments above. The
* actual workspace is already allocated (in main.buffer), and the space for
* the pointer lists is allocated too. This routine just fills in the
* curiously ordered lists. This will be repeated at the beginning of each
* pass.
*/
{
jpeg_d_main_controller main = cinfo.main;
int ci, i, rgroup;
int M = cinfo.min_DCT_scaled_size;
jpeg_component_info compptr;
byte[][] buf, xbuf0, xbuf1;
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
rgroup = (compptr.v_samp_factor * compptr.DCT_scaled_size)
/ cinfo.min_DCT_scaled_size; /*
* height of a row group of
* component
*/
xbuf0 = main.xbuffer[0][ci];
int xbuf0_offset = main.xbuffer_offset[0][ci];
xbuf1 = main.xbuffer[1][ci];
int xbuf1_offset = main.xbuffer_offset[1][ci];
/* First copy the workspace pointers as-is */
buf = main.buffer[ci];
for (i = 0; i < rgroup * (M + 2); i++) {
xbuf0[i + xbuf0_offset] = xbuf1[i + xbuf1_offset] = buf[i];
}
/* In the second list, put the last four row groups in swapped order */
for (i = 0; i < rgroup * 2; i++) {
xbuf1[rgroup * (M - 2) + i + xbuf1_offset] = buf[rgroup * M + i];
xbuf1[rgroup * M + i + xbuf1_offset] = buf[rgroup * (M - 2) + i];
}
/*
* The wraparound pointers at top and bottom will be filled later
* (see set_wraparound_pointers, below). Initially we want the
* "above" pointers to duplicate the first actual data line. This
* only needs to happen in xbuffer[0].
*/
for (i = 0; i < rgroup; i++) {
xbuf0[i - rgroup + xbuf0_offset] = xbuf0[0 + xbuf0_offset];
}
}
}
static void alloc_funny_pointers(jpeg_decompress_struct cinfo)
/*
* Allocate space for the funny pointer lists. This is done only once, not
* once per pass.
*/
{
jpeg_d_main_controller main = cinfo.main;
int ci, rgroup;
int M = cinfo.min_DCT_scaled_size;
jpeg_component_info compptr;
byte[][] xbuf;
/*
* Get top-level space for component array pointers. We alloc both
* arrays with one call to save a few cycles.
*/
main.xbuffer[0] = new byte[cinfo.num_components][][];
main.xbuffer[1] = new byte[cinfo.num_components][][];
main.xbuffer_offset[0] = new int[cinfo.num_components];
main.xbuffer_offset[1] = new int[cinfo.num_components];
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
rgroup = (compptr.v_samp_factor * compptr.DCT_scaled_size)
/ cinfo.min_DCT_scaled_size; /*
* height of a row group of
* component
*/
/*
* Get space for pointer lists --- M+4 row groups in each list. We
* alloc both pointer lists with one call to save a few cycles.
*/
xbuf = new byte[2 * (rgroup * (M + 4))][];
int offset = rgroup;
main.xbuffer_offset[0][ci] = offset;
main.xbuffer[0][ci] = xbuf;
offset += rgroup * (M + 4);
main.xbuffer_offset[1][ci] = offset;
main.xbuffer[1][ci] = xbuf;
}
}
static void jinit_d_main_controller(jpeg_decompress_struct cinfo,
boolean need_full_buffer) {
int ci, rgroup, ngroups;
jpeg_component_info compptr;
jpeg_d_main_controller main = cinfo.main = new jpeg_d_main_controller();
// main.pub.start_pass = start_pass_main;
if (need_full_buffer)
{
error();
// ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
}
/*
* Allocate the workspace. ngroups is the number of row groups we need.
*/
if (cinfo.upsample.need_context_rows) {
if (cinfo.min_DCT_scaled_size < 2) {
error();
}
// ERREXIT(cinfo, JERR_NOTIMPL);
alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
ngroups = cinfo.min_DCT_scaled_size + 2;
} else {
ngroups = cinfo.min_DCT_scaled_size;
}
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
rgroup = (compptr.v_samp_factor * compptr.DCT_scaled_size)
/ cinfo.min_DCT_scaled_size; /*
* height of a row group of
* component
*/
main.buffer[ci] = new byte[rgroup * ngroups][compptr.width_in_blocks
* compptr.DCT_scaled_size];
}
}
static long jround_up(long a, long b)
/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
/* Assumes a >= 0, b > 0 */
{
a += b - 1L;
return a - (a % b);
}
static void jinit_upsampler(jpeg_decompress_struct cinfo) {
int ci;
jpeg_component_info compptr;
boolean need_buffer, do_fancy;
int h_in_group, v_in_group, h_out_group, v_out_group;
jpeg_upsampler upsample = new jpeg_upsampler();
cinfo.upsample = upsample;
// upsample.start_pass = start_pass_upsample;
// upsample.upsample = sep_upsample;
upsample.need_context_rows = false; /* until we find out differently */
if (cinfo.CCIR601_sampling)
{
error();
// ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
}
/*
* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
* so don't ask for it.
*/
do_fancy = cinfo.do_fancy_upsampling && cinfo.min_DCT_scaled_size > 1;
/*
* Verify we can handle the sampling factors, select per-component
* methods, and create storage as needed.
*/
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
/*
* Compute size of an "input group" after IDCT scaling. This many
* samples are to be converted to max_h_samp_factor *
* max_v_samp_factor pixels.
*/
h_in_group = (compptr.h_samp_factor * compptr.DCT_scaled_size)
/ cinfo.min_DCT_scaled_size;
v_in_group = (compptr.v_samp_factor * compptr.DCT_scaled_size)
/ cinfo.min_DCT_scaled_size;
h_out_group = cinfo.max_h_samp_factor;
v_out_group = cinfo.max_v_samp_factor;
upsample.rowgroup_height[ci] = v_in_group; /* save for use later */
need_buffer = true;
if (!compptr.component_needed) {
/* Don't bother to upsample an uninteresting component. */
upsample.methods[ci] = NOOP_UPSAMPLE;
need_buffer = false;
} else if (h_in_group == h_out_group && v_in_group == v_out_group) {
/* Fullsize components can be processed without any work. */
upsample.methods[ci] = FULLSIZE_UPSAMPLE;
need_buffer = false;
} else if (h_in_group * 2 == h_out_group
&& v_in_group == v_out_group) {
/* Special cases for 2h1v upsampling */
if (do_fancy && compptr.downsampled_width > 2) {
upsample.methods[ci] = H2V1_FANCY_UPSAMPLE;
} else {
upsample.methods[ci] = H2V1_UPSAMPLE;
}
} else if (h_in_group * 2 == h_out_group
&& v_in_group * 2 == v_out_group) {
/* Special cases for 2h2v upsampling */
if (do_fancy && compptr.downsampled_width > 2) {
upsample.methods[ci] = H2V2_FANCY_UPSAMPLE;
upsample.need_context_rows = true;
} else {
upsample.methods[ci] = H2V2_UPSAMPLE;
}
} else if ((h_out_group % h_in_group) == 0
&& (v_out_group % v_in_group) == 0) {
/* Generic integral-factors upsampling method */
upsample.methods[ci] = INT_UPSAMPLE;
upsample.h_expand[ci] = (byte) (h_out_group / h_in_group);
upsample.v_expand[ci] = (byte) (v_out_group / v_in_group);
} else {
error();
}
// ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
if (need_buffer) {
upsample.color_buf[ci] = new byte[cinfo.max_v_samp_factor][(int) jround_up(
cinfo.output_width, cinfo.max_h_samp_factor)];
}
}
}
static void jinit_phuff_decoder(jpeg_decompress_struct cinfo) {
int[][] coef_bit_ptr;
int ci, i;
cinfo.entropy = new phuff_entropy_decoder();
// entropy.pub.start_pass = start_pass_phuff_decoder;
/* Create progression status table */
cinfo.coef_bits = new int[cinfo.num_components][DCTSIZE2];
coef_bit_ptr = cinfo.coef_bits;
for (ci = 0; ci < cinfo.num_components; ci++) {
for (i = 0; i < DCTSIZE2; i++) {
coef_bit_ptr[ci][i] = -1;
}
}
}
static void jinit_huff_decoder(jpeg_decompress_struct cinfo) {
cinfo.entropy = new huff_entropy_decoder();
// entropy.pub.start_pass = start_pass_huff_decoder;
// entropy.pub.decode_mcu = decode_mcu;
}
static void jinit_inverse_dct(jpeg_decompress_struct cinfo) {
int ci;
jpeg_component_info compptr;
jpeg_inverse_dct idct = cinfo.idct = new jpeg_inverse_dct();
// idct.pub.start_pass = start_pass;
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
/* Allocate and pre-zero a multiplier table for each component */
compptr.dct_table = new int[DCTSIZE2];
/* Mark multiplier table not yet set up for any method */
idct.cur_method[ci] = -1;
}
}
static final int CONST_BITS = 13;
static final int PASS1_BITS = 2;
static final int RANGE_MASK = (MAXJSAMPLE * 4 + 3);
static void jpeg_idct_islow(jpeg_decompress_struct cinfo,
jpeg_component_info compptr, short[] coef_block,
byte[][] output_buf, int output_buf_offset, int output_col) {
int tmp0, tmp1, tmp2, tmp3;
int tmp10, tmp11, tmp12, tmp13;
int z1, z2, z3, z4, z5;
short[] inptr;
int[] quantptr;
int[] wsptr;
byte[] outptr;
byte[] range_limit = cinfo.sample_range_limit;
int range_limit_offset = cinfo.sample_range_limit_offset
+ CENTERJSAMPLE;
int ctr;
int[] workspace = cinfo.workspace; /* buffers data between passes */
// SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
/* Note results are scaled up by sqrt(8) compared to a true IDCT; */
/* furthermore, we scale the results by 2**PASS1_BITS. */
inptr = coef_block;
quantptr = compptr.dct_table;
wsptr = workspace;
int inptr_offset = 0, quantptr_offset = 0, wsptr_offset = 0;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/*
* Due to quantization, we will usually find that many of the input
* coefficients are zero, especially the AC terms. We can exploit
* this by short-circuiting the IDCT calculation for any column in
* which all the AC terms are zero. In that case each output is
* equal to the DC coefficient (with scale factor as needed). With
* typical images and quantization tables, half or more of the
* column DCT calculations can be simplified this way.
*/
if (inptr[DCTSIZE * 1 + inptr_offset] == 0
&& inptr[DCTSIZE * 2 + inptr_offset] == 0
&& inptr[DCTSIZE * 3 + inptr_offset] == 0
&& inptr[DCTSIZE * 4 + inptr_offset] == 0
&& inptr[DCTSIZE * 5 + inptr_offset] == 0
&& inptr[DCTSIZE * 6 + inptr_offset] == 0
&& inptr[DCTSIZE * 7 + inptr_offset] == 0) {
/* AC terms all zero */
int dcval = ((inptr[DCTSIZE * 0 + inptr_offset]) * quantptr[DCTSIZE
* 0 + quantptr_offset]) << PASS1_BITS;
wsptr[DCTSIZE * 0 + wsptr_offset] = dcval;
wsptr[DCTSIZE * 1 + wsptr_offset] = dcval;
wsptr[DCTSIZE * 2 + wsptr_offset] = dcval;
wsptr[DCTSIZE * 3 + wsptr_offset] = dcval;
wsptr[DCTSIZE * 4 + wsptr_offset] = dcval;
wsptr[DCTSIZE * 5 + wsptr_offset] = dcval;
wsptr[DCTSIZE * 6 + wsptr_offset] = dcval;
wsptr[DCTSIZE * 7 + wsptr_offset] = dcval;
inptr_offset++; /* advance pointers to next column */
quantptr_offset++;
wsptr_offset++;
continue;
}
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = ((inptr[DCTSIZE * 2 + inptr_offset]) * quantptr[DCTSIZE * 2
+ quantptr_offset]);
z3 = ((inptr[DCTSIZE * 6 + inptr_offset]) * quantptr[DCTSIZE * 6
+ quantptr_offset]);
z1 = ((z2 + z3) * 4433/* FIX_0_541196100 */);
tmp2 = z1 + (z3 * -15137/* FIX_1_847759065 */);
tmp3 = z1 + (z2 * 6270/* FIX_0_765366865 */);
z2 = ((inptr[DCTSIZE * 0 + inptr_offset]) * quantptr[DCTSIZE * 0
+ quantptr_offset]);
z3 = ((inptr[DCTSIZE * 4 + inptr_offset]) * quantptr[DCTSIZE * 4
+ quantptr_offset]);
tmp0 = (z2 + z3) << CONST_BITS;
tmp1 = (z2 - z3) << CONST_BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
/*
* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
tmp0 = ((inptr[DCTSIZE * 7 + inptr_offset]) * quantptr[DCTSIZE * 7
+ quantptr_offset]);
tmp1 = ((inptr[DCTSIZE * 5 + inptr_offset]) * quantptr[DCTSIZE * 5
+ quantptr_offset]);
tmp2 = ((inptr[DCTSIZE * 3 + inptr_offset]) * quantptr[DCTSIZE * 3
+ quantptr_offset]);
tmp3 = ((inptr[DCTSIZE * 1 + inptr_offset]) * quantptr[DCTSIZE * 1
+ quantptr_offset]);
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = ((z3 + z4) * 9633/* FIX_1_175875602 */); /* sqrt(2) * c3 */
tmp0 = (tmp0 * 2446/* FIX_0_298631336 */); /*
* sqrt(2) *
* (-c1+c3+c5-c7)
*/
tmp1 = (tmp1 * 16819/* FIX_2_053119869 */); /*
* sqrt(2) * (
* c1+c3-c5+c7)
*/
tmp2 = (tmp2 * 25172/* FIX_3_072711026 */); /*
* sqrt(2) * (
* c1+c3+c5-c7)
*/
tmp3 = (tmp3 * 12299/* FIX_1_501321110 */); /*
* sqrt(2) * (
* c1+c3-c5-c7)
*/
z1 = (z1 * -7373/* FIX_0_899976223 */); /* sqrt(2) * (c7-c3) */
z2 = (z2 * -20995/* FIX_2_562915447 */); /* sqrt(2) * (-c1-c3) */
z3 = (z3 * -16069/* FIX_1_961570560 */); /* sqrt(2) * (-c3-c5) */
z4 = (z4 * -3196/* FIX_0_390180644 */); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
// #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
wsptr[DCTSIZE * 0 + wsptr_offset] = (((tmp10 + tmp3) + (1 << ((CONST_BITS - PASS1_BITS) - 1))) >> (CONST_BITS - PASS1_BITS));
wsptr[DCTSIZE * 7 + wsptr_offset] = (((tmp10 - tmp3) + (1 << ((CONST_BITS - PASS1_BITS) - 1))) >> (CONST_BITS - PASS1_BITS));
wsptr[DCTSIZE * 1 + wsptr_offset] = (((tmp11 + tmp2) + (1 << ((CONST_BITS - PASS1_BITS) - 1))) >> (CONST_BITS - PASS1_BITS));
wsptr[DCTSIZE * 6 + wsptr_offset] = (((tmp11 - tmp2) + (1 << ((CONST_BITS - PASS1_BITS) - 1))) >> (CONST_BITS - PASS1_BITS));
wsptr[DCTSIZE * 2 + wsptr_offset] = (((tmp12 + tmp1) + (1 << ((CONST_BITS - PASS1_BITS) - 1))) >> (CONST_BITS - PASS1_BITS));
wsptr[DCTSIZE * 5 + wsptr_offset] = (((tmp12 - tmp1) + (1 << ((CONST_BITS - PASS1_BITS) - 1))) >> (CONST_BITS - PASS1_BITS));
wsptr[DCTSIZE * 3 + wsptr_offset] = (((tmp13 + tmp0) + (1 << ((CONST_BITS - PASS1_BITS) - 1))) >> (CONST_BITS - PASS1_BITS));
wsptr[DCTSIZE * 4 + wsptr_offset] = (((tmp13 - tmp0) + (1 << ((CONST_BITS - PASS1_BITS) - 1))) >> (CONST_BITS - PASS1_BITS));
inptr_offset++; /* advance pointers to next column */
quantptr_offset++;
wsptr_offset++;
}
/* Pass 2: process rows from work array, store into output array. */
/* Note that we must descale the results by a factor of 8 == 2**3, */
/* and also undo the PASS1_BITS scaling. */
int outptr_offset = 0;
wsptr = workspace;
wsptr_offset = 0;
for (ctr = 0; ctr < DCTSIZE; ctr++) {
outptr = output_buf[ctr + output_buf_offset];
outptr_offset = output_col;
/*
* Rows of zeroes can be exploited in the same way as we did with
* columns. However, the column calculation has created many nonzero
* AC terms, so the simplification applies less often (typically 5%
* to 10% of the time). On machines with very fast multiplication,
* it's possible that the test takes more time than it's worth. In
* that case this section may be commented out.
*/
// #ifndef NO_ZERO_ROW_TEST
if (wsptr[1 + wsptr_offset] == 0 && wsptr[2 + wsptr_offset] == 0
&& wsptr[3 + wsptr_offset] == 0
&& wsptr[4 + wsptr_offset] == 0
&& wsptr[5 + wsptr_offset] == 0
&& wsptr[6 + wsptr_offset] == 0
&& wsptr[7 + wsptr_offset] == 0) {
/* AC terms all zero */
// #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
byte dcval = range_limit[range_limit_offset
+ ((((wsptr[0 + wsptr_offset]) + (1 << ((PASS1_BITS + 3) - 1))) >> PASS1_BITS + 3) & RANGE_MASK)];
outptr[0 + outptr_offset] = dcval;
outptr[1 + outptr_offset] = dcval;
outptr[2 + outptr_offset] = dcval;
outptr[3 + outptr_offset] = dcval;
outptr[4 + outptr_offset] = dcval;
outptr[5 + outptr_offset] = dcval;
outptr[6 + outptr_offset] = dcval;
outptr[7 + outptr_offset] = dcval;
wsptr_offset += DCTSIZE; /* advance pointer to next row */
continue;
}
// #endif
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
z2 = wsptr[2 + wsptr_offset];
z3 = wsptr[6 + wsptr_offset];
z1 = ((z2 + z3) * 4433/* FIX_0_541196100 */);
tmp2 = z1 + (z3 * -15137/* FIX_1_847759065 */);
tmp3 = z1 + (z2 * 6270/* FIX_0_765366865 */);
tmp0 = (wsptr[0 + wsptr_offset] + wsptr[4 + wsptr_offset]) << CONST_BITS;
tmp1 = (wsptr[0 + wsptr_offset] - wsptr[4 + wsptr_offset]) << CONST_BITS;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
/*
* Odd part per figure 8; the matrix is unitary and hence its
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
tmp0 = wsptr[7 + wsptr_offset];
tmp1 = wsptr[5 + wsptr_offset];
tmp2 = wsptr[3 + wsptr_offset];
tmp3 = wsptr[1 + wsptr_offset];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = ((z3 + z4) * 9633/* FIX_1_175875602 */); /* sqrt(2) * c3 */
tmp0 = (tmp0 * 2446/* FIX_0_298631336 */); /*
* sqrt(2) *
* (-c1+c3+c5-c7)
*/
tmp1 = (tmp1 * 16819/* FIX_2_053119869 */); /*
* sqrt(2) * (
* c1+c3-c5+c7)
*/
tmp2 = (tmp2 * 25172/* FIX_3_072711026 */); /*
* sqrt(2) * (
* c1+c3+c5-c7)
*/
tmp3 = (tmp3 * 12299/* FIX_1_501321110 */); /*
* sqrt(2) * (
* c1+c3-c5-c7)
*/
z1 = (z1 * -7373/* FIX_0_899976223 */); /* sqrt(2) * (c7-c3) */
z2 = (z2 * -20995/* FIX_2_562915447 */); /* sqrt(2) * (-c1-c3) */
z3 = (z3 * -16069/* FIX_1_961570560 */); /* sqrt(2) * (-c3-c5) */
z4 = (z4 * -3196/* FIX_0_390180644 */); /* sqrt(2) * (c5-c3) */
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
// #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
outptr[0 + outptr_offset] = range_limit[range_limit_offset
+ ((((tmp10 + tmp3) + (1 << ((CONST_BITS + PASS1_BITS + 3) - 1))) >> CONST_BITS
+ PASS1_BITS + 3) & RANGE_MASK)];
outptr[7 + outptr_offset] = range_limit[range_limit_offset
+ ((((tmp10 - tmp3) + (1 << ((CONST_BITS + PASS1_BITS + 3) - 1))) >> CONST_BITS
+ PASS1_BITS + 3) & RANGE_MASK)];
outptr[1 + outptr_offset] = range_limit[range_limit_offset
+ ((((tmp11 + tmp2) + (1 << ((CONST_BITS + PASS1_BITS + 3) - 1))) >> CONST_BITS
+ PASS1_BITS + 3) & RANGE_MASK)];
outptr[6 + outptr_offset] = range_limit[range_limit_offset
+ ((((tmp11 - tmp2) + (1 << ((CONST_BITS + PASS1_BITS + 3) - 1))) >> CONST_BITS
+ PASS1_BITS + 3) & RANGE_MASK)];
outptr[2 + outptr_offset] = range_limit[range_limit_offset
+ ((((tmp12 + tmp1) + (1 << ((CONST_BITS + PASS1_BITS + 3) - 1))) >> CONST_BITS
+ PASS1_BITS + 3) & RANGE_MASK)];
outptr[5 + outptr_offset] = range_limit[range_limit_offset
+ ((((tmp12 - tmp1) + (1 << ((CONST_BITS + PASS1_BITS + 3) - 1))) >> CONST_BITS
+ PASS1_BITS + 3) & RANGE_MASK)];
outptr[3 + outptr_offset] = range_limit[range_limit_offset
+ ((((tmp13 + tmp0) + (1 << ((CONST_BITS + PASS1_BITS + 3) - 1))) >> CONST_BITS
+ PASS1_BITS + 3) & RANGE_MASK)];
outptr[4 + outptr_offset] = range_limit[range_limit_offset
+ ((((tmp13 - tmp0) + (1 << ((CONST_BITS + PASS1_BITS + 3) - 1))) >> CONST_BITS
+ PASS1_BITS + 3) & RANGE_MASK)];
wsptr_offset += DCTSIZE; /* advance pointer to next row */
}
}
static void upsample(jpeg_decompress_struct cinfo, byte[][][] input_buf,
int[] input_buf_offset, int[] in_row_group_ctr,
int in_row_groups_avail, byte[][] output_buf, int[] out_row_ctr,
int out_rows_avail) {
sep_upsample(cinfo, input_buf, input_buf_offset, in_row_group_ctr,
in_row_groups_avail, output_buf, out_row_ctr, out_rows_avail);
}
static boolean smoothing_ok(jpeg_decompress_struct cinfo) {
jpeg_d_coef_controller coef = cinfo.coef;
boolean smoothing_useful = false;
int ci, coefi;
jpeg_component_info compptr;
JQUANT_TBL qtable;
int[] coef_bits;
int[] coef_bits_latch;
if (!cinfo.progressive_mode || cinfo.coef_bits == null) {
return false;
}
/* Allocate latch area if not already done */
if (coef.coef_bits_latch == null) {
coef.coef_bits_latch = new int[cinfo.num_components * SAVED_COEFS];
}
coef_bits_latch = coef.coef_bits_latch;
int coef_bits_latch_offset = 0;
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
/* All components' quantization values must already be latched. */
if ((qtable = compptr.quant_table) == null) {
return false;
}
/*
* Verify DC & first 5 AC quantizers are nonzero to avoid
* zero-divide.
*/
if (qtable.quantval[0] == 0 || qtable.quantval[Q01_POS] == 0
|| qtable.quantval[Q10_POS] == 0
|| qtable.quantval[Q20_POS] == 0
|| qtable.quantval[Q11_POS] == 0
|| qtable.quantval[Q02_POS] == 0) {
return false;
}
/* DC values must be at least partly known for all components. */
coef_bits = cinfo.coef_bits[ci];
if (coef_bits[0] < 0) {
return false;
}
/*
* Block smoothing is helpful if some AC coefficients remain
* inaccurate.
*/
for (coefi = 1; coefi <= 5; coefi++) {
coef_bits_latch[coefi + coef_bits_latch_offset] = coef_bits[coefi];
if (coef_bits[coefi] != 0) {
smoothing_useful = true;
}
}
coef_bits_latch_offset += SAVED_COEFS;
}
return smoothing_useful;
}
static void master_selection(jpeg_decompress_struct cinfo) {
jpeg_decomp_master master = cinfo.master;
boolean use_c_buffer;
long samplesperrow;
int jd_samplesperrow;
/* Initialize dimensions and other stuff */
jpeg_calc_output_dimensions(cinfo);
prepare_range_limit_table(cinfo);
/* Width of an output scanline must be representable as JDIMENSION. */
samplesperrow = (long) cinfo.output_width
* (long) cinfo.out_color_components;
jd_samplesperrow = (int) samplesperrow;
if (jd_samplesperrow != samplesperrow)
{
error();
// ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
}
/* Initialize my private state */
master.pass_number = 0;
master.using_merged_upsample = use_merged_upsample(cinfo);
/* Color quantizer selection */
master.quantizer_1pass = null;
master.quantizer_2pass = null;
/* No mode changes if not using buffered-image mode. */
if (!cinfo.quantize_colors || !cinfo.buffered_image) {
cinfo.enable_1pass_quant = false;
cinfo.enable_external_quant = false;
cinfo.enable_2pass_quant = false;
}
if (cinfo.quantize_colors) {
error(JPEGError.ERROR_NOT_IMPLEMENTED);
// if (cinfo.raw_data_out)
// ERREXIT(cinfo, JERR_NOTIMPL);
// /* 2-pass quantizer only works in 3-component color space. */
// if (cinfo.out_color_components != 3) {
// cinfo.enable_1pass_quant = true;
// cinfo.enable_external_quant = false;
// cinfo.enable_2pass_quant = false;
// cinfo.colormap = null;
// } else if (cinfo.colormap != null) {
// cinfo.enable_external_quant = true;
// } else if (cinfo.two_pass_quantize) {
// cinfo.enable_2pass_quant = true;
// } else {
// cinfo.enable_1pass_quant = true;
// }
//
// if (cinfo.enable_1pass_quant) {
// #ifdef QUANT_1PASS_SUPPORTED
// jinit_1pass_quantizer(cinfo);
// master.quantizer_1pass = cinfo.cquantize;
// #else
// ERREXIT(cinfo, JERR_NOT_COMPILED);
// #endif
// }
//
// /* We use the 2-pass code to map to external colormaps. */
// if (cinfo.enable_2pass_quant || cinfo.enable_external_quant) {
// #ifdef QUANT_2PASS_SUPPORTED
// jinit_2pass_quantizer(cinfo);
// master.quantizer_2pass = cinfo.cquantize;
// #else
// ERREXIT(cinfo, JERR_NOT_COMPILED);
// #endif
// }
// /* If both quantizers are initialized, the 2-pass one is left
// active;
// * this is necessary for starting with quantization to an external
// map.
// */
}
/* Post-processing: in particular, color conversion first */
if (!cinfo.raw_data_out) {
if (master.using_merged_upsample) {
// #ifdef UPSAMPLE_MERGING_SUPPORTED
// jinit_merged_upsampler(cinfo); /* does color conversion too
// */
// #else
error();
// ERREXIT(cinfo, JERR_NOT_COMPILED);
// #endif
} else {
jinit_color_deconverter(cinfo);
jinit_upsampler(cinfo);
}
jinit_d_post_controller(cinfo, cinfo.enable_2pass_quant);
}
/* Inverse DCT */
jinit_inverse_dct(cinfo);
/* Entropy decoding: either Huffman or arithmetic coding. */
if (cinfo.arith_code) {
error();
// ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
} else {
if (cinfo.progressive_mode) {
// #ifdef D_PROGRESSIVE_SUPPORTED
jinit_phuff_decoder(cinfo);
// #else
// ERREXIT(cinfo, JERR_NOT_COMPILED);
// #endif
} else {
jinit_huff_decoder(cinfo);
}
}
/* Initialize principal buffer controllers. */
use_c_buffer = cinfo.inputctl.has_multiple_scans
|| cinfo.buffered_image;
jinit_d_coef_controller(cinfo, use_c_buffer);
if (!cinfo.raw_data_out) {
jinit_d_main_controller(cinfo, false /*
* never need full buffer
* here
*/);
}
/* Initialize input side of decompressor to consume first scan. */
start_input_pass(cinfo);
// #ifdef D_MULTISCAN_FILES_SUPPORTED
/*
* If jpeg_start_decompress will read the whole file, initialize
* progress monitoring appropriately. The input step is counted as one
* pass.
*/
// if (cinfo.progress != null && ! cinfo.buffered_image &&
// cinfo.inputctl.has_multiple_scans) {
// int nscans;
// /* Estimate number of scans to set pass_limit. */
// if (cinfo.progressive_mode) {
// /* Arbitrarily estimate 2 interleaved DC scans + 3 AC
// scans/component. */
// nscans = 2 + 3 * cinfo.num_components;
// } else {
// /* For a nonprogressive multiscan file, estimate 1 scan per
// component. */
// nscans = cinfo.num_components;
// }
// cinfo.progress.pass_counter = 0L;
// cinfo.progress.pass_limit = (long) cinfo.total_iMCU_rows * nscans;
// cinfo.progress.completed_passes = 0;
// cinfo.progress.total_passes = (cinfo.enable_2pass_quant ? 3 : 2);
// /* Count the input pass as done */
// master.pass_number++;
// }
// #endif /* D_MULTISCAN_FILES_SUPPORTED */
}
static void jinit_master_decompress(jpeg_decompress_struct cinfo) {
jpeg_decomp_master master = new jpeg_decomp_master();
cinfo.master = master;
// master.prepare_for_output_pass = prepare_for_output_pass;
// master.finish_output_pass = finish_output_pass;
master.is_dummy_pass = false;
master_selection(cinfo);
}
static void jcopy_sample_rows(byte[][] input_array, int source_row,
byte[][] output_array, int dest_row, int num_rows, int num_cols)
/*
* Copy some rows of samples from one place to another. num_rows rows are
* copied from input_array[source_row++] to output_array[dest_row++]; these
* areas may overlap for duplication. The source and destination arrays must
* be at least as wide as num_cols.
*/
{
byte[] inptr, outptr;
int count = num_cols;
int row;
int input_array_offset = source_row;
int output_array_offset = dest_row;
for (row = num_rows; row > 0; row--) {
inptr = input_array[input_array_offset++];
outptr = output_array[output_array_offset++];
System.arraycopy(inptr, 0, outptr, 0, count);
}
}
static boolean jpeg_start_decompress(jpeg_decompress_struct cinfo) {
if (cinfo.global_state == DSTATE_READY) {
/* First call: initialize master control, select active modules */
jinit_master_decompress(cinfo);
if (cinfo.buffered_image) {
/* No more work here; expecting jpeg_start_output next */
cinfo.global_state = DSTATE_BUFIMAGE;
return true;
}
cinfo.global_state = DSTATE_PRELOAD;
}
if (cinfo.global_state == DSTATE_PRELOAD) {
/* If file has multiple scans, absorb them all into the coef buffer */
if (cinfo.inputctl.has_multiple_scans) {
// #ifdef D_MULTISCAN_FILES_SUPPORTED
for (;;) {
int retcode;
/* Call progress monitor hook if present */
// if (cinfo.progress != null)
// (*cinfo.progress.progress_monitor) ((j_common_ptr)
// cinfo);
/* Absorb some more input */
retcode = consume_input(cinfo);
if (retcode == JPEG_SUSPENDED) {
return false;
}
if (retcode == JPEG_REACHED_EOI) {
break;
/* Advance progress counter if appropriate */
// if (cinfo.progress != null && (retcode ==
// JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
// if (++cinfo.progress.pass_counter >=
// cinfo.progress.pass_limit) {
// /* jdmaster underestimated number of scans; ratchet up
// one scan */
// cinfo.progress.pass_limit += (long)
// cinfo.total_iMCU_rows;
// }
// }
}
}
// #else
// ERREXIT(cinfo, JERR_NOT_COMPILED);
// #endif /* D_MULTISCAN_FILES_SUPPORTED */
}
cinfo.output_scan_number = cinfo.input_scan_number;
} else if (cinfo.global_state != DSTATE_PRESCAN) {
error();
}
// ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
/* Perform any dummy output passes, and set up for the final pass */
return output_pass_setup(cinfo);
}
static void prepare_for_output_pass(jpeg_decompress_struct cinfo) {
jpeg_decomp_master master = cinfo.master;
if (master.is_dummy_pass) {
// #ifdef QUANT_2PASS_SUPPORTED
// /* Final pass of 2-pass quantization */
// master.pub.is_dummy_pass = FALSE;
// (*cinfo.cquantize.start_pass) (cinfo, FALSE);
// (*cinfo.post.start_pass) (cinfo, JBUF_CRANK_DEST);
// (*cinfo.main.start_pass) (cinfo, JBUF_CRANK_DEST);
// #else
error(JPEGError.ERROR_NOT_IMPLEMENTED);
// ERREXIT(cinfo, JERR_NOT_COMPILED);
// #endif /* QUANT_2PASS_SUPPORTED */
} else {
if (cinfo.quantize_colors && cinfo.colormap == null) {
/* Select new quantization method */
if (cinfo.two_pass_quantize && cinfo.enable_2pass_quant) {
cinfo.cquantize = master.quantizer_2pass;
master.is_dummy_pass = true;
} else if (cinfo.enable_1pass_quant) {
cinfo.cquantize = master.quantizer_1pass;
} else {
error();
// ERREXIT(cinfo, JERR_MODE_CHANGE);
}
}
cinfo.idct.start_pass(cinfo);
start_output_pass(cinfo);
if (!cinfo.raw_data_out) {
if (!master.using_merged_upsample) {
cinfo.cconvert.start_pass(cinfo);
}
cinfo.upsample.start_pass(cinfo);
if (cinfo.quantize_colors) {
cinfo.cquantize.start_pass(cinfo, master.is_dummy_pass);
}
cinfo.post.start_pass(cinfo,
(master.is_dummy_pass ? JBUF_SAVE_AND_PASS
: JBUF_PASS_THRU));
cinfo.main.start_pass(cinfo, JBUF_PASS_THRU);
}
}
// /* Set up progress monitor's pass info if present */
// if (cinfo.progress != NULL) {
// cinfo.progress.completed_passes = master.pass_number;
// cinfo.progress.total_passes = master.pass_number +
// (master.pub.is_dummy_pass ? 2 : 1);
// /* In buffered-image mode, we assume one more output pass if EOI not
// * yet reached, but no more passes if EOI has been reached.
// */
// if (cinfo.buffered_image && ! cinfo.inputctl.eoi_reached) {
// cinfo.progress.total_passes += (cinfo.enable_2pass_quant ? 2 : 1);
// }
// }
}
static boolean jpeg_resync_to_restart(jpeg_decompress_struct cinfo,
int desired) {
int marker = cinfo.unread_marker;
int action = 1;
/* Always put up a warning. */
// WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);
/* Outer loop handles repeated decision after scanning forward. */
for (;;) {
if (marker < M_SOF0) {
action = 2; /* invalid marker */
} else if (marker < M_RST0 || marker > M_RST7) {
action = 3; /* valid non-restart marker */
} else {
if (marker == (M_RST0 + ((desired + 1) & 7))
|| marker == (M_RST0 + ((desired + 2) & 7))) {
action = 3; /* one of the next two expected restarts */
} else if (marker == (M_RST0 + ((desired - 1) & 7))
|| marker == (M_RST0 + ((desired - 2) & 7))) {
action = 2; /* a prior restart, so advance */
} else {
action = 1; /* desired restart or too far away */
}
}
// TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);
switch (action) {
case 1:
/* Discard marker and let entropy decoder resume processing. */
cinfo.unread_marker = 0;
return true;
case 2:
/* Scan to the next marker, and repeat the decision loop. */
if (!next_marker(cinfo)) {
return false;
}
marker = cinfo.unread_marker;
break;
case 3:
/* Return without advancing past this marker. */
/*
* Entropy decoder will be forced to process an empty
* segment.
*/
return true;
}
} /* end loop */
}
static boolean read_restart_marker(jpeg_decompress_struct cinfo) {
/* Obtain a marker unless we already did. */
/* Note that next_marker will complain if it skips any data. */
if (cinfo.unread_marker == 0) {
if (!next_marker(cinfo)) {
return false;
}
}
if (cinfo.unread_marker == (M_RST0 + cinfo.marker.next_restart_num)) {
/*
* Normal case --- swallow the marker and let entropy decoder
* continue
*/
// TRACEMS1(cinfo, 3, JTRC_RST, cinfo.marker.next_restart_num);
cinfo.unread_marker = 0;
} else {
/* Uh-oh, the restart markers have been messed up. */
/* Let the data source manager determine how to resync. */
if (!jpeg_resync_to_restart(cinfo, cinfo.marker.next_restart_num)) {
return false;
}
}
/* Update next-restart state */
cinfo.marker.next_restart_num = (cinfo.marker.next_restart_num + 1) & 7;
return true;
}
static boolean jpeg_fill_bit_buffer(bitread_working_state state,
int get_buffer, int bits_left, int nbits)
/* Load up the bit buffer to a depth of at least nbits */
{
/* Copy heavily used state fields into locals (hopefully registers) */
byte[] buffer = state.buffer;
int bytes_in_buffer = state.bytes_in_buffer;
int bytes_offset = state.bytes_offset;
jpeg_decompress_struct cinfo = state.cinfo;
/* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
/* (It is assumed that no request will be for more than that many bits.) */
/* We fail to do so only if we hit a marker or are forced to suspend. */
if (cinfo.unread_marker == 0) { /* cannot advance past a marker */
while (bits_left < MIN_GET_BITS) {
int c;
/* Attempt to read a byte */
if (bytes_offset == bytes_in_buffer) {
if (!fill_input_buffer(cinfo)) {
return false;
}
buffer = cinfo.buffer;
bytes_in_buffer = cinfo.bytes_in_buffer;
bytes_offset = cinfo.bytes_offset;
}
c = buffer[bytes_offset++] & 0xFF;
/* If it's 0xFF, check and discard stuffed zero byte */
if (c == 0xFF) {
/*
* Loop here to discard any padding FF's on terminating
* marker, so that we can save a valid unread_marker value.
* NOTE: we will accept multiple FF's followed by a 0 as
* meaning a single FF data byte. This data pattern is not
* valid according to the standard.
*/
do {
if (bytes_offset == bytes_in_buffer) {
if (!fill_input_buffer(cinfo)) {
return false;
}
buffer = cinfo.buffer;
bytes_in_buffer = cinfo.bytes_in_buffer;
bytes_offset = cinfo.bytes_offset;
}
c = buffer[bytes_offset++] & 0xFF;
} while (c == 0xFF);
if (c == 0) {
/* Found FF/00, which represents an FF data byte */
c = 0xFF;
} else {
/*
* Oops, it's actually a marker indicating end of
* compressed data. Save the marker code for later use.
* Fine point: it might appear that we should save the
* marker into bitread working state, not straight into
* permanent state. But once we have hit a marker, we
* cannot need to suspend within the current MCU,
* because we will read no more bytes from the data
* source. So it is OK to update permanent state right
* away.
*/
cinfo.unread_marker = c;
/* See if we need to insert some fake zero bits. */
// goto no_more_bytes;
if (nbits > bits_left) {
/*
* Uh-oh. Report corrupted data to user and stuff
* zeroes into the data stream, so that we can
* produce some kind of image. We use a nonvolatile
* flag to ensure that only one warning message
* appears per data segment.
*/
if (!cinfo.entropy.insufficient_data) {
// WARNMS(cinfo, JWRN_HIT_MARKER);
cinfo.entropy.insufficient_data = true;
}
/* Fill the buffer with zero bits */
get_buffer <<= MIN_GET_BITS - bits_left;
bits_left = MIN_GET_BITS;
}
/* Unload the local registers */
state.buffer = buffer;
state.bytes_in_buffer = bytes_in_buffer;
state.bytes_offset = bytes_offset;
state.get_buffer = get_buffer;
state.bits_left = bits_left;
return true;
}
}
/* OK, load c into get_buffer */
get_buffer = (get_buffer << 8) | c;
bits_left += 8;
} /* end while */
} else {
// no_more_bytes:
/*
* We get here if we've read the marker that terminates the
* compressed data segment. There should be enough bits in the
* buffer register to satisfy the request; if so, no problem.
*/
if (nbits > bits_left) {
/*
* Uh-oh. Report corrupted data to user and stuff zeroes into
* the data stream, so that we can produce some kind of image.
* We use a nonvolatile flag to ensure that only one warning
* message appears per data segment.
*/
if (!cinfo.entropy.insufficient_data) {
// WARNMS(cinfo, JWRN_HIT_MARKER);
cinfo.entropy.insufficient_data = true;
}
/* Fill the buffer with zero bits */
get_buffer <<= MIN_GET_BITS - bits_left;
bits_left = MIN_GET_BITS;
}
}
/* Unload the local registers */
state.buffer = buffer;
state.bytes_in_buffer = bytes_in_buffer;
state.bytes_offset = bytes_offset;
state.get_buffer = get_buffer;
state.bits_left = bits_left;
return true;
}
static int jpeg_huff_decode(bitread_working_state state, int get_buffer,
int bits_left, d_derived_tbl htbl, int min_bits) {
int l = min_bits;
int code;
/* HUFF_DECODE has determined that the code is at least min_bits */
/* bits long, so fetch that many bits in one swoop. */
// CHECK_BIT_BUFFER(*state, l, return -1);
{
if (bits_left < (l)) {
if (!jpeg_fill_bit_buffer(state, get_buffer, bits_left, l)) {
return -1;
}
get_buffer = (state).get_buffer;
bits_left = (state).bits_left;
}
}
// code = GET_BITS(l);
code = (((get_buffer >> (bits_left -= (l)))) & ((1 << (l)) - 1));
/* Collect the rest of the Huffman code one bit at a time. */
/* This is per Figure F.16 in the JPEG spec. */
while (code > htbl.maxcode[l]) {
code <<= 1;
// CHECK_BIT_BUFFER(*state, 1, return -1);
{
if (bits_left < (1)) {
if (!jpeg_fill_bit_buffer(state, get_buffer, bits_left, 1)) {
return -1;
}
get_buffer = (state).get_buffer;
bits_left = (state).bits_left;
}
}
// code |= GET_BITS(1);
code |= (((get_buffer >> (bits_left -= (1)))) & ((1 << (1)) - 1));
l++;
}
/* Unload the local registers */
state.get_buffer = get_buffer;
state.bits_left = bits_left;
/* With garbage input we may reach the sentinel value l = 17. */
if (l > 16) {
// WARNMS(state.cinfo, JWRN_HUFF_BAD_CODE);
return 0; /* fake a zero as the safest result */
}
return htbl.pub.huffval[(code + htbl.valoffset[l])] & 0xFF;
}
static int decompress_onepass(jpeg_decompress_struct cinfo,
byte[][][] output_buf, int[] output_buf_offset) {
jpeg_d_coef_controller coef = cinfo.coef;
int MCU_col_num; /* index of current MCU within row */
int last_MCU_col = cinfo.MCUs_per_row - 1;
int last_iMCU_row = cinfo.total_iMCU_rows - 1;
int blkn, ci, xindex, yindex, yoffset, useful_width;
byte[][] output_ptr;
int start_col, output_col;
jpeg_component_info compptr;
// inverse_DCT_method_ptr inverse_DCT;
/* Loop to process as much as one whole iMCU row */
for (yoffset = coef.MCU_vert_offset; yoffset < coef.MCU_rows_per_iMCU_row; yoffset++) {
for (MCU_col_num = coef.MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) {
/*
* Try to fetch an MCU. Entropy decoder expects buffer to be
* zeroed.
*/
for (int i = 0; i < cinfo.blocks_in_MCU; i++) {
short[] blk = coef.MCU_buffer[i];
for (int j = 0; j < blk.length; j++) {
blk[j] = 0;
}
}
if (!cinfo.entropy.decode_mcu(cinfo, coef.MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef.MCU_vert_offset = yoffset;
coef.MCU_ctr = MCU_col_num;
return JPEG_SUSPENDED;
}
/*
* Determine where data should go in output_buf and do the IDCT
* thing. We skip dummy blocks at the right and bottom edges
* (but blkn gets incremented past them!). Note the inner loop
* relies on having allocated the MCU_buffer[] blocks
* sequentially.
*/
blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
compptr = cinfo.cur_comp_info[ci];
/* Don't bother to IDCT an uninteresting component. */
if (!compptr.component_needed) {
blkn += compptr.MCU_blocks;
continue;
}
// inverse_DCT =
// cinfo.idct.inverse_DCT[compptr.component_index];
useful_width = (MCU_col_num < last_MCU_col) ? compptr.MCU_width
: compptr.last_col_width;
output_ptr = output_buf[compptr.component_index];
int output_ptr_offset = output_buf_offset[compptr.component_index]
+ yoffset * compptr.DCT_scaled_size;
start_col = MCU_col_num * compptr.MCU_sample_width;
for (yindex = 0; yindex < compptr.MCU_height; yindex++) {
if (cinfo.input_iMCU_row < last_iMCU_row
|| yoffset + yindex < compptr.last_row_height) {
output_col = start_col;
for (xindex = 0; xindex < useful_width; xindex++) {
jpeg_idct_islow(cinfo, compptr,
coef.MCU_buffer[blkn + xindex],
output_ptr, output_ptr_offset,
output_col);
output_col += compptr.DCT_scaled_size;
}
}
blkn += compptr.MCU_width;
output_ptr_offset += compptr.DCT_scaled_size;
}
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
coef.MCU_ctr = 0;
}
/* Completed the iMCU row, advance counters for next one */
cinfo.output_iMCU_row++;
if (++(cinfo.input_iMCU_row) < cinfo.total_iMCU_rows) {
coef.start_iMCU_row(cinfo);
return JPEG_ROW_COMPLETED;
}
/* Completed the scan */
finish_input_pass(cinfo);
return JPEG_SCAN_COMPLETED;
}
static int decompress_smooth_data(jpeg_decompress_struct cinfo,
byte[][][] output_buf, int[] output_buf_offset) {
jpeg_d_coef_controller coef = cinfo.coef;
int last_iMCU_row = cinfo.total_iMCU_rows - 1;
int block_num, last_block_column;
int ci, block_row, block_rows;
short[][][] buffer;
short[][] buffer_ptr, prev_block_row, next_block_row;
byte[][] output_ptr;
int output_col;
jpeg_component_info compptr;
// inverse_DCT_method_ptr inverse_DCT;
boolean first_row, last_row;
short[] workspace = coef.workspace;
if (workspace == null) {
workspace = coef.workspace = new short[DCTSIZE2];
}
int[] coef_bits;
JQUANT_TBL quanttbl;
int Q00, Q01, Q02, Q10, Q11, Q20, num;
int DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9;
int Al, pred;
/* Force some input to be done if we are getting ahead of the input. */
while (cinfo.input_scan_number <= cinfo.output_scan_number
&& !cinfo.inputctl.eoi_reached) {
if (cinfo.input_scan_number == cinfo.output_scan_number) {
/*
* If input is working on current scan, we ordinarily want it to
* have completed the current row. But if input scan is DC, we
* want it to keep one row ahead so that next block row's DC
* values are up to date.
*/
int delta = (cinfo.Ss == 0) ? 1 : 0;
if (cinfo.input_iMCU_row > cinfo.output_iMCU_row + delta) {
break;
}
}
if (consume_input(cinfo) == JPEG_SUSPENDED) {
return JPEG_SUSPENDED;
}
}
/* OK, output from the virtual arrays. */
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
/* Don't bother to IDCT an uninteresting component. */
if (!compptr.component_needed) {
continue;
}
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo.output_iMCU_row < last_iMCU_row) {
block_rows = compptr.v_samp_factor;
last_row = false;
} else {
/*
* NB: can't use last_row_height here; it is
* input-side-dependent!
*/
block_rows = (compptr.height_in_blocks % compptr.v_samp_factor);
if (block_rows == 0) {
block_rows = compptr.v_samp_factor;
}
last_row = true;
}
/* Align the virtual buffer for this component. */
int buffer_offset;
if (cinfo.output_iMCU_row > 0) {
buffer = coef.whole_image[ci];
buffer_offset = (cinfo.output_iMCU_row - 1)
* compptr.v_samp_factor;
buffer_offset += compptr.v_samp_factor; /*
* point to current iMCU
* row
*/
first_row = false;
} else {
buffer = coef.whole_image[ci];
buffer_offset = 0;
first_row = true;
}
/* Fetch component-dependent info */
coef_bits = coef.coef_bits_latch;
int coef_offset = (ci * SAVED_COEFS);
quanttbl = compptr.quant_table;
Q00 = quanttbl.quantval[0];
Q01 = quanttbl.quantval[Q01_POS];
Q10 = quanttbl.quantval[Q10_POS];
Q20 = quanttbl.quantval[Q20_POS];
Q11 = quanttbl.quantval[Q11_POS];
Q02 = quanttbl.quantval[Q02_POS];
// inverse_DCT = cinfo.idct.inverse_DCT[ci];
output_ptr = output_buf[ci];
int output_ptr_offset = output_buf_offset[ci];
/* Loop over all DCT blocks to be processed. */
for (block_row = 0; block_row < block_rows; block_row++) {
buffer_ptr = buffer[block_row + buffer_offset];
int buffer_ptr_offset = 0, prev_block_row_offset = 0, next_block_row_offset = 0;
if (first_row && block_row == 0) {
prev_block_row = buffer_ptr;
prev_block_row_offset = buffer_ptr_offset;
} else {
prev_block_row = buffer[block_row - 1 + buffer_offset];
prev_block_row_offset = 0;
}
if (last_row && block_row == block_rows - 1) {
next_block_row = buffer_ptr;
next_block_row_offset = buffer_ptr_offset;
} else {
next_block_row = buffer[block_row + 1 + buffer_offset];
next_block_row_offset = 0;
}
/*
* We fetch the surrounding DC values using a sliding-register
* approach. Initialize all nine here so as to do the right
* thing on narrow pics.
*/
DC1 = DC2 = DC3 = prev_block_row[0 + prev_block_row_offset][0];
DC4 = DC5 = DC6 = buffer_ptr[0 + buffer_ptr_offset][0];
DC7 = DC8 = DC9 = next_block_row[0 + next_block_row_offset][0];
output_col = 0;
last_block_column = compptr.width_in_blocks - 1;
for (block_num = 0; block_num <= last_block_column; block_num++) {
/*
* Fetch current DCT block into workspace so we can modify
* it.
*/
// jcopy_block_row(buffer_ptr, workspace, 1);
System.arraycopy(buffer_ptr[buffer_ptr_offset], 0,
workspace, 0, workspace.length);
/* Update DC values */
if (block_num < last_block_column) {
DC3 = prev_block_row[1 + prev_block_row_offset][0];
DC6 = buffer_ptr[1 + buffer_ptr_offset][0];
DC9 = next_block_row[1 + next_block_row_offset][0];
}
/*
* Compute coefficient estimates per K.8. An estimate is
* applied only if coefficient is still zero, and is not
* known to be fully accurate.
*/
/* AC01 */
if ((Al = coef_bits[1 + coef_offset]) != 0
&& workspace[1] == 0) {
num = 36 * Q00 * (DC4 - DC6);
if (num >= 0) {
pred = (((Q01 << 7) + num) / (Q01 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
} else {
pred = (((Q01 << 7) - num) / (Q01 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
pred = -pred;
}
workspace[1] = (short) pred;
}
/* AC10 */
if ((Al = coef_bits[2 + coef_offset]) != 0
&& workspace[8] == 0) {
num = 36 * Q00 * (DC2 - DC8);
if (num >= 0) {
pred = (((Q10 << 7) + num) / (Q10 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
} else {
pred = (((Q10 << 7) - num) / (Q10 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
pred = -pred;
}
workspace[8] = (short) pred;
}
/* AC20 */
if ((Al = coef_bits[3 + coef_offset]) != 0
&& workspace[16] == 0) {
num = 9 * Q00 * (DC2 + DC8 - 2 * DC5);
if (num >= 0) {
pred = (((Q20 << 7) + num) / (Q20 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
} else {
pred = (((Q20 << 7) - num) / (Q20 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
pred = -pred;
}
workspace[16] = (short) pred;
}
/* AC11 */
if ((Al = coef_bits[4 + coef_offset]) != 0
&& workspace[9] == 0) {
num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
if (num >= 0) {
pred = (((Q11 << 7) + num) / (Q11 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
} else {
pred = (((Q11 << 7) - num) / (Q11 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
pred = -pred;
}
workspace[9] = (short) pred;
}
/* AC02 */
if ((Al = coef_bits[5 + coef_offset]) != 0
&& workspace[2] == 0) {
num = 9 * Q00 * (DC4 + DC6 - 2 * DC5);
if (num >= 0) {
pred = (((Q02 << 7) + num) / (Q02 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
} else {
pred = (((Q02 << 7) - num) / (Q02 << 8));
if (Al > 0 && pred >= (1 << Al)) {
pred = (1 << Al) - 1;
}
pred = -pred;
}
workspace[2] = (short) pred;
}
/* OK, do the IDCT */
jpeg_idct_islow(cinfo, compptr, workspace, output_ptr,
output_ptr_offset, output_col);
/* Advance for next column */
DC1 = DC2;
DC2 = DC3;
DC4 = DC5;
DC5 = DC6;
DC7 = DC8;
DC8 = DC9;
buffer_ptr_offset++;
prev_block_row_offset++;
next_block_row_offset++;
output_col += compptr.DCT_scaled_size;
}
output_ptr_offset += compptr.DCT_scaled_size;
}
}
if (++(cinfo.output_iMCU_row) < cinfo.total_iMCU_rows) {
return JPEG_ROW_COMPLETED;
}
return JPEG_SCAN_COMPLETED;
}
static int decompress_data(jpeg_decompress_struct cinfo,
byte[][][] output_buf, int[] output_buf_offset) {
jpeg_d_coef_controller coef = cinfo.coef;
int last_iMCU_row = cinfo.total_iMCU_rows - 1;
int block_num;
int ci, block_row, block_rows;
short[][][] buffer;
short[][] buffer_ptr;
byte[][] output_ptr;
int output_col;
jpeg_component_info compptr;
// inverse_DCT_method_ptr inverse_DCT;
/* Force some input to be done if we are getting ahead of the input. */
while (cinfo.input_scan_number < cinfo.output_scan_number
|| (cinfo.input_scan_number == cinfo.output_scan_number && cinfo.input_iMCU_row <= cinfo.output_iMCU_row)) {
if (consume_input(cinfo) == JPEG_SUSPENDED) {
return JPEG_SUSPENDED;
}
}
/* OK, output from the virtual arrays. */
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
/* Don't bother to IDCT an uninteresting component. */
if (!compptr.component_needed) {
continue;
}
/* Align the virtual buffer for this component. */
buffer = coef.whole_image[ci];
int buffer_offset = cinfo.output_iMCU_row * compptr.v_samp_factor;
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo.output_iMCU_row < last_iMCU_row) {
block_rows = compptr.v_samp_factor;
} else {
/*
* NB: can't use last_row_height here; it is
* input-side-dependent!
*/
block_rows = (compptr.height_in_blocks % compptr.v_samp_factor);
if (block_rows == 0) {
block_rows = compptr.v_samp_factor;
}
}
// inverse_DCT = cinfo.idct.inverse_DCT[ci];
output_ptr = output_buf[ci];
int output_ptr_offset = output_buf_offset[ci];
/* Loop over all DCT blocks to be processed. */
for (block_row = 0; block_row < block_rows; block_row++) {
buffer_ptr = buffer[block_row + buffer_offset];
int buffer_ptr_offset = 0;
output_col = 0;
for (block_num = 0; block_num < compptr.width_in_blocks; block_num++) {
jpeg_idct_islow(cinfo, compptr,
buffer_ptr[buffer_ptr_offset], output_ptr,
output_ptr_offset, output_col);
buffer_ptr_offset++;
output_col += compptr.DCT_scaled_size;
}
output_ptr_offset += compptr.DCT_scaled_size;
}
}
if (++(cinfo.output_iMCU_row) < cinfo.total_iMCU_rows) {
return JPEG_ROW_COMPLETED;
}
return JPEG_SCAN_COMPLETED;
}
static void post_process_data(jpeg_decompress_struct cinfo,
byte[][][] input_buf, int[] input_buf_offset,
int[] in_row_group_ctr, int in_row_groups_avail,
byte[][] output_buf, int[] out_row_ctr, int out_rows_avail) {
upsample(cinfo, input_buf, input_buf_offset, in_row_group_ctr,
in_row_groups_avail, output_buf, out_row_ctr, out_rows_avail);
}
static void set_bottom_pointers(jpeg_decompress_struct cinfo)
/*
* Change the pointer lists to duplicate the last sample row at the bottom
* of the image. whichptr indicates which xbuffer holds the final iMCU row.
* Also sets rowgroups_avail to indicate number of nondummy row groups in
* row.
*/
{
jpeg_d_main_controller main = cinfo.main;
int ci, i, rgroup, iMCUheight, rows_left;
jpeg_component_info compptr;
byte[][] xbuf;
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
/* Count sample rows in one iMCU row and in one row group */
iMCUheight = compptr.v_samp_factor * compptr.DCT_scaled_size;
rgroup = iMCUheight / cinfo.min_DCT_scaled_size;
/* Count nondummy sample rows remaining for this component */
rows_left = (compptr.downsampled_height % iMCUheight);
if (rows_left == 0) {
rows_left = iMCUheight;
}
/*
* Count nondummy row groups. Should get same answer for each
* component, so we need only do it once.
*/
if (ci == 0) {
main.rowgroups_avail = ((rows_left - 1) / rgroup + 1);
}
/*
* Duplicate the last real sample row rgroup*2 times; this pads out
* the last partial rowgroup and ensures at least one full rowgroup
* of context.
*/
xbuf = main.xbuffer[main.whichptr][ci];
int xbuf_offset = main.xbuffer_offset[main.whichptr][ci];
for (i = 0; i < rgroup * 2; i++) {
xbuf[rows_left + i + xbuf_offset] = xbuf[rows_left - 1
+ xbuf_offset];
}
}
}
static void set_wraparound_pointers(jpeg_decompress_struct cinfo)
/*
* Set up the "wraparound" pointers at top and bottom of the pointer lists.
* This changes the pointer list state from top-of-image to the normal
* state.
*/
{
jpeg_d_main_controller main = cinfo.main;
int ci, i, rgroup;
int M = cinfo.min_DCT_scaled_size;
jpeg_component_info compptr;
byte[][] xbuf0, xbuf1;
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
rgroup = (compptr.v_samp_factor * compptr.DCT_scaled_size)
/ cinfo.min_DCT_scaled_size; /*
* height of a row group of
* component
*/
xbuf0 = main.xbuffer[0][ci];
int xbuf0_offset = main.xbuffer_offset[0][ci];
xbuf1 = main.xbuffer[1][ci];
int xbuf1_offset = main.xbuffer_offset[1][ci];
for (i = 0; i < rgroup; i++) {
xbuf0[i - rgroup + xbuf0_offset] = xbuf0[rgroup * (M + 1) + i
+ xbuf0_offset];
xbuf1[i - rgroup + xbuf1_offset] = xbuf1[rgroup * (M + 1) + i
+ xbuf1_offset];
xbuf0[rgroup * (M + 2) + i + xbuf0_offset] = xbuf0[i
+ xbuf0_offset];
xbuf1[rgroup * (M + 2) + i + xbuf1_offset] = xbuf1[i
+ xbuf1_offset];
}
}
}
static void process_data_crank_post(jpeg_decompress_struct cinfo,
byte[][] output_buf, int[] out_row_ctr, int out_rows_avail) {
error();
}
static void process_data_context_main(jpeg_decompress_struct cinfo,
byte[][] output_buf, int[] out_row_ctr, int out_rows_avail) {
jpeg_d_main_controller main = cinfo.main;
/* Read input data if we haven't filled the main buffer yet */
if (!main.buffer_full) {
int result;
switch (cinfo.coef.decompress_data) {
case DECOMPRESS_DATA:
result = decompress_data(cinfo,
main.xbuffer[main.whichptr],
main.xbuffer_offset[main.whichptr]);
break;
case DECOMPRESS_SMOOTH_DATA:
result = decompress_smooth_data(cinfo,
main.xbuffer[main.whichptr],
main.xbuffer_offset[main.whichptr]);
break;
case DECOMPRESS_ONEPASS:
result = decompress_onepass(cinfo,
main.xbuffer[main.whichptr],
main.xbuffer_offset[main.whichptr]);
break;
default:
result = 0;
}
if (result == 0) {
return; /* suspension forced, can do nothing more */
}
main.buffer_full = true; /* OK, we have an iMCU row to work with */
main.iMCU_row_ctr++; /* count rows received */
}
/*
* Postprocessor typically will not swallow all the input data it is
* handed in one call (due to filling the output buffer first). Must be
* prepared to exit and restart. This switch lets us keep track of how
* far we got. Note that each case falls through to the next on
* successful completion.
*/
switch (main.context_state) {
case CTX_POSTPONED_ROW:
/*
* Call postprocessor using previously set pointers for
* postponed row
*/
post_process_data(cinfo, main.xbuffer[main.whichptr],
main.xbuffer_offset[main.whichptr], main.rowgroup_ctr,
main.rowgroups_avail, output_buf, out_row_ctr,
out_rows_avail);
if (main.rowgroup_ctr[0] < main.rowgroups_avail) {
return; /* Need to suspend */
}
main.context_state = CTX_PREPARE_FOR_IMCU;
if (out_row_ctr[0] >= out_rows_avail) {
return; /* Postprocessor exactly filled output buf */
}
/* FALLTHROUGH */
case CTX_PREPARE_FOR_IMCU:
/* Prepare to process first M-1 row groups of this iMCU row */
main.rowgroup_ctr[0] = 0;
main.rowgroups_avail = (cinfo.min_DCT_scaled_size - 1);
/*
* Check for bottom of image: if so, tweak pointers to
* "duplicate" the last sample row, and adjust rowgroups_avail
* to ignore padding rows.
*/
if (main.iMCU_row_ctr == cinfo.total_iMCU_rows) {
set_bottom_pointers(cinfo);
}
main.context_state = CTX_PROCESS_IMCU;
/* FALLTHROUGH */
case CTX_PROCESS_IMCU:
/* Call postprocessor using previously set pointers */
post_process_data(cinfo, main.xbuffer[main.whichptr],
main.xbuffer_offset[main.whichptr], main.rowgroup_ctr,
main.rowgroups_avail, output_buf, out_row_ctr,
out_rows_avail);
if (main.rowgroup_ctr[0] < main.rowgroups_avail) {
return; /* Need to suspend */
}
/*
* After the first iMCU, change wraparound pointers to normal
* state
*/
if (main.iMCU_row_ctr == 1) {
set_wraparound_pointers(cinfo);
}
/* Prepare to load new iMCU row using other xbuffer list */
main.whichptr ^= 1; /* 0=>1 or 1=>0 */
main.buffer_full = false;
/* Still need to process last row group of this iMCU row, */
/* which is saved at index M+1 of the other xbuffer */
main.rowgroup_ctr[0] = (cinfo.min_DCT_scaled_size + 1);
main.rowgroups_avail = (cinfo.min_DCT_scaled_size + 2);
main.context_state = CTX_POSTPONED_ROW;
}
}
static void process_data_simple_main(jpeg_decompress_struct cinfo,
byte[][] output_buf, int[] out_row_ctr, int out_rows_avail) {
jpeg_d_main_controller main = cinfo.main;
int rowgroups_avail;
/* Read input data if we haven't filled the main buffer yet */
if (!main.buffer_full) {
int result;
switch (cinfo.coef.decompress_data) {
case DECOMPRESS_DATA:
result = decompress_data(cinfo, main.buffer,
main.buffer_offset);
break;
case DECOMPRESS_SMOOTH_DATA:
result = decompress_smooth_data(cinfo, main.buffer,
main.buffer_offset);
break;
case DECOMPRESS_ONEPASS:
result = decompress_onepass(cinfo, main.buffer,
main.buffer_offset);
break;
default:
result = 0;
}
if (result == 0) {
return; /* suspension forced, can do nothing more */
}
main.buffer_full = true; /* OK, we have an iMCU row to work with */
}
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
rowgroups_avail = cinfo.min_DCT_scaled_size;
/*
* Note: at the bottom of the image, we may pass extra garbage row
* groups to the postprocessor. The postprocessor has to check for
* bottom of image anyway (at row resolution), so no point in us doing
* it too.
*/
/* Feed the postprocessor */
post_process_data(cinfo, main.buffer, main.buffer_offset,
main.rowgroup_ctr, rowgroups_avail, output_buf, out_row_ctr,
out_rows_avail);
/* Has postprocessor consumed all the data yet? If so, mark buffer empty */
if (main.rowgroup_ctr[0] >= rowgroups_avail) {
main.buffer_full = false;
main.rowgroup_ctr[0] = 0;
}
}
static int jpeg_read_scanlines(jpeg_decompress_struct cinfo,
byte[][] scanlines, int max_lines) {
if (cinfo.global_state != DSTATE_SCANNING) {
error();
}
// ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
if (cinfo.output_scanline >= cinfo.output_height) {
// WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
return 0;
}
/* Call progress monitor hook if present */
// if (cinfo.progress != NULL) {
// cinfo.progress.pass_counter = (long) cinfo.output_scanline;
// cinfo.progress.pass_limit = (long) cinfo.output_height;
// (*cinfo.progress.progress_monitor) ((j_common_ptr) cinfo);
// }
/* Process some data */
cinfo.row_ctr[0] = 0;
switch (cinfo.main.process_data) {
case PROCESS_DATA_SIMPLE_MAIN:
process_data_simple_main(cinfo, scanlines, cinfo.row_ctr,
max_lines);
break;
case PROCESS_DATA_CONTEXT_MAIN:
process_data_context_main(cinfo, scanlines, cinfo.row_ctr,
max_lines);
break;
case PROCESS_DATA_CRANK_POST:
process_data_crank_post(cinfo, scanlines, cinfo.row_ctr,
max_lines);
break;
default:
error();
}
cinfo.output_scanline += cinfo.row_ctr[0];
return cinfo.row_ctr[0];
}
static boolean output_pass_setup(jpeg_decompress_struct cinfo) {
if (cinfo.global_state != DSTATE_PRESCAN) {
/* First call: do pass setup */
prepare_for_output_pass(cinfo);
cinfo.output_scanline = 0;
cinfo.global_state = DSTATE_PRESCAN;
}
/* Loop over any required dummy passes */
while (cinfo.master.is_dummy_pass) {
error();
// #ifdef QUANT_2PASS_SUPPORTED
// /* Crank through the dummy pass */
// while (cinfo.output_scanline < cinfo.output_height) {
// JDIMENSION last_scanline;
// /* Call progress monitor hook if present */
// if (cinfo.progress != NULL) {
// cinfo.progress.pass_counter = (long) cinfo.output_scanline;
// cinfo.progress.pass_limit = (long) cinfo.output_height;
// (*cinfo.progress.progress_monitor) ((j_common_ptr) cinfo);
// }
// /* Process some data */
// last_scanline = cinfo.output_scanline;
// (*cinfo.main.process_data) (cinfo, (JSAMPARRAY) NULL,
// &cinfo.output_scanline, (JDIMENSION) 0);
// if (cinfo.output_scanline == last_scanline)
// return FALSE; /* No progress made, must suspend */
// }
// /* Finish up dummy pass, and set up for another one */
// (*cinfo.master.finish_output_pass) (cinfo);
// (*cinfo.master.prepare_for_output_pass) (cinfo);
// cinfo.output_scanline = 0;
// #else
// ERREXIT(cinfo, JERR_NOT_COMPILED);
// #endif /* QUANT_2PASS_SUPPORTED */
}
/*
* Ready for application to drive output pass through
* jpeg_read_scanlines or jpeg_read_raw_data.
*/
cinfo.global_state = cinfo.raw_data_out ? DSTATE_RAW_OK
: DSTATE_SCANNING;
return true;
}
static boolean get_dht(jpeg_decompress_struct cinfo)
/* Process a DHT marker */
{
int length;
byte[] bits = new byte[17];
byte[] huffval = new byte[256];
int i, index, count;
JHUFF_TBL htblptr;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
length -= 2;
while (length > 16) {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
index = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
// TRACEMS1(cinfo, 1, JTRC_DHT, index);
bits[0] = 0;
count = 0;
for (i = 1; i <= 16; i++) {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
bits[i] = cinfo.buffer[cinfo.bytes_offset++];
count += bits[i] & 0xFF;
}
length -= 1 + 16;
// TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
// bits[1], bits[2], bits[3], bits[4],
// bits[5], bits[6], bits[7], bits[8]);
// TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
// bits[9], bits[10], bits[11], bits[12],
// bits[13], bits[14], bits[15], bits[16]);
/*
* Here we just do minimal validation of the counts to avoid walking
* off the end of our table space. jdhuff.c will check more
* carefully.
*/
if (count > 256 || (count) > length)
{
error();
// ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
}
for (i = 0; i < count; i++) {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
huffval[i] = cinfo.buffer[cinfo.bytes_offset++];
}
length -= count;
if ((index & 0x10) != 0) { /* AC table definition */
index -= 0x10;
htblptr = cinfo.ac_huff_tbl_ptrs[index] = new JHUFF_TBL();
} else { /* DC table definition */
htblptr = cinfo.dc_huff_tbl_ptrs[index] = new JHUFF_TBL();
}
if (index < 0 || index >= NUM_HUFF_TBLS)
{
error();
// ERREXIT1(cinfo, JERR_DHT_INDEX, index);
}
System.arraycopy(bits, 0, htblptr.bits, 0, bits.length);
System.arraycopy(huffval, 0, htblptr.huffval, 0, huffval.length);
}
if (length != 0)
{
error();
// ERREXIT(cinfo, JERR_BAD_LENGTH);
}
return true;
}
static boolean get_dqt(jpeg_decompress_struct cinfo)
/* Process a DQT marker */
{
int length;
int n, i, prec;
int tmp;
JQUANT_TBL quant_ptr;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
length -= 2;
while (length > 0) {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
n = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
prec = n >> 4;
n &= 0x0F;
// TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);
if (n >= NUM_QUANT_TBLS)
{
error();
// ERREXIT1(cinfo, JERR_DQT_INDEX, n);
}
if (cinfo.quant_tbl_ptrs[n] == null) {
cinfo.quant_tbl_ptrs[n] = new JQUANT_TBL();
}
quant_ptr = cinfo.quant_tbl_ptrs[n];
for (i = 0; i < DCTSIZE2; i++) {
if (prec != 0) {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
tmp = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
tmp |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
} else {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
tmp = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
}
/* We convert the zigzag-order table to natural array order. */
quant_ptr.quantval[jpeg_natural_order[i]] = (short) tmp;
}
// if (cinfo.err.trace_level >= 2) {
// for (i = 0; i < DCTSIZE2; i += 8) {
// TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
// quant_ptr.quantval[i], quant_ptr.quantval[i+1],
// quant_ptr.quantval[i+2], quant_ptr.quantval[i+3],
// quant_ptr.quantval[i+4], quant_ptr.quantval[i+5],
// quant_ptr.quantval[i+6], quant_ptr.quantval[i+7]);
// }
// }
length -= (DCTSIZE2 + 1);
if (prec != 0) {
length -= DCTSIZE2;
}
}
if (length != 0)
{
error();
// ERREXIT(cinfo, JERR_BAD_LENGTH);
}
return true;
}
static boolean get_dri(jpeg_decompress_struct cinfo)
/* Process a DRI marker */
{
int length;
int tmp;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (length != 4)
{
error();
// ERREXIT(cinfo, JERR_BAD_LENGTH);
}
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
tmp = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
tmp |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
// TRACEMS1(cinfo, 1, JTRC_DRI, tmp);
cinfo.restart_interval = tmp;
return true;
}
static boolean get_dac(jpeg_decompress_struct cinfo)
/* Process a DAC marker */
{
int length;
int index, val;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
length -= 2;
while (length > 0) {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
index = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
val = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
length -= 2;
// TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
if (index < 0 || index >= (2 * NUM_ARITH_TBLS))
{
error();
// ERREXIT1(cinfo, JERR_DAC_INDEX, index);
}
if (index >= NUM_ARITH_TBLS) { /* define AC table */
cinfo.arith_ac_K[index - NUM_ARITH_TBLS] = (byte) val;
} else { /* define DC table */
cinfo.arith_dc_L[index] = (byte) (val & 0x0F);
cinfo.arith_dc_U[index] = (byte) (val >> 4);
if (cinfo.arith_dc_L[index] > cinfo.arith_dc_U[index])
{
error();
// ERREXIT1(cinfo, JERR_DAC_VALUE, val);
}
}
}
if (length != 0)
{
error();
// ERREXIT(cinfo, JERR_BAD_LENGTH);
}
return true;
}
static boolean get_sos(jpeg_decompress_struct cinfo)
/* Process a SOS marker */
{
int length;
int i, ci, n, c, cc;
jpeg_component_info compptr = null;
if (!cinfo.marker.saw_SOF)
{
error();
// ERREXIT(cinfo, JERR_SOS_NO_SOF);
}
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
n = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
// TRACEMS1(cinfo, 1, JTRC_SOS, n);
if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)
{
error();
// ERREXIT(cinfo, JERR_BAD_LENGTH);
}
cinfo.comps_in_scan = n;
/* Collect the component-spec parameters */
for (i = 0; i < n; i++) {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
cc = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
if (cc == compptr.component_id) {
break;
}
}
if (ci == cinfo.num_components)
{
error();
// ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
}
cinfo.cur_comp_info[i] = compptr;
compptr.dc_tbl_no = (c >> 4) & 15;
compptr.ac_tbl_no = (c) & 15;
// TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, compptr.dc_tbl_no,
// compptr.ac_tbl_no);
}
/* Collect the additional scan parameters Ss, Se, Ah/Al. */
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
cinfo.Ss = c;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
cinfo.Se = c;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
cinfo.Ah = (c >> 4) & 15;
cinfo.Al = (c) & 15;
// TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo.Ss, cinfo.Se, cinfo.Ah,
// cinfo.Al);
/* Prepare to scan data & restart markers */
cinfo.marker.next_restart_num = 0;
/* Count another SOS marker */
cinfo.input_scan_number++;
return true;
}
static boolean get_sof(jpeg_decompress_struct cinfo, boolean is_prog,
boolean is_arith) {
int length;
int c, ci;
cinfo.progressive_mode = is_prog;
cinfo.arith_code = is_arith;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
cinfo.data_precision = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
cinfo.image_height = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
cinfo.image_height |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
cinfo.image_width = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
cinfo.image_width |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
cinfo.num_components = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
length -= 8;
// TRACEMS4(cinfo, 1, JTRC_SOF, cinfo.unread_marker,
// (int) cinfo.image_width, (int) cinfo.image_height,
// cinfo.num_components);
if (cinfo.marker.saw_SOF)
{
error();
// ERREXIT(cinfo, JERR_SOF_DUPLICATE);
}
/*
* 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)
{
error();
// ERREXIT(cinfo, JERR_EMPTY_IMAGE);
}
if (length != (cinfo.num_components * 3))
{
error();
// ERREXIT(cinfo, JERR_BAD_LENGTH);
}
if (cinfo.comp_info == null) {
cinfo.comp_info = new jpeg_component_info[cinfo.num_components];
}
for (ci = 0; ci < cinfo.num_components; ci++) {
jpeg_component_info compptr = cinfo.comp_info[ci] = new jpeg_component_info();
compptr.component_index = ci;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
compptr.component_id = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
compptr.h_samp_factor = (c >> 4) & 15;
compptr.v_samp_factor = (c) & 15;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
compptr.quant_tbl_no = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
// TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,
// compptr.component_id, compptr.h_samp_factor,
// compptr.v_samp_factor, compptr.quant_tbl_no);
}
cinfo.marker.saw_SOF = true;
return true;
}
static void sep_upsample(jpeg_decompress_struct cinfo,
byte[][][] input_buf, int[] input_buf_offset,
int[] in_row_group_ctr, int in_row_groups_avail,
byte[][] output_buf, int[] out_row_ctr, int out_rows_avail) {
jpeg_upsampler upsample = cinfo.upsample;
int ci;
jpeg_component_info compptr;
int num_rows;
/* Fill the conversion buffer, if it's empty */
if (upsample.next_row_out >= cinfo.max_v_samp_factor) {
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
/*
* Invoke per-component upsample method. Notice we pass a
* POINTER to color_buf[ci], so that fullsize_upsample can
* change it.
*/
int offset = input_buf_offset[ci]
+ (in_row_group_ctr[0] * upsample.rowgroup_height[ci]);
switch (upsample.methods[ci]) {
case NOOP_UPSAMPLE:
noop_upsample(cinfo, compptr, input_buf[ci], offset,
upsample.color_buf, upsample.color_buf_offset,
ci);
break;
case FULLSIZE_UPSAMPLE:
fullsize_upsample(cinfo, compptr, input_buf[ci],
offset, upsample.color_buf,
upsample.color_buf_offset, ci);
break;
case H2V1_FANCY_UPSAMPLE:
h2v1_fancy_upsample(cinfo, compptr, input_buf[ci],
offset, upsample.color_buf,
upsample.color_buf_offset, ci);
break;
case H2V1_UPSAMPLE:
h2v1_upsample(cinfo, compptr, input_buf[ci], offset,
upsample.color_buf, upsample.color_buf_offset,
ci);
break;
case H2V2_FANCY_UPSAMPLE:
h2v2_fancy_upsample(cinfo, compptr, input_buf[ci],
offset, upsample.color_buf,
upsample.color_buf_offset, ci);
break;
case H2V2_UPSAMPLE:
h2v2_upsample(cinfo, compptr, input_buf[ci], offset,
upsample.color_buf, upsample.color_buf_offset,
ci);
break;
case INT_UPSAMPLE:
int_upsample(cinfo, compptr, input_buf[ci], offset,
upsample.color_buf, upsample.color_buf_offset,
ci);
break;
}
}
upsample.next_row_out = 0;
}
/* Color-convert and emit rows */
/* How many we have in the buffer: */
num_rows = (cinfo.max_v_samp_factor - upsample.next_row_out);
/*
* Not more than the distance to the end of the image. Need this test in
* case the image height is not a multiple of max_v_samp_factor:
*/
if (num_rows > upsample.rows_to_go) {
num_rows = upsample.rows_to_go;
}
/* And not more than what the client can accept: */
out_rows_avail -= out_row_ctr[0];
if (num_rows > out_rows_avail) {
num_rows = out_rows_avail;
}
switch (cinfo.cconvert.color_convert) {
case NULL_CONVERT:
null_convert(cinfo, upsample.color_buf,
upsample.color_buf_offset, upsample.next_row_out,
output_buf, out_row_ctr[0], num_rows);
break;
case GRAYSCALE_CONVERT:
grayscale_convert(cinfo, upsample.color_buf,
upsample.color_buf_offset, upsample.next_row_out,
output_buf, out_row_ctr[0], num_rows);
break;
case YCC_RGB_CONVERT:
ycc_rgb_convert(cinfo, upsample.color_buf,
upsample.color_buf_offset, upsample.next_row_out,
output_buf, out_row_ctr[0], num_rows);
break;
case GRAY_RGB_CONVERT:
gray_rgb_convert(cinfo, upsample.color_buf,
upsample.color_buf_offset, upsample.next_row_out,
output_buf, out_row_ctr[0], num_rows);
break;
case YCCK_CMYK_CONVERT:
error();
break;
}
/* Adjust counts */
out_row_ctr[0] += num_rows;
upsample.rows_to_go -= num_rows;
upsample.next_row_out += num_rows;
/* When the buffer is emptied, declare this input row group consumed */
if (upsample.next_row_out >= cinfo.max_v_samp_factor) {
in_row_group_ctr[0]++;
}
}
static void noop_upsample(jpeg_decompress_struct cinfo,
jpeg_component_info compptr, byte[][] input_data,
int input_data_offset, byte[][][] output_data_ptr,
int[] output_data_offset, int output_data_index) {
output_data_ptr[output_data_index] = null; /* safety check */
}
static void fullsize_upsample(jpeg_decompress_struct cinfo,
jpeg_component_info compptr, byte[][] input_data,
int input_data_offset, byte[][][] output_data_ptr,
int[] output_data_offset, int output_data_index) {
output_data_ptr[output_data_index] = input_data;
output_data_offset[output_data_index] = input_data_offset;
}
static void h2v1_upsample(jpeg_decompress_struct cinfo,
jpeg_component_info compptr, byte[][] input_data,
int input_data_offset, byte[][][] output_data_ptr,
int[] output_data_offset, int output_data_index) {
byte[][] output_data = output_data_ptr[output_data_index];
byte[] inptr, outptr;
byte invalue;
int outend;
int inrow;
output_data_offset[output_data_index] = 0;
for (inrow = 0; inrow < cinfo.max_v_samp_factor; inrow++) {
inptr = input_data[inrow + input_data_offset];
outptr = output_data[inrow];
int inptr_offset = 0, outptr_offset = 0;
outend = outptr_offset + cinfo.output_width;
while (outptr_offset < outend) {
invalue = inptr[inptr_offset++]; /*
* don't need GETJSAMPLE()
* here
*/
outptr[outptr_offset++] = invalue;
outptr[outptr_offset++] = invalue;
}
}
}
static void h2v2_upsample(jpeg_decompress_struct cinfo,
jpeg_component_info compptr, byte[][] input_data,
int input_data_offset, byte[][][] output_data_ptr,
int[] output_data_offset, int output_data_index) {
byte[][] output_data = output_data_ptr[output_data_index];
byte[] inptr, outptr;
byte invalue;
int outend;
int inrow, outrow;
output_data_offset[output_data_index] = 0;
inrow = outrow = 0;
while (outrow < cinfo.max_v_samp_factor) {
inptr = input_data[inrow + input_data_offset];
outptr = output_data[outrow];
int inptr_offset = 0, outptr_offset = 0;
outend = outptr_offset + cinfo.output_width;
while (outptr_offset < outend) {
invalue = inptr[inptr_offset++]; /*
* don't need GETJSAMPLE()
* here
*/
outptr[outptr_offset++] = invalue;
outptr[outptr_offset++] = invalue;
}
jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 1,
cinfo.output_width);
inrow++;
outrow += 2;
}
}
static void h2v1_fancy_upsample(jpeg_decompress_struct cinfo,
jpeg_component_info compptr, byte[][] input_data,
int input_data_offset, byte[][][] output_data_ptr,
int[] output_data_offset, int output_data_index) {
byte[][] output_data = output_data_ptr[output_data_index];
byte[] inptr, outptr;
int invalue;
int colctr;
int inrow;
output_data_offset[output_data_index] = 0;
for (inrow = 0; inrow < cinfo.max_v_samp_factor; inrow++) {
inptr = input_data[inrow + input_data_offset];
outptr = output_data[inrow];
int inptr_offset = 0, outptr_offset = 0;
/* Special case for first column */
invalue = inptr[inptr_offset++] & 0xFF;
outptr[outptr_offset++] = (byte) invalue;
outptr[outptr_offset++] = (byte) ((invalue * 3
+ (inptr[inptr_offset] & 0xFF) + 2) >> 2);
for (colctr = compptr.downsampled_width - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel */
invalue = (inptr[inptr_offset++] & 0xFF) * 3;
outptr[outptr_offset++] = (byte) ((invalue
+ (inptr[inptr_offset - 2] & 0xFF) + 1) >> 2);
outptr[outptr_offset++] = (byte) ((invalue
+ (inptr[inptr_offset] & 0xFF) + 2) >> 2);
}
/* Special case for last column */
invalue = (inptr[inptr_offset] & 0xFF);
outptr[outptr_offset++] = (byte) ((invalue * 3
+ (inptr[inptr_offset - 1] & 0xFF) + 1) >> 2);
outptr[outptr_offset++] = (byte) invalue;
}
}
static void h2v2_fancy_upsample(jpeg_decompress_struct cinfo,
jpeg_component_info compptr, byte[][] input_data,
int input_data_offset, byte[][][] output_data_ptr,
int[] output_data_offset, int output_data_index) {
byte[][] output_data = output_data_ptr[output_data_index];
byte[] inptr0, inptr1, outptr;
int thiscolsum, lastcolsum, nextcolsum;
int colctr;
int inrow, outrow, v;
output_data_offset[output_data_index] = 0;
inrow = outrow = 0;
while (outrow < cinfo.max_v_samp_factor) {
for (v = 0; v < 2; v++) {
/*
* inptr0 points to nearest input row, inptr1 points to next
* nearest
*/
inptr0 = input_data[inrow + input_data_offset];
if (v == 0) {
inptr1 = input_data[inrow - 1 + input_data_offset];
} else {
/* next nearest is row below */
inptr1 = input_data[inrow + 1 + input_data_offset];
}
outptr = output_data[outrow++];
int inptr0_offset = 0, inptr1_offset = 0, outptr_offset = 0;
/* Special case for first column */
thiscolsum = (inptr0[inptr0_offset++] & 0xFF) * 3
+ (inptr1[inptr1_offset++] & 0xFF);
nextcolsum = (inptr0[inptr0_offset++] & 0xFF) * 3
+ (inptr1[inptr1_offset++] & 0xFF);
outptr[outptr_offset++] = (byte) ((thiscolsum * 4 + 8) >> 4);
outptr[outptr_offset++] = (byte) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
lastcolsum = thiscolsum;
thiscolsum = nextcolsum;
for (colctr = compptr.downsampled_width - 2; colctr > 0; colctr--) {
/*
* General case: 3/4 * nearer pixel + 1/4 * further pixel in
* each
*/
/* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
nextcolsum = (inptr0[inptr0_offset++] & 0xFF) * 3
+ (inptr1[inptr1_offset++] & 0xFF);
outptr[outptr_offset++] = (byte) ((thiscolsum * 3
+ lastcolsum + 8) >> 4);
outptr[outptr_offset++] = (byte) ((thiscolsum * 3
+ nextcolsum + 7) >> 4);
lastcolsum = thiscolsum;
thiscolsum = nextcolsum;
}
/* Special case for last column */
outptr[outptr_offset++] = (byte) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
outptr[outptr_offset++] = (byte) ((thiscolsum * 4 + 7) >> 4);
}
inrow++;
}
}
static void int_upsample(jpeg_decompress_struct cinfo,
jpeg_component_info compptr, byte[][] input_data,
int input_data_offset, byte[][][] output_data_ptr,
int[] output_data_offset, int output_data_index) {
jpeg_upsampler upsample = cinfo.upsample;
byte[][] output_data = output_data_ptr[output_data_index];
byte[] inptr, outptr;
byte invalue;
int h;
int outend;
int h_expand, v_expand;
int inrow, outrow;
output_data_offset[output_data_index] = 0;
h_expand = upsample.h_expand[compptr.component_index];
v_expand = upsample.v_expand[compptr.component_index];
inrow = outrow = 0;
while (outrow < cinfo.max_v_samp_factor) {
/* Generate one output row with proper horizontal expansion */
inptr = input_data[inrow + input_data_offset];
int inptr_offset = 0;
outptr = output_data[outrow];
int outptr_offset = 0;
outend = outptr_offset + cinfo.output_width;
while (outptr_offset < outend) {
invalue = inptr[inptr_offset++]; /*
* don't need GETJSAMPLE()
* here
*/
for (h = h_expand; h > 0; h--) {
outptr[outptr_offset++] = invalue;
}
}
/* Generate any additional output rows by duplicating the first one */
if (v_expand > 1) {
jcopy_sample_rows(output_data, outrow, output_data, outrow + 1,
v_expand - 1, cinfo.output_width);
}
inrow++;
outrow += v_expand;
}
}
static void null_convert(jpeg_decompress_struct cinfo,
byte[][][] input_buf, int[] input_buf_offset, int input_row,
byte[][] output_buf, int output_buf_offset, int num_rows) {
byte[] inptr, outptr;
int count;
int num_components = cinfo.num_components;
int num_cols = cinfo.output_width;
int ci;
while (--num_rows >= 0) {
for (ci = 0; ci < num_components; ci++) {
inptr = input_buf[ci][input_row + input_buf_offset[0]];
outptr = output_buf[output_buf_offset];
/* BGR instead of RGB */
int offset = 0;
switch (ci) {
case 2:
offset = RGB_BLUE;
break;
case 1:
offset = RGB_GREEN;
break;
case 0:
offset = RGB_RED;
break;
}
int outptr_offset = offset, inptr_offset = 0;
for (count = num_cols; count > 0; count--) {
outptr[outptr_offset] = inptr[inptr_offset++]; /*
* needn't
* bother
* with
* GETJSAMPLE()
* here
*/
outptr_offset += num_components;
}
}
input_row++;
output_buf_offset++;
}
}
static void grayscale_convert(jpeg_decompress_struct cinfo,
byte[][][] input_buf, int[] input_buf_offset, int input_row,
byte[][] output_buf, int output_buf_offset, int num_rows) {
jcopy_sample_rows(input_buf[0], input_row + input_buf_offset[0],
output_buf, output_buf_offset, num_rows, cinfo.output_width);
}
static void gray_rgb_convert(jpeg_decompress_struct cinfo,
byte[][][] input_buf, int[] input_buf_offset, int input_row,
byte[][] output_buf, int output_buf_offset, int num_rows) {
byte[] inptr, outptr;
int col;
int num_cols = cinfo.output_width;
while (--num_rows >= 0) {
inptr = input_buf[0][input_row++ + input_buf_offset[0]];
outptr = output_buf[output_buf_offset++];
int outptr_offset = 0;
for (col = 0; col < num_cols; col++) {
/* We can dispense with GETJSAMPLE() here */
outptr[RGB_RED + outptr_offset] = outptr[RGB_GREEN
+ outptr_offset] = outptr[RGB_BLUE + outptr_offset] = inptr[col];
outptr_offset += RGB_PIXELSIZE;
}
}
}
static void ycc_rgb_convert(jpeg_decompress_struct cinfo,
byte[][][] input_buf, int[] input_buf_offset, int input_row,
byte[][] output_buf, int output_buf_offset, int num_rows) {
jpeg_color_deconverter cconvert = cinfo.cconvert;
int y, cb, cr;
byte[] outptr;
byte[] inptr0, inptr1, inptr2;
int col;
int num_cols = cinfo.output_width;
/* copy these pointers into registers if possible */
byte[] range_limit = cinfo.sample_range_limit;
int range_limit_offset = cinfo.sample_range_limit_offset;
int[] Crrtab = cconvert.Cr_r_tab;
int[] Cbbtab = cconvert.Cb_b_tab;
int[] Crgtab = cconvert.Cr_g_tab;
int[] Cbgtab = cconvert.Cb_g_tab;
// SHIFT_TEMPS
while (--num_rows >= 0) {
inptr0 = input_buf[0][input_row + input_buf_offset[0]];
inptr1 = input_buf[1][input_row + input_buf_offset[1]];
inptr2 = input_buf[2][input_row + input_buf_offset[2]];
input_row++;
outptr = output_buf[output_buf_offset++];
int outptr_offset = 0;
for (col = 0; col < num_cols; col++) {
y = (inptr0[col] & 0xFF);
cb = (inptr1[col] & 0xFF);
cr = (inptr2[col] & 0xFF);
/*
* Range-limiting is essential due to noise introduced by DCT
* losses.
*/
outptr[outptr_offset + RGB_RED] = range_limit[y + Crrtab[cr]
+ range_limit_offset];
outptr[outptr_offset + RGB_GREEN] = range_limit[y
+ ((Cbgtab[cb] + Crgtab[cr] >> SCALEBITS))
+ range_limit_offset];
outptr[outptr_offset + RGB_BLUE] = range_limit[y + Cbbtab[cb]
+ range_limit_offset];
outptr_offset += RGB_PIXELSIZE;
}
}
}
static boolean process_APPn(int n, jpeg_decompress_struct cinfo) {
if (n == 0 || n == 14) {
return get_interesting_appn(cinfo);
}
return skip_variable(cinfo);
}
static boolean process_COM(jpeg_decompress_struct cinfo) {
return skip_variable(cinfo);
}
static void skip_input_data(jpeg_decompress_struct cinfo, int num_bytes) {
if (num_bytes > 0) {
while (num_bytes > cinfo.bytes_in_buffer - cinfo.bytes_offset) {
num_bytes -= cinfo.bytes_in_buffer - cinfo.bytes_offset;
if (!fill_input_buffer(cinfo)) {
error();
/*
* note we assume that fill_input_buffer will never return
* FALSE, so suspension need not be handled.
*/
}
}
cinfo.bytes_offset += num_bytes;
}
}
static boolean skip_variable(jpeg_decompress_struct cinfo)
/* Skip over an unknown or uninteresting variable-length marker */
{
int length;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
length -= 2;
// TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo.unread_marker, (int)
// length);
if (length > 0) {
skip_input_data(cinfo, length);
}
return true;
}
static boolean get_interesting_appn(jpeg_decompress_struct cinfo)
/* Process an APP0 or APP14 marker without saving it */
{
int length;
byte[] b = new byte[APPN_DATA_LEN];
int i, numtoread;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
length -= 2;
/* get the interesting part of the marker data */
if (length >= APPN_DATA_LEN) {
numtoread = APPN_DATA_LEN;
} else if (length > 0) {
numtoread = length;
} else {
numtoread = 0;
}
for (i = 0; i < numtoread; i++) {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
b[i] = cinfo.buffer[cinfo.bytes_offset++];
}
length -= numtoread;
/* process it */
switch (cinfo.unread_marker) {
case M_APP0:
examine_app0(cinfo, b, numtoread, length);
break;
case M_APP14:
examine_app14(cinfo, b, numtoread, length);
break;
default:
/*
* can't get here unless jpeg_save_markers chooses wrong
* processor
*/
error();
// ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo.unread_marker);
break;
}
/* skip any remaining data -- could be lots */
if (length > 0) {
skip_input_data(cinfo, length);
}
return true;
}
static void examine_app0(jpeg_decompress_struct cinfo, byte[] data,
int datalen, int remaining)
/*
* Examine first few bytes from an APP0. Take appropriate action if it is a
* JFIF marker. datalen is # of bytes at data[], remaining is length of rest
* of marker data.
*/
{
int totallen = datalen + remaining;
if (datalen >= APP0_DATA_LEN && (data[0] & 0xFF) == 0x4A
&& (data[1] & 0xFF) == 0x46 && (data[2] & 0xFF) == 0x49
&& (data[3] & 0xFF) == 0x46 && (data[4] & 0xFF) == 0) {
/* Found JFIF APP0 marker: save info */
cinfo.saw_JFIF_marker = true;
cinfo.JFIF_major_version = (data[5]);
cinfo.JFIF_minor_version = (byte) (data[6] & 0xFF);
cinfo.density_unit = (byte) (data[7] & 0xFF);
cinfo.X_density = (short) (((data[8] & 0xFF) << 8) + (data[9] & 0xFF));
cinfo.Y_density = (short) (((data[10] & 0xFF) << 8) + (data[11] & 0xFF));
/*
* Check version. Major version must be 1, anything else signals an
* incompatible change. (We used to treat this as an error, but now
* it's a nonfatal warning, because some bozo at Hijaak couldn't
* read the spec.) Minor version should be 0..2, but process anyway
* if newer.
*/
if (cinfo.JFIF_major_version != 1) {
// WARNMS2(cinfo, JWRN_JFIF_MAJOR,
// cinfo.JFIF_major_version, cinfo.JFIF_minor_version);
}
/* Generate trace messages */
// TRACEMS5(cinfo, 1, JTRC_JFIF,
// cinfo.JFIF_major_version, cinfo.JFIF_minor_version,
// cinfo.X_density, cinfo.Y_density, cinfo.density_unit);
/* Validate thumbnail dimensions and issue appropriate messages */
if (((data[12] & 0xFF) | (data[13]) & 0xFF) != 0) {
// TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
// GETJOCTET(data[12]), GETJOCTET(data[13]));
}
totallen -= APP0_DATA_LEN;
if (totallen != ((data[12] & 0xFF) * (data[13] & 0xFF) * 3)) {
// TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int)
// totallen);
}
} else if (datalen >= 6 && (data[0] & 0xFF) == 0x4A
&& (data[1] & 0xFF) == 0x46 && (data[2] & 0xFF) == 0x58
&& (data[3] & 0xFF) == 0x58 && (data[4] & 0xFF) == 0) {
/* Found JFIF "JFXX" extension APP0 marker */
/*
* The library doesn't actually do anything with these, but we try
* to produce a helpful trace message.
*/
switch ((data[5]) & 0xFF) {
case 0x10:
// TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen);
break;
case 0x11:
// TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
break;
case 0x13:
// TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
break;
default:
// TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
// GETJOCTET(data[5]), (int) totallen);
break;
}
} else {
/* Start of APP0 does not match "JFIF" or "JFXX", or too short */
// TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen);
}
}
static void examine_app14(jpeg_decompress_struct cinfo, byte[] data,
int datalen, int remaining)
/*
* Examine first few bytes from an APP14. Take appropriate action if it is
* an Adobe marker. datalen is # of bytes at data[], remaining is length of
* rest of marker data.
*/
{
int /* version, flags0, flags1, */transform;
if (datalen >= APP14_DATA_LEN && (data[0] & 0xFF) == 0x41
&& (data[1] & 0xFF) == 0x64 && (data[2] & 0xFF) == 0x6F
&& (data[3] & 0xFF) == 0x62 && (data[4] & 0xFF) == 0x65) {
/* Found Adobe APP14 marker */
// version = ((data[5] & 0xFF) << 8) + (data[6] & 0xFF);
// flags0 = ((data[7] & 0xFF) << 8) + (data[8] & 0xFF);
// flags1 = ((data[9] & 0xFF) << 8) + (data[10] & 0xFF);
transform = (data[11] & 0xFF);
// TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1,
// transform);
cinfo.saw_Adobe_marker = true;
cinfo.Adobe_transform = (byte) transform;
} else {
/* Start of APP14 does not match "Adobe", or too short */
// TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
}
}
static boolean get_soi(jpeg_decompress_struct cinfo) /*
* Process an SOI
* marker
*/{
int i;
// TRACEMS(cinfo, 1, JTRC_SOI);
if (cinfo.marker.saw_SOI)
{
error();
// ERREXIT(cinfo, JERR_SOI_DUPLICATE);
}
/* Reset all parameters that are defined to be reset by SOI */
for (i = 0; i < NUM_ARITH_TBLS; i++) {
cinfo.arith_dc_L[i] = 0;
cinfo.arith_dc_U[i] = 1;
cinfo.arith_ac_K[i] = 5;
}
cinfo.restart_interval = 0;
/* Set initial assumptions for colorspace etc */
cinfo.jpeg_color_space = JCS_UNKNOWN;
cinfo.CCIR601_sampling = false; /* Assume non-CCIR sampling??? */
cinfo.saw_JFIF_marker = false;
cinfo.JFIF_major_version = 1; /* set default JFIF APP0 values */
cinfo.JFIF_minor_version = 1;
cinfo.density_unit = 0;
cinfo.X_density = 1;
cinfo.Y_density = 1;
cinfo.saw_Adobe_marker = false;
cinfo.Adobe_transform = 0;
cinfo.marker.saw_SOI = true;
return true;
}
static void jinit_input_controller(jpeg_decompress_struct cinfo) {
/*
* Initialize state: can't use reset_input_controller since we don't
* want to try to reset other modules yet.
*/
jpeg_input_controller inputctl = cinfo.inputctl = new jpeg_input_controller();
inputctl.has_multiple_scans = false; /* "unknown" would be better */
inputctl.eoi_reached = false;
inputctl.inheaders = true;
}
static void reset_marker_reader(jpeg_decompress_struct cinfo) {
jpeg_marker_reader marker = cinfo.marker;
cinfo.comp_info = null; /* until allocated by get_sof */
cinfo.input_scan_number = 0; /* no SOS seen yet */
cinfo.unread_marker = 0; /* no pending marker */
marker.saw_SOI = false; /* set internal state too */
marker.saw_SOF = false;
marker.discarded_bytes = 0;
// marker.cur_marker = null;
}
static void reset_input_controller(jpeg_decompress_struct cinfo) {
jpeg_input_controller inputctl = cinfo.inputctl;
inputctl.has_multiple_scans = false; /* "unknown" would be better */
inputctl.eoi_reached = false;
inputctl.inheaders = true;
/* Reset other modules */
reset_marker_reader(cinfo);
/*
* Reset progression state -- would be cleaner if entropy decoder did
* this
*/
cinfo.coef_bits = null;
}
static void finish_output_pass(jpeg_decompress_struct cinfo) {
jpeg_decomp_master master = cinfo.master;
if (cinfo.quantize_colors) {
error(JPEGError.ERROR_NOT_IMPLEMENTED);
// (*cinfo.cquantize.finish_pass) (cinfo);
}
master.pass_number++;
}
static void jpeg_destroy(jpeg_decompress_struct cinfo) {
/* We need only tell the memory manager to release everything. */
/* NB: mem pointer is NULL if memory mgr failed to initialize. */
// if (cinfo.mem != NULL)
// (*cinfo.mem.self_destruct) (cinfo);
// cinfo.mem = NULL; /* be safe if jpeg_destroy is called twice */
cinfo.global_state = 0; /* mark it destroyed */
}
static void jpeg_destroy_decompress(jpeg_decompress_struct cinfo) {
jpeg_destroy(cinfo); /* use common routine */
}
static boolean jpeg_input_complete(jpeg_decompress_struct cinfo) {
/* Check for valid jpeg object */
if (cinfo.global_state < DSTATE_START
|| cinfo.global_state > DSTATE_STOPPING) {
error();
}
// ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
return cinfo.inputctl.eoi_reached;
}
static boolean jpeg_start_output(jpeg_decompress_struct cinfo,
int scan_number) {
if (cinfo.global_state != DSTATE_BUFIMAGE
&& cinfo.global_state != DSTATE_PRESCAN) {
error();
}
// ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
/* Limit scan number to valid range */
if (scan_number <= 0) {
scan_number = 1;
}
if (cinfo.inputctl.eoi_reached && scan_number > cinfo.input_scan_number) {
scan_number = cinfo.input_scan_number;
}
cinfo.output_scan_number = scan_number;
/* Perform any dummy output passes, and set up for the real pass */
return output_pass_setup(cinfo);
}
static boolean jpeg_finish_output(jpeg_decompress_struct cinfo) {
if ((cinfo.global_state == DSTATE_SCANNING || cinfo.global_state == DSTATE_RAW_OK)
&& cinfo.buffered_image) {
/* Terminate this pass. */
/* We do not require the whole pass to have been completed. */
finish_output_pass(cinfo);
cinfo.global_state = DSTATE_BUFPOST;
} else if (cinfo.global_state != DSTATE_BUFPOST) {
/* BUFPOST = repeat call after a suspension, anything else is error */
error();
// ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
}
/* Read markers looking for SOS or EOI */
while (cinfo.input_scan_number <= cinfo.output_scan_number
&& !cinfo.inputctl.eoi_reached) {
if (consume_input(cinfo) == JPEG_SUSPENDED) {
return false; /* Suspend, come back later */
}
}
cinfo.global_state = DSTATE_BUFIMAGE;
return true;
}
static boolean jpeg_finish_decompress(jpeg_decompress_struct cinfo) {
if ((cinfo.global_state == DSTATE_SCANNING || cinfo.global_state == DSTATE_RAW_OK)
&& !cinfo.buffered_image) {
/* Terminate final pass of non-buffered mode */
if (cinfo.output_scanline < cinfo.output_height) {
error();
}
// ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
finish_output_pass(cinfo);
cinfo.global_state = DSTATE_STOPPING;
} else if (cinfo.global_state == DSTATE_BUFIMAGE) {
/* Finishing after a buffered-image operation */
cinfo.global_state = DSTATE_STOPPING;
} else if (cinfo.global_state != DSTATE_STOPPING) {
/* STOPPING = repeat call after a suspension, anything else is error */
error();
// ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
}
/* Read until EOI */
while (!cinfo.inputctl.eoi_reached) {
if (consume_input(cinfo) == JPEG_SUSPENDED) {
return false; /* Suspend, come back later */
}
}
/* Do final cleanup */
// (*cinfo.src.term_source) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
jpeg_abort(cinfo);
return true;
}
static int jpeg_read_header(jpeg_decompress_struct cinfo,
boolean require_image) {
int retcode;
if (cinfo.global_state != DSTATE_START
&& cinfo.global_state != DSTATE_INHEADER)
{
error();
// ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
}
retcode = jpeg_consume_input(cinfo);
switch (retcode) {
case JPEG_REACHED_SOS:
retcode = JPEG_HEADER_OK;
break;
case JPEG_REACHED_EOI:
if (require_image) {
error();
}
// ERREXIT(cinfo, JERR_NO_IMAGE);
/*
* Reset to start state; it would be safer to require the
* application to call jpeg_abort, but we can't change it now
* for compatibility reasons. A side effect is to free any
* temporary memory (there shouldn't be any).
*/
jpeg_abort(cinfo); /* sets state = DSTATE_START */
retcode = JPEG_HEADER_TABLES_ONLY;
break;
case JPEG_SUSPENDED:
/* no work */
break;
}
return retcode;
}
static int dummy_consume_data(jpeg_decompress_struct cinfo) {
return JPEG_SUSPENDED; /* Always indicate nothing was done */
}
static int consume_data(jpeg_decompress_struct cinfo) {
jpeg_d_coef_controller coef = cinfo.coef;
int MCU_col_num; /* index of current MCU within row */
int blkn, ci, xindex, yindex, yoffset;
int start_col;
// short[][][][] buffer = new short[MAX_COMPS_IN_SCAN][][][];
short[][] buffer_ptr;
jpeg_component_info compptr;
// /* Align the virtual buffers for the components used in this scan. */
// for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
// compptr = cinfo.cur_comp_info[ci];
// buffer[ci] = coef.whole_image[compptr.component_index];
// /* Note: entropy decoder expects buffer to be zeroed,
// * but this is handled automatically by the memory manager
// * because we requested a pre-zeroed array.
// */
// }
/* Loop to process one whole iMCU row */
for (yoffset = coef.MCU_vert_offset; yoffset < coef.MCU_rows_per_iMCU_row; yoffset++) {
for (MCU_col_num = coef.MCU_ctr; MCU_col_num < cinfo.MCUs_per_row; MCU_col_num++) {
/*
* Construct list of pointers to DCT blocks belonging to this
* MCU
*/
blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
compptr = cinfo.cur_comp_info[ci];
start_col = MCU_col_num * compptr.MCU_width;
for (yindex = 0; yindex < compptr.MCU_height; yindex++) {
// buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
buffer_ptr = coef.whole_image[compptr.component_index][yindex
+ yoffset
+ cinfo.input_iMCU_row
* compptr.v_samp_factor];
int buffer_ptr_offset = start_col;
for (xindex = 0; xindex < compptr.MCU_width; xindex++) {
coef.MCU_buffer[blkn++] = buffer_ptr[buffer_ptr_offset++];
}
}
}
/* Try to fetch the MCU. */
if (!cinfo.entropy.decode_mcu(cinfo, coef.MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef.MCU_vert_offset = yoffset;
coef.MCU_ctr = MCU_col_num;
return JPEG_SUSPENDED;
}
}
/* Completed an MCU row, but perhaps not an iMCU row */
coef.MCU_ctr = 0;
}
/* Completed the iMCU row, advance counters for next one */
if (++(cinfo.input_iMCU_row) < cinfo.total_iMCU_rows) {
coef.start_iMCU_row(cinfo);
return JPEG_ROW_COMPLETED;
}
/* Completed the scan */
finish_input_pass(cinfo);
return JPEG_SCAN_COMPLETED;
}
static int consume_input(jpeg_decompress_struct cinfo) {
switch (cinfo.inputctl.consume_input) {
case COEF_CONSUME_INPUT:
switch (cinfo.coef.consume_data) {
case CONSUME_DATA:
return consume_data(cinfo);
case DUMMY_CONSUME_DATA:
return dummy_consume_data(cinfo);
default:
error();
}
break;
case INPUT_CONSUME_INPUT:
return consume_markers(cinfo);
default:
error();
}
return 0;
}
static boolean fill_input_buffer(jpeg_decompress_struct cinfo) {
try {
InputStream inputStream = cinfo.inputStream;
int nbytes = inputStream.read(cinfo.buffer);
if (nbytes <= 0) {
if (cinfo.start_of_file) {
error();
}
// ERREXIT(cinfo, JERR_INPUT_EMPTY);
// WARNMS(cinfo, JWRN_JPEG_EOF);
/* Insert a fake EOI marker */
cinfo.buffer[0] = (byte) 0xFF;
cinfo.buffer[1] = (byte) M_EOI;
nbytes = 2;
}
cinfo.bytes_in_buffer = nbytes;
cinfo.bytes_offset = 0;
cinfo.start_of_file = false;
} catch (IOException e) {
error(JPEGError.ERROR_IO);
return false;
}
return true;
}
static boolean first_marker(jpeg_decompress_struct cinfo) {
/* Like next_marker, but used to obtain the initial SOI marker. */
/*
* For this marker, we do not allow preceding garbage or fill;
* otherwise, we might well scan an entire input file before realizing
* it ain't JPEG. If an application wants to process non-JFIF files, it
* must seek to the SOI before calling the JPEG library.
*/
int c, c2;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c2 = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
if (c != 0xFF || c2 != M_SOI)
{
error();
// ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
}
cinfo.unread_marker = c2;
return true;
}
static boolean next_marker(jpeg_decompress_struct cinfo) {
int c;
for (;;) {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
/*
* Skip any non-FF bytes. This may look a bit inefficient, but it
* will not occur in a valid file. We sync after each discarded byte
* so that a suspending data source can discard the byte from its
* buffer.
*/
while (c != 0xFF) {
cinfo.marker.discarded_bytes++;
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
}
/*
* This loop swallows any duplicate FF bytes. Extra FFs are legal as
* pad bytes, so don't count them in discarded_bytes. We assume
* there will not be so many consecutive FF bytes as to overflow a
* suspending data source's input buffer.
*/
do {
if (cinfo.bytes_offset == cinfo.bytes_in_buffer) {
fill_input_buffer(cinfo);
}
c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
} while (c == 0xFF);
if (c != 0) {
break; /* found a valid marker, exit loop */
}
/*
* Reach here if we found a stuffed-zero data sequence (FF/00).
* Discard it and loop back to try again.
*/
cinfo.marker.discarded_bytes += 2;
}
if (cinfo.marker.discarded_bytes != 0) {
// WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA,
// cinfo.marker.discarded_bytes, c);
cinfo.marker.discarded_bytes = 0;
}
cinfo.unread_marker = c;
return true;
}
static int read_markers(jpeg_decompress_struct cinfo) {
/* Outer loop repeats once for each marker. */
for (;;) {
/* Collect the marker proper, unless we already did. */
/*
* NB: first_marker() enforces the requirement that SOI appear
* first.
*/
if (cinfo.unread_marker == 0) {
if (!cinfo.marker.saw_SOI) {
if (!first_marker(cinfo)) {
return JPEG_SUSPENDED;
}
} else {
if (!next_marker(cinfo)) {
return JPEG_SUSPENDED;
}
}
}
/*
* At this point cinfo.unread_marker contains the marker code and
* the input point is just past the marker proper, but before any
* parameters. A suspension will cause us to return with this state
* still true.
*/
switch (cinfo.unread_marker) {
case M_SOI:
if (!get_soi(cinfo)) {
return JPEG_SUSPENDED;
}
break;
case M_SOF0: /* Baseline */
case M_SOF1: /* Extended sequential, Huffman */
if (!get_sof(cinfo, false, false)) {
return JPEG_SUSPENDED;
}
break;
case M_SOF2: /* Progressive, Huffman */
if (!get_sof(cinfo, true, false)) {
return JPEG_SUSPENDED;
}
break;
case M_SOF9: /* Extended sequential, arithmetic */
if (!get_sof(cinfo, false, true)) {
return JPEG_SUSPENDED;
}
break;
case M_SOF10: /* Progressive, arithmetic */
if (!get_sof(cinfo, true, true)) {
return JPEG_SUSPENDED;
}
break;
/* Currently unsupported SOFn types */
case M_SOF3: /* Lossless, Huffman */
case M_SOF5: /* Differential sequential, Huffman */
case M_SOF6: /* Differential progressive, Huffman */
case M_SOF7: /* Differential lossless, Huffman */
case M_JPG: /* Reserved for JPEG extensions */
case M_SOF11: /* Lossless, arithmetic */
case M_SOF13: /* Differential sequential, arithmetic */
case M_SOF14: /* Differential progressive, arithmetic */
case M_SOF15: /* Differential lossless, arithmetic */
error();
// ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED,
// cinfo.unread_marker);
break;
case M_SOS:
if (!get_sos(cinfo)) {
return JPEG_SUSPENDED;
}
cinfo.unread_marker = 0; /* processed the marker */
return JPEG_REACHED_SOS;
case M_EOI:
// TRACEMS(cinfo, 1, JTRC_EOI);
cinfo.unread_marker = 0; /* processed the marker */
return JPEG_REACHED_EOI;
case M_DAC:
if (!get_dac(cinfo)) {
return JPEG_SUSPENDED;
}
break;
case M_DHT:
if (!get_dht(cinfo)) {
return JPEG_SUSPENDED;
}
break;
case M_DQT:
if (!get_dqt(cinfo)) {
return JPEG_SUSPENDED;
}
break;
case M_DRI:
if (!get_dri(cinfo)) {
return JPEG_SUSPENDED;
}
break;
case M_APP0:
case M_APP1:
case M_APP2:
case M_APP3:
case M_APP4:
case M_APP5:
case M_APP6:
case M_APP7:
case M_APP8:
case M_APP9:
case M_APP10:
case M_APP11:
case M_APP12:
case M_APP13:
case M_APP14:
case M_APP15:
if (!process_APPn(cinfo.unread_marker - M_APP0, cinfo)) {
return JPEG_SUSPENDED;
}
break;
case M_COM:
if (!process_COM(cinfo)) {
return JPEG_SUSPENDED;
}
break;
case M_RST0: /* these are all parameterless */
case M_RST1:
case M_RST2:
case M_RST3:
case M_RST4:
case M_RST5:
case M_RST6:
case M_RST7:
case M_TEM:
// TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER,
// cinfo.unread_marker);
break;
case M_DNL: /* Ignore DNL ... perhaps the wrong thing */
if (!skip_variable(cinfo)) {
return JPEG_SUSPENDED;
}
break;
default: /* must be DHP, EXP, JPGn, or RESn */
/*
* For now, we treat the reserved markers as fatal errors
* since they are likely to be used to signal incompatible
* JPEG Part 3 extensions. Once the JPEG 3 version-number
* marker is well defined, this code ought to change!
*/
error();
// ERREXIT1(cinfo, JERR_UNKNOWN_MARKER,
// cinfo.unread_marker);
break;
}
/* Successfully processed marker, so reset state variable */
cinfo.unread_marker = 0;
} /* end loop */
}
static long jdiv_round_up(long a, long b)
/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
/* Assumes a >= 0, b > 0 */
{
return (a + b - 1) / b;
}
static void initial_setup(jpeg_decompress_struct cinfo)
/* Called once, when first SOS marker is reached */
{
int ci;
jpeg_component_info compptr;
/* Make sure image isn't bigger than I can handle */
if (cinfo.image_height > JPEG_MAX_DIMENSION
|| cinfo.image_width > JPEG_MAX_DIMENSION)
{
error();
// ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)
// JPEG_MAX_DIMENSION);
}
/* For now, precision must match compiled-in value... */
if (cinfo.data_precision != BITS_IN_JSAMPLE)
{
error(" [data precision=" + cinfo.data_precision + "]");
// ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo.data_precision);
}
/* Check that number of components won't exceed internal array sizes */
if (cinfo.num_components > MAX_COMPONENTS)
{
error();
// ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo.num_components,
// MAX_COMPONENTS);
}
/* Compute maximum sampling factors; check factor validity */
cinfo.max_h_samp_factor = 1;
cinfo.max_v_samp_factor = 1;
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
if (compptr.h_samp_factor <= 0
|| compptr.h_samp_factor > MAX_SAMP_FACTOR
|| compptr.v_samp_factor <= 0
|| compptr.v_samp_factor > MAX_SAMP_FACTOR) {
error();
}
// ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo.max_h_samp_factor = Math.max(cinfo.max_h_samp_factor,
compptr.h_samp_factor);
cinfo.max_v_samp_factor = Math.max(cinfo.max_v_samp_factor,
compptr.v_samp_factor);
}
/*
* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. In
* the full decompressor, this will be overridden by jdmaster.c; but in
* the transcoder, jdmaster.c is not used, so we must do it here.
*/
cinfo.min_DCT_scaled_size = DCTSIZE;
/* Compute dimensions of components */
for (ci = 0; ci < cinfo.num_components; ci++) {
compptr = cinfo.comp_info[ci];
compptr.DCT_scaled_size = DCTSIZE;
/* Size in DCT blocks */
compptr.width_in_blocks = (int) jdiv_round_up(
(long) cinfo.image_width * (long) compptr.h_samp_factor,
(cinfo.max_h_samp_factor * DCTSIZE));
compptr.height_in_blocks = (int) jdiv_round_up(
(long) cinfo.image_height * (long) compptr.v_samp_factor,
(cinfo.max_v_samp_factor * DCTSIZE));
/*
* downsampled_width and downsampled_height will also be overridden
* by jdmaster.c if we are doing full decompression. The transcoder
* library doesn't use these values, but the calling application
* might.
*/
/* Size in samples */
compptr.downsampled_width = (int) jdiv_round_up(
(long) cinfo.image_width * (long) compptr.h_samp_factor,
cinfo.max_h_samp_factor);
compptr.downsampled_height = (int) jdiv_round_up(
(long) cinfo.image_height * (long) compptr.v_samp_factor,
cinfo.max_v_samp_factor);
/* Mark component needed, until color conversion says otherwise */
compptr.component_needed = true;
/* Mark no quantization table yet saved for component */
compptr.quant_table = null;
}
/* Compute number of fully interleaved MCU rows. */
cinfo.total_iMCU_rows = (int) jdiv_round_up(cinfo.image_height,
(cinfo.max_v_samp_factor * DCTSIZE));
/* Decide whether file contains multiple scans */
if (cinfo.comps_in_scan < cinfo.num_components
|| cinfo.progressive_mode) {
cinfo.inputctl.has_multiple_scans = true;
} else {
cinfo.inputctl.has_multiple_scans = false;
}
}
static void per_scan_setup(jpeg_decompress_struct cinfo)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo.comps_in_scan and cinfo.cur_comp_info[] were set from SOS marker */
{
int ci, mcublks, tmp = 0;
jpeg_component_info compptr;
if (cinfo.comps_in_scan == 1) {
/* Noninterleaved (single-component) scan */
compptr = cinfo.cur_comp_info[0];
/* Overall image size in MCUs */
cinfo.MCUs_per_row = compptr.width_in_blocks;
cinfo.MCU_rows_in_scan = compptr.height_in_blocks;
/* For noninterleaved scan, always one block per MCU */
compptr.MCU_width = 1;
compptr.MCU_height = 1;
compptr.MCU_blocks = 1;
compptr.MCU_sample_width = compptr.DCT_scaled_size;
compptr.last_col_width = 1;
/*
* For noninterleaved scans, it is convenient to define
* last_row_height as the number of block rows present in the last
* iMCU row.
*/
tmp = (compptr.height_in_blocks % compptr.v_samp_factor);
if (tmp == 0) {
tmp = compptr.v_samp_factor;
}
compptr.last_row_height = tmp;
/* Prepare array describing MCU composition */
cinfo.blocks_in_MCU = 1;
cinfo.MCU_membership[0] = 0;
} else {
/* Interleaved (multi-component) scan */
if (cinfo.comps_in_scan <= 0
|| cinfo.comps_in_scan > MAX_COMPS_IN_SCAN)
{
error();
// ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo.comps_in_scan,
// MAX_COMPS_IN_SCAN);
}
/* Overall image size in MCUs */
cinfo.MCUs_per_row = (int) jdiv_round_up(cinfo.image_width,
(cinfo.max_h_samp_factor * DCTSIZE));
cinfo.MCU_rows_in_scan = (int) jdiv_round_up(cinfo.image_height,
(cinfo.max_v_samp_factor * DCTSIZE));
cinfo.blocks_in_MCU = 0;
for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
compptr = cinfo.cur_comp_info[ci];
/* Sampling factors give # of blocks of component in each MCU */
compptr.MCU_width = compptr.h_samp_factor;
compptr.MCU_height = compptr.v_samp_factor;
compptr.MCU_blocks = compptr.MCU_width * compptr.MCU_height;
compptr.MCU_sample_width = compptr.MCU_width
* compptr.DCT_scaled_size;
/* Figure number of non-dummy blocks in last MCU column & row */
tmp = (compptr.width_in_blocks % compptr.MCU_width);
if (tmp == 0) {
tmp = compptr.MCU_width;
}
compptr.last_col_width = tmp;
tmp = (compptr.height_in_blocks % compptr.MCU_height);
if (tmp == 0) {
tmp = compptr.MCU_height;
}
compptr.last_row_height = tmp;
/* Prepare array describing MCU composition */
mcublks = compptr.MCU_blocks;
if (cinfo.blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) {
error();
}
// ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
while (mcublks-- > 0) {
cinfo.MCU_membership[cinfo.blocks_in_MCU++] = ci;
}
}
}
}
static void latch_quant_tables(jpeg_decompress_struct cinfo) {
int ci, qtblno;
jpeg_component_info compptr;
JQUANT_TBL qtbl;
for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
compptr = cinfo.cur_comp_info[ci];
/* No work if we already saved Q-table for this component */
if (compptr.quant_table != null) {
continue;
}
/* Make sure specified quantization table is present */
qtblno = compptr.quant_tbl_no;
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS
|| cinfo.quant_tbl_ptrs[qtblno] == null) {
error();
}
// ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
/* OK, save away the quantization table */
qtbl = new JQUANT_TBL();
System.arraycopy(cinfo.quant_tbl_ptrs[qtblno].quantval, 0,
qtbl.quantval, 0, qtbl.quantval.length);
qtbl.sent_table = cinfo.quant_tbl_ptrs[qtblno].sent_table;
compptr.quant_table = qtbl;
}
}
static void jpeg_make_d_derived_tbl(jpeg_decompress_struct cinfo,
boolean isDC, int tblno, d_derived_tbl dtbl) {
JHUFF_TBL htbl;
int p, i = 0, l, si, numsymbols;
int lookbits, ctr;
byte[] huffsize = new byte[257];
int[] huffcode = new int[257];
int code;
/*
* Note that huffsize[] and huffcode[] are filled in code-length order,
* paralleling the order of the symbols themselves in htbl.huffval[].
*/
/* Find the input Huffman table */
if (tblno < 0 || tblno >= NUM_HUFF_TBLS) {
error();
}
// ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
htbl = isDC ? cinfo.dc_huff_tbl_ptrs[tblno]
: cinfo.ac_huff_tbl_ptrs[tblno];
if (htbl == null)
{
error();
// ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
}
/* Allocate a workspace if we haven't already done so. */
dtbl.pub = htbl; /* fill in back link */
/* Figure C.1: make table of Huffman code length for each symbol */
p = 0;
for (l = 1; l <= 16; l++) {
i = htbl.bits[l] & 0xFF;
if (i < 0 || p + i > 256) {
error();
}
// ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
while (i-- != 0) {
huffsize[p++] = (byte) l;
}
}
huffsize[p] = 0;
numsymbols = p;
/* Figure C.2: generate the codes themselves */
/* We also validate that the counts represent a legal Huffman code tree. */
code = 0;
si = huffsize[0];
p = 0;
while ((huffsize[p]) != 0) {
while ((huffsize[p]) == si) {
huffcode[p++] = code;
code++;
}
/*
* code is now 1 more than the last code used for codelength si; but
* it must still fit in si bits, since no code is allowed to be all
* ones.
*/
if ((code) >= ((1) << si)) {
error();
}
// ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
code <<= 1;
si++;
}
/* Figure F.15: generate decoding tables for bit-sequential decoding */
p = 0;
for (l = 1; l <= 16; l++) {
if ((htbl.bits[l] & 0xFF) != 0) {
/*
* valoffset[l] = huffval[] index of 1st symbol of code length
* l, minus the minimum code of length l
*/
dtbl.valoffset[l] = p - huffcode[p];
p += (htbl.bits[l] & 0xFF);
dtbl.maxcode[l] = huffcode[p - 1]; /* maximum code of length l */
} else {
dtbl.maxcode[l] = -1; /* -1 if no codes of this length */
}
}
dtbl.maxcode[17] = 0xFFFFF; /* ensures jpeg_huff_decode terminates */
/*
* Compute lookahead tables to speed up decoding. First we set all the
* table entries to 0, indicating "too long"; then we iterate through
* the Huffman codes that are short enough and fill in all the entries
* that correspond to bit sequences starting with that code.
*/
for (int j = 0; j < dtbl.look_nbits.length; j++) {
dtbl.look_nbits[j] = 0;
}
p = 0;
for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
for (i = 1; i <= (htbl.bits[l] & 0xFF); i++, p++) {
/*
* l = current code's length, p = its index in huffcode[] &
* huffval[].
*/
/*
* Generate left-justified code followed by all possible bit
* sequences
*/
lookbits = huffcode[p] << (HUFF_LOOKAHEAD - l);
for (ctr = 1 << (HUFF_LOOKAHEAD - l); ctr > 0; ctr--) {
dtbl.look_nbits[lookbits] = l;
dtbl.look_sym[lookbits] = htbl.huffval[p];
lookbits++;
}
}
}
/*
* Validate symbols as being reasonable. For AC tables, we make no
* check, but accept all byte values 0..255. For DC tables, we require
* the symbols to be in range 0..15. (Tighter bounds could be applied
* depending on the data depth and mode, but this is sufficient to
* ensure safe decoding.)
*/
if (isDC) {
for (i = 0; i < numsymbols; i++) {
int sym = htbl.huffval[i] & 0xFF;
if (sym < 0 || sym > 15)
{
error();
// ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
}
}
}
}
static void start_input_pass(jpeg_decompress_struct cinfo) {
per_scan_setup(cinfo);
latch_quant_tables(cinfo);
cinfo.entropy.start_pass(cinfo);
cinfo.coef.start_input_pass(cinfo);
cinfo.inputctl.consume_input = COEF_CONSUME_INPUT;
}
static void finish_input_pass(jpeg_decompress_struct cinfo) {
cinfo.inputctl.consume_input = INPUT_CONSUME_INPUT;
}
static int consume_markers(jpeg_decompress_struct cinfo) {
jpeg_input_controller inputctl = cinfo.inputctl;
int val;
if (inputctl.eoi_reached) {
return JPEG_REACHED_EOI;
}
val = read_markers(cinfo);
switch (val) {
case JPEG_REACHED_SOS: /* Found SOS */
if (inputctl.inheaders) { /* 1st SOS */
initial_setup(cinfo);
inputctl.inheaders = false;
/*
* Note: start_input_pass must be called by jdmaster.c
* before any more input can be consumed. jdapimin.c is
* responsible for enforcing this sequencing.
*/
} else { /* 2nd or later SOS marker */
if (!inputctl.has_multiple_scans) {
error();
}
// ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't
// expecting this! */
start_input_pass(cinfo);
}
break;
case JPEG_REACHED_EOI: /* Found EOI */
inputctl.eoi_reached = true;
if (inputctl.inheaders) { /*
* Tables-only datastream,
* apparently
*/
if (cinfo.marker.saw_SOF)
{
error();
// ERREXIT(cinfo, JERR_SOF_NO_SOS);
}
} else {
/*
* Prevent infinite loop in coef ctlr's decompress_data
* routine if user set output_scan_number larger than number
* of scans.
*/
if (cinfo.output_scan_number > cinfo.input_scan_number) {
cinfo.output_scan_number = cinfo.input_scan_number;
}
}
break;
case JPEG_SUSPENDED:
break;
}
return val;
}
static void default_decompress_parms(jpeg_decompress_struct cinfo) {
/* Guess the input colorspace, and set output colorspace accordingly. */
/* (Wish JPEG committee had provided a real way to specify this...) */
/* Note application may override our guesses. */
switch (cinfo.num_components) {
case 1:
cinfo.jpeg_color_space = JCS_GRAYSCALE;
cinfo.out_color_space = JCS_GRAYSCALE;
break;
case 3:
if (cinfo.saw_JFIF_marker) {
cinfo.jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
} else if (cinfo.saw_Adobe_marker) {
switch (cinfo.Adobe_transform) {
case 0:
cinfo.jpeg_color_space = JCS_RGB;
break;
case 1:
cinfo.jpeg_color_space = JCS_YCbCr;
break;
default:
// WARNMS1(cinfo, JWRN_ADOBE_XFORM,
// cinfo.Adobe_transform);
cinfo.jpeg_color_space = JCS_YCbCr; /*
* assume it's
* YCbCr
*/
break;
}
} else {
/*
* Saw no special markers, try to guess from the component
* IDs
*/
int cid0 = cinfo.comp_info[0].component_id;
int cid1 = cinfo.comp_info[1].component_id;
int cid2 = cinfo.comp_info[2].component_id;
if (cid0 == 1 && cid1 == 2 && cid2 == 3) {
cinfo.jpeg_color_space = JCS_YCbCr; /*
* assume JFIF w/out
* marker
*/
} else if (cid0 == 82 && cid1 == 71 && cid2 == 66) {
cinfo.jpeg_color_space = JCS_RGB; /*
* ASCII 'R', 'G',
* 'B'
*/
} else {
// TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1,
// cid2);
cinfo.jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
}
}
/* Always guess RGB is proper output colorspace. */
cinfo.out_color_space = JCS_RGB;
break;
case 4:
if (cinfo.saw_Adobe_marker) {
switch (cinfo.Adobe_transform) {
case 0:
cinfo.jpeg_color_space = JCS_CMYK;
break;
case 2:
cinfo.jpeg_color_space = JCS_YCCK;
break;
default:
// WARNMS1(cinfo, JWRN_ADOBE_XFORM,
// cinfo.Adobe_transform);
cinfo.jpeg_color_space = JCS_YCCK; /*
* assume it's
* YCCK
*/
break;
}
} else {
/* No special markers, assume straight CMYK. */
cinfo.jpeg_color_space = JCS_CMYK;
}
cinfo.out_color_space = JCS_CMYK;
break;
default:
cinfo.jpeg_color_space = JCS_UNKNOWN;
cinfo.out_color_space = JCS_UNKNOWN;
break;
}
/* Set defaults for other decompression parameters. */
cinfo.scale_num = 1; /* 1:1 scaling */
cinfo.scale_denom = 1;
cinfo.output_gamma = 1.0;
cinfo.buffered_image = false;
cinfo.raw_data_out = false;
cinfo.dct_method = JDCT_DEFAULT;
cinfo.do_fancy_upsampling = true;
cinfo.do_block_smoothing = true;
cinfo.quantize_colors = false;
/* We set these in case application only sets quantize_colors. */
cinfo.dither_mode = JDITHER_FS;
cinfo.two_pass_quantize = true;
cinfo.desired_number_of_colors = 256;
cinfo.colormap = null;
/* Initialize for no mode change in buffered-image mode. */
cinfo.enable_1pass_quant = false;
cinfo.enable_external_quant = false;
cinfo.enable_2pass_quant = false;
}
static void init_source(jpeg_decompress_struct cinfo) {
cinfo.buffer = new byte[INPUT_BUFFER_SIZE];
cinfo.bytes_in_buffer = 0;
cinfo.bytes_offset = 0;
cinfo.start_of_file = true;
}
static int jpeg_consume_input(jpeg_decompress_struct cinfo) {
int retcode = JPEG_SUSPENDED;
/* NB: every possible DSTATE value should be listed in this switch */
switch (cinfo.global_state) {
case DSTATE_START:
/* Start-of-datastream actions: reset appropriate modules */
reset_input_controller(cinfo);
/* Initialize application's data source module */
init_source(cinfo);
cinfo.global_state = DSTATE_INHEADER;
/* FALLTHROUGH */
case DSTATE_INHEADER:
retcode = consume_input(cinfo);
if (retcode == JPEG_REACHED_SOS) { /*
* Found SOS, prepare to
* decompress
*/
/* Set up default parameters based on header data */
default_decompress_parms(cinfo);
/* Set global state: ready for start_decompress */
cinfo.global_state = DSTATE_READY;
}
break;
case DSTATE_READY:
/* Can't advance past first SOS until start_decompress is called */
retcode = JPEG_REACHED_SOS;
break;
case DSTATE_PRELOAD:
case DSTATE_PRESCAN:
case DSTATE_SCANNING:
case DSTATE_RAW_OK:
case DSTATE_BUFIMAGE:
case DSTATE_BUFPOST:
case DSTATE_STOPPING:
retcode = consume_input(cinfo);
break;
default:
error();
// ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
}
return retcode;
}
static void jpeg_abort(jpeg_decompress_struct cinfo) {
// int pool;
//
// /* Releasing pools in reverse order might help avoid fragmentation
// * with some (brain-damaged) malloc libraries.
// */
// for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
// (*cinfo.mem.free_pool) (cinfo, pool);
// }
/* Reset overall state for possible reuse of object */
if (cinfo.is_decompressor) {
cinfo.global_state = DSTATE_START;
/*
* Try to keep application from accessing now-deleted marker list. A
* bit kludgy to do it here, but this is the most central place.
*/
// ((j_decompress_ptr) cinfo).marker_list = null;
} else {
cinfo.global_state = CSTATE_START;
}
}
// static boolean isFileFormat(LEDataInputStream stream) {
// try {
// byte[] buffer = new byte[2];
// stream.read(buffer);
// stream.unread(buffer);
// return (buffer[0] & 0xFF) == 0xFF && (buffer[1] & 0xFF) == M_SOI;
// } catch (Exception e) {
// return false;
// }
// }
//
public static Image loadFromByteStream(InputStream inputStream) {
jpeg_decompress_struct cinfo = new jpeg_decompress_struct();
cinfo.inputStream = inputStream;
jpeg_create_decompress(cinfo);
jpeg_read_header(cinfo, true);
jpeg_start_decompress(cinfo);
int scanlinePad = 4;
int row_stride = (((cinfo.output_width * cinfo.out_color_components * 8 + 7) / 8) + (scanlinePad - 1))
/ scanlinePad * scanlinePad;
byte[][] buffer = new byte[1][row_stride];
byte[] data = new byte[row_stride * cinfo.output_height];
while (cinfo.output_scanline < cinfo.output_height) {
int offset = row_stride * cinfo.output_scanline;
jpeg_read_scanlines(cinfo, buffer, 1);
System.arraycopy(buffer[0], 0, data, offset, row_stride);
}
jpeg_finish_decompress(cinfo);
jpeg_destroy_decompress(cinfo);
// Fix big endian
if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN && cinfo.out_color_space == JCS_RGB) {
for (int i = 0; i < data.length; i += 3) {
byte temp = data[i];
data[i] = data[i + 2];
data[i + 2] = temp;
}
}
return new Image
(
cinfo.output_width,
cinfo.output_height,
cinfo.out_color_space == JCS_RGB ? Image.RGB : Image.LUMINANCE,
data
);
}
}