#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#ifdef WITH_SIMD
#include "jsimd.h"
#else
#include "jchuff.h"
#endif
#include <limits.h>
#include "jpeg_nbits.h"
#if defined(__x86_64__) && defined(__ILP32__)
typedef unsigned long long bit_buf_type;
#else
typedef size_t bit_buf_type;
#endif
#if defined(WITH_SIMD) && !(defined(__arm__) || defined(__aarch64__) || \
defined(_M_ARM) || defined(_M_ARM64))
typedef unsigned long long simd_bit_buf_type;
#else
typedef bit_buf_type simd_bit_buf_type;
#endif
#if (defined(SIZEOF_SIZE_T) && SIZEOF_SIZE_T == 8) || defined(_WIN64) || \
(defined(__x86_64__) && defined(__ILP32__))
#define BIT_BUF_SIZE 64
#elif (defined(SIZEOF_SIZE_T) && SIZEOF_SIZE_T == 4) || defined(_WIN32)
#define BIT_BUF_SIZE 32
#else
#error Cannot determine word size
#endif
#define SIMD_BIT_BUF_SIZE (sizeof(simd_bit_buf_type) * 8)
typedef struct {
union {
bit_buf_type c;
#ifdef WITH_SIMD
simd_bit_buf_type simd;
#endif
} put_buffer;
int free_bits;
int last_dc_val[MAX_COMPS_IN_SCAN];
} savable_state;
typedef struct {
struct jpeg_entropy_encoder pub;
savable_state saved;
unsigned int restarts_to_go;
int next_restart_num;
c_derived_tbl *dc_derived_tbls[NUM_HUFF_TBLS];
c_derived_tbl *ac_derived_tbls[NUM_HUFF_TBLS];
#ifdef ENTROPY_OPT_SUPPORTED
long *dc_count_ptrs[NUM_HUFF_TBLS];
long *ac_count_ptrs[NUM_HUFF_TBLS];
#endif
#ifdef WITH_SIMD
int simd;
#endif
} huff_entropy_encoder;
typedef huff_entropy_encoder *huff_entropy_ptr;
typedef struct {
JOCTET *next_output_byte;
size_t free_in_buffer;
savable_state cur;
j_compress_ptr cinfo;
#ifdef WITH_SIMD
int simd;
#endif
} working_state;
METHODDEF(boolean) encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data);
METHODDEF(void) finish_pass_huff(j_compress_ptr cinfo);
#ifdef ENTROPY_OPT_SUPPORTED
METHODDEF(boolean) encode_mcu_gather(j_compress_ptr cinfo,
JBLOCKROW *MCU_data);
METHODDEF(void) finish_pass_gather(j_compress_ptr cinfo);
#endif
METHODDEF(void)
start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics)
{
huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci, dctbl, actbl;
jpeg_component_info *compptr;
if (gather_statistics) {
#ifdef ENTROPY_OPT_SUPPORTED
entropy->pub.encode_mcu = encode_mcu_gather;
entropy->pub.finish_pass = finish_pass_gather;
#else
ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
} else {
entropy->pub.encode_mcu = encode_mcu_huff;
entropy->pub.finish_pass = finish_pass_huff;
}
#ifdef WITH_SIMD
entropy->simd = jsimd_can_huff_encode_one_block();
#endif
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;
if (gather_statistics) {
#ifdef ENTROPY_OPT_SUPPORTED
if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
if (actbl < 0 || actbl >= NUM_HUFF_TBLS)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
if (entropy->dc_count_ptrs[dctbl] == NULL)
entropy->dc_count_ptrs[dctbl] = (long *)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long));
memset(entropy->dc_count_ptrs[dctbl], 0, 257 * sizeof(long));
if (entropy->ac_count_ptrs[actbl] == NULL)
entropy->ac_count_ptrs[actbl] = (long *)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long));
memset(entropy->ac_count_ptrs[actbl], 0, 257 * sizeof(long));
#endif
} else {
jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
&entropy->dc_derived_tbls[dctbl]);
jpeg_make_c_derived_tbl(cinfo, FALSE, actbl,
&entropy->ac_derived_tbls[actbl]);
}
entropy->saved.last_dc_val[ci] = 0;
}
#ifdef WITH_SIMD
if (entropy->simd) {
entropy->saved.put_buffer.simd = 0;
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
entropy->saved.free_bits = 0;
#else
entropy->saved.free_bits = SIMD_BIT_BUF_SIZE;
#endif
} else
#endif
{
entropy->saved.put_buffer.c = 0;
entropy->saved.free_bits = BIT_BUF_SIZE;
}
entropy->restarts_to_go = cinfo->restart_interval;
entropy->next_restart_num = 0;
}
GLOBAL(void)
jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno,
c_derived_tbl **pdtbl)
{
JHUFF_TBL *htbl;
c_derived_tbl *dtbl;
int p, i, l, lastp, si, maxsymbol;
char huffsize[257];
unsigned int huffcode[257];
unsigned int code;
if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
htbl =
isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
if (htbl == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
if (*pdtbl == NULL)
*pdtbl = (c_derived_tbl *)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(c_derived_tbl));
dtbl = *pdtbl;
p = 0;
for (l = 1; l <= 16; l++) {
i = (int)htbl->bits[l];
if (i < 0 || p + i > 256)
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
while (i--)
huffsize[p++] = (char)l;
}
huffsize[p] = 0;
lastp = p;
code = 0;
si = huffsize[0];
p = 0;
while (huffsize[p]) {
while (((int)huffsize[p]) == si) {
huffcode[p++] = code;
code++;
}
if (((JLONG)code) >= (((JLONG)1) << si))
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
code <<= 1;
si++;
}
memset(dtbl->ehufco, 0, sizeof(dtbl->ehufco));
memset(dtbl->ehufsi, 0, sizeof(dtbl->ehufsi));
maxsymbol = isDC ? (cinfo->master->lossless ? 16 : 15) : 255;
for (p = 0; p < lastp; p++) {
i = htbl->huffval[p];
if (i < 0 || i > maxsymbol || dtbl->ehufsi[i])
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
dtbl->ehufco[i] = huffcode[p];
dtbl->ehufsi[i] = huffsize[p];
}
}
#define emit_byte(state, val, action) { \
*(state)->next_output_byte++ = (JOCTET)(val); \
if (--(state)->free_in_buffer == 0) \
if (!dump_buffer(state)) \
{ action; } \
}
LOCAL(boolean)
dump_buffer(working_state *state)
{
struct jpeg_destination_mgr *dest = state->cinfo->dest;
if (!(*dest->empty_output_buffer) (state->cinfo))
return FALSE;
state->next_output_byte = dest->next_output_byte;
state->free_in_buffer = dest->free_in_buffer;
return TRUE;
}
#define EMIT_BYTE(b) { \
buffer[0] = (JOCTET)(b); \
buffer[1] = 0; \
buffer -= -2 + ((JOCTET)(b) < 0xFF); \
}
#if BIT_BUF_SIZE == 64
#define FLUSH() { \
if (put_buffer & 0x8080808080808080 & ~(put_buffer + 0x0101010101010101)) { \
EMIT_BYTE(put_buffer >> 56) \
EMIT_BYTE(put_buffer >> 48) \
EMIT_BYTE(put_buffer >> 40) \
EMIT_BYTE(put_buffer >> 32) \
EMIT_BYTE(put_buffer >> 24) \
EMIT_BYTE(put_buffer >> 16) \
EMIT_BYTE(put_buffer >> 8) \
EMIT_BYTE(put_buffer ) \
} else { \
buffer[0] = (JOCTET)(put_buffer >> 56); \
buffer[1] = (JOCTET)(put_buffer >> 48); \
buffer[2] = (JOCTET)(put_buffer >> 40); \
buffer[3] = (JOCTET)(put_buffer >> 32); \
buffer[4] = (JOCTET)(put_buffer >> 24); \
buffer[5] = (JOCTET)(put_buffer >> 16); \
buffer[6] = (JOCTET)(put_buffer >> 8); \
buffer[7] = (JOCTET)(put_buffer); \
buffer += 8; \
} \
}
#else
#define FLUSH() { \
if (put_buffer & 0x80808080 & ~(put_buffer + 0x01010101)) { \
EMIT_BYTE(put_buffer >> 24) \
EMIT_BYTE(put_buffer >> 16) \
EMIT_BYTE(put_buffer >> 8) \
EMIT_BYTE(put_buffer ) \
} else { \
buffer[0] = (JOCTET)(put_buffer >> 24); \
buffer[1] = (JOCTET)(put_buffer >> 16); \
buffer[2] = (JOCTET)(put_buffer >> 8); \
buffer[3] = (JOCTET)(put_buffer); \
buffer += 4; \
} \
}
#endif
#define PUT_AND_FLUSH(code, size) { \
put_buffer = (put_buffer << (size + free_bits)) | (code >> -free_bits); \
FLUSH() \
free_bits += BIT_BUF_SIZE; \
put_buffer = code; \
}
#define PUT_BITS(code, size) { \
free_bits -= size; \
if (free_bits < 0) \
PUT_AND_FLUSH(code, size) \
else \
put_buffer = (put_buffer << size) | code; \
}
#define PUT_CODE(code, size) { \
temp &= (((JLONG)1) << nbits) - 1; \
temp |= code << nbits; \
nbits += size; \
PUT_BITS(temp, nbits) \
}
#define BUFSIZE (DCTSIZE2 * 8)
#define LOAD_BUFFER() { \
if (state->free_in_buffer < BUFSIZE) { \
localbuf = 1; \
buffer = _buffer; \
} else \
buffer = state->next_output_byte; \
}
#define STORE_BUFFER() { \
if (localbuf) { \
size_t bytes, bytestocopy; \
bytes = buffer - _buffer; \
buffer = _buffer; \
while (bytes > 0) { \
bytestocopy = MIN(bytes, state->free_in_buffer); \
memcpy(state->next_output_byte, buffer, bytestocopy); \
state->next_output_byte += bytestocopy; \
buffer += bytestocopy; \
state->free_in_buffer -= bytestocopy; \
if (state->free_in_buffer == 0) \
if (!dump_buffer(state)) return FALSE; \
bytes -= bytestocopy; \
} \
} else { \
state->free_in_buffer -= (buffer - state->next_output_byte); \
state->next_output_byte = buffer; \
} \
}
LOCAL(boolean)
flush_bits(working_state *state)
{
JOCTET _buffer[BUFSIZE], *buffer, temp;
simd_bit_buf_type put_buffer; int put_bits;
int localbuf = 0;
#ifdef WITH_SIMD
if (state->simd) {
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
put_bits = state->cur.free_bits;
#else
put_bits = SIMD_BIT_BUF_SIZE - state->cur.free_bits;
#endif
put_buffer = state->cur.put_buffer.simd;
} else
#endif
{
put_bits = BIT_BUF_SIZE - state->cur.free_bits;
put_buffer = state->cur.put_buffer.c;
}
LOAD_BUFFER()
while (put_bits >= 8) {
put_bits -= 8;
temp = (JOCTET)(put_buffer >> put_bits);
EMIT_BYTE(temp)
}
if (put_bits) {
temp = (JOCTET)((put_buffer << (8 - put_bits)) | (0xFF >> put_bits));
EMIT_BYTE(temp)
}
#ifdef WITH_SIMD
if (state->simd) {
state->cur.put_buffer.simd = 0;
#if defined(__aarch64__) && !defined(NEON_INTRINSICS)
state->cur.free_bits = 0;
#else
state->cur.free_bits = SIMD_BIT_BUF_SIZE;
#endif
} else
#endif
{
state->cur.put_buffer.c = 0;
state->cur.free_bits = BIT_BUF_SIZE;
}
STORE_BUFFER()
return TRUE;
}
#ifdef WITH_SIMD
LOCAL(boolean)
encode_one_block_simd(working_state *state, JCOEFPTR block, int last_dc_val,
c_derived_tbl *dctbl, c_derived_tbl *actbl)
{
JOCTET _buffer[BUFSIZE], *buffer;
int localbuf = 0;
#ifdef ZERO_BUFFERS
memset(_buffer, 0, sizeof(_buffer));
#endif
LOAD_BUFFER()
buffer = jsimd_huff_encode_one_block(state, buffer, block, last_dc_val,
dctbl, actbl);
STORE_BUFFER()
return TRUE;
}
#endif
LOCAL(boolean)
encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
c_derived_tbl *dctbl, c_derived_tbl *actbl)
{
int temp, nbits, free_bits;
bit_buf_type put_buffer;
JOCTET _buffer[BUFSIZE], *buffer;
int localbuf = 0;
int max_coef_bits = state->cinfo->data_precision + 2;
free_bits = state->cur.free_bits;
put_buffer = state->cur.put_buffer.c;
LOAD_BUFFER()
temp = block[0] - last_dc_val;
nbits = temp >> (CHAR_BIT * sizeof(int) - 1);
temp += nbits;
nbits ^= temp;
nbits = JPEG_NBITS(nbits);
if (nbits > max_coef_bits + 1)
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
PUT_CODE(dctbl->ehufco[nbits], dctbl->ehufsi[nbits])
{
int r = 0;
#define kloop(jpeg_natural_order_of_k) { \
if ((temp = block[jpeg_natural_order_of_k]) == 0) { \
r += 16; \
} else { \
\
nbits = temp >> (CHAR_BIT * sizeof(int) - 1); \
temp += nbits; \
nbits ^= temp; \
nbits = JPEG_NBITS_NONZERO(nbits); \
\
if (nbits > max_coef_bits) \
ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); \
\
while (r >= 16 * 16) { \
r -= 16 * 16; \
PUT_BITS(actbl->ehufco[0xf0], actbl->ehufsi[0xf0]) \
} \
\
r += nbits; \
PUT_CODE(actbl->ehufco[r], actbl->ehufsi[r]) \
r = 0; \
} \
}
kloop(1); kloop(8); kloop(16); kloop(9); kloop(2); kloop(3);
kloop(10); kloop(17); kloop(24); kloop(32); kloop(25); kloop(18);
kloop(11); kloop(4); kloop(5); kloop(12); kloop(19); kloop(26);
kloop(33); kloop(40); kloop(48); kloop(41); kloop(34); kloop(27);
kloop(20); kloop(13); kloop(6); kloop(7); kloop(14); kloop(21);
kloop(28); kloop(35); kloop(42); kloop(49); kloop(56); kloop(57);
kloop(50); kloop(43); kloop(36); kloop(29); kloop(22); kloop(15);
kloop(23); kloop(30); kloop(37); kloop(44); kloop(51); kloop(58);
kloop(59); kloop(52); kloop(45); kloop(38); kloop(31); kloop(39);
kloop(46); kloop(53); kloop(60); kloop(61); kloop(54); kloop(47);
kloop(55); kloop(62); kloop(63);
if (r > 0) {
PUT_BITS(actbl->ehufco[0], actbl->ehufsi[0])
}
}
state->cur.put_buffer.c = put_buffer;
state->cur.free_bits = free_bits;
STORE_BUFFER()
return TRUE;
}
LOCAL(boolean)
emit_restart(working_state *state, int restart_num)
{
int ci;
if (!flush_bits(state))
return FALSE;
emit_byte(state, 0xFF, return FALSE);
emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
for (ci = 0; ci < state->cinfo->comps_in_scan; ci++)
state->cur.last_dc_val[ci] = 0;
return TRUE;
}
METHODDEF(boolean)
encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
working_state state;
int blkn, ci;
jpeg_component_info *compptr;
state.next_output_byte = cinfo->dest->next_output_byte;
state.free_in_buffer = cinfo->dest->free_in_buffer;
state.cur = entropy->saved;
state.cinfo = cinfo;
#ifdef WITH_SIMD
state.simd = entropy->simd;
#endif
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
if (!emit_restart(&state, entropy->next_restart_num))
return FALSE;
}
#ifdef WITH_SIMD
if (entropy->simd) {
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
ci = cinfo->MCU_membership[blkn];
compptr = cinfo->cur_comp_info[ci];
if (!encode_one_block_simd(&state,
MCU_data[blkn][0], state.cur.last_dc_val[ci],
entropy->dc_derived_tbls[compptr->dc_tbl_no],
entropy->ac_derived_tbls[compptr->ac_tbl_no]))
return FALSE;
state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
}
} else
#endif
{
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
ci = cinfo->MCU_membership[blkn];
compptr = cinfo->cur_comp_info[ci];
if (!encode_one_block(&state,
MCU_data[blkn][0], state.cur.last_dc_val[ci],
entropy->dc_derived_tbls[compptr->dc_tbl_no],
entropy->ac_derived_tbls[compptr->ac_tbl_no]))
return FALSE;
state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
}
}
cinfo->dest->next_output_byte = state.next_output_byte;
cinfo->dest->free_in_buffer = state.free_in_buffer;
entropy->saved = state.cur;
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0) {
entropy->restarts_to_go = cinfo->restart_interval;
entropy->next_restart_num++;
entropy->next_restart_num &= 7;
}
entropy->restarts_to_go--;
}
return TRUE;
}
METHODDEF(void)
finish_pass_huff(j_compress_ptr cinfo)
{
huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
working_state state;
state.next_output_byte = cinfo->dest->next_output_byte;
state.free_in_buffer = cinfo->dest->free_in_buffer;
state.cur = entropy->saved;
state.cinfo = cinfo;
#ifdef WITH_SIMD
state.simd = entropy->simd;
#endif
if (!flush_bits(&state))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
cinfo->dest->next_output_byte = state.next_output_byte;
cinfo->dest->free_in_buffer = state.free_in_buffer;
entropy->saved = state.cur;
}
#ifdef ENTROPY_OPT_SUPPORTED
LOCAL(void)
htest_one_block(j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
long dc_counts[], long ac_counts[])
{
register int temp;
register int nbits;
register int k, r;
int max_coef_bits = cinfo->data_precision + 2;
temp = block[0] - last_dc_val;
if (temp < 0)
temp = -temp;
nbits = 0;
while (temp) {
nbits++;
temp >>= 1;
}
if (nbits > max_coef_bits + 1)
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
dc_counts[nbits]++;
r = 0;
for (k = 1; k < DCTSIZE2; k++) {
if ((temp = block[jpeg_natural_order[k]]) == 0) {
r++;
} else {
while (r > 15) {
ac_counts[0xF0]++;
r -= 16;
}
if (temp < 0)
temp = -temp;
nbits = 1;
while ((temp >>= 1))
nbits++;
if (nbits > max_coef_bits)
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
ac_counts[(r << 4) + nbits]++;
r = 0;
}
}
if (r > 0)
ac_counts[0]++;
}
METHODDEF(boolean)
encode_mcu_gather(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int blkn, ci;
jpeg_component_info *compptr;
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0) {
for (ci = 0; ci < cinfo->comps_in_scan; ci++)
entropy->saved.last_dc_val[ci] = 0;
entropy->restarts_to_go = cinfo->restart_interval;
}
entropy->restarts_to_go--;
}
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
ci = cinfo->MCU_membership[blkn];
compptr = cinfo->cur_comp_info[ci];
htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci],
entropy->dc_count_ptrs[compptr->dc_tbl_no],
entropy->ac_count_ptrs[compptr->ac_tbl_no]);
entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0];
}
return TRUE;
}
GLOBAL(void)
jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
{
#define MAX_CLEN 32
UINT8 bits[MAX_CLEN + 1];
int bit_pos[MAX_CLEN + 1];
int codesize[257];
int nz_index[257];
int others[257];
int c1, c2;
int p, i, j;
int num_nz_symbols;
long v, v2;
memset(bits, 0, sizeof(bits));
memset(codesize, 0, sizeof(codesize));
for (i = 0; i < 257; i++)
others[i] = -1;
freq[256] = 1;
num_nz_symbols = 0;
for (i = 0; i < 257; i++) {
if (freq[i]) {
nz_index[num_nz_symbols] = i;
freq[num_nz_symbols] = freq[i];
num_nz_symbols++;
}
}
for (;;) {
c1 = -1;
c2 = -1;
v = 1000000000L;
v2 = 1000000000L;
for (i = 0; i < num_nz_symbols; i++) {
if (freq[i] <= v2) {
if (freq[i] <= v) {
c2 = c1;
v2 = v;
v = freq[i];
c1 = i;
} else {
v2 = freq[i];
c2 = i;
}
}
}
if (c2 < 0)
break;
freq[c1] += freq[c2];
freq[c2] = 1000000001L;
codesize[c1]++;
while (others[c1] >= 0) {
c1 = others[c1];
codesize[c1]++;
}
others[c1] = c2;
codesize[c2]++;
while (others[c2] >= 0) {
c2 = others[c2];
codesize[c2]++;
}
}
for (i = 0; i < num_nz_symbols; i++) {
if (codesize[i] > MAX_CLEN)
ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW);
bits[codesize[i]]++;
}
p = 0;
for (i = 1; i <= MAX_CLEN; i++) {
bit_pos[i] = p;
p += bits[i];
}
for (i = MAX_CLEN; i > 16; i--) {
while (bits[i] > 0) {
j = i - 2;
while (bits[j] == 0)
j--;
bits[i] -= 2;
bits[i - 1]++;
bits[j + 1] += 2;
bits[j]--;
}
}
while (bits[i] == 0)
i--;
bits[i]--;
memcpy(htbl->bits, bits, sizeof(htbl->bits));
for (i = 0; i < num_nz_symbols - 1; i++) {
htbl->huffval[bit_pos[codesize[i]]] = (UINT8)nz_index[i];
bit_pos[codesize[i]]++;
}
htbl->sent_table = FALSE;
}
METHODDEF(void)
finish_pass_gather(j_compress_ptr cinfo)
{
huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci, dctbl, actbl;
jpeg_component_info *compptr;
JHUFF_TBL **htblptr;
boolean did_dc[NUM_HUFF_TBLS];
boolean did_ac[NUM_HUFF_TBLS];
memset(did_dc, 0, sizeof(did_dc));
memset(did_ac, 0, sizeof(did_ac));
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;
if (!did_dc[dctbl]) {
htblptr = &cinfo->dc_huff_tbl_ptrs[dctbl];
if (*htblptr == NULL)
*htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
did_dc[dctbl] = TRUE;
}
if (!did_ac[actbl]) {
htblptr = &cinfo->ac_huff_tbl_ptrs[actbl];
if (*htblptr == NULL)
*htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
did_ac[actbl] = TRUE;
}
}
}
#endif
GLOBAL(void)
jinit_huff_encoder(j_compress_ptr cinfo)
{
huff_entropy_ptr entropy;
int i;
entropy = (huff_entropy_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(huff_entropy_encoder));
cinfo->entropy = (struct jpeg_entropy_encoder *)entropy;
entropy->pub.start_pass = start_pass_huff;
for (i = 0; i < NUM_HUFF_TBLS; i++) {
entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
#ifdef ENTROPY_OPT_SUPPORTED
entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL;
#endif
}
}