Skip to content

Commit 4802ddd

Browse files
committed
Partial fix for mozilla#138
Initial implementation of trellis quantization for arithmetic coding. The rate computation does not yet implement all rules of the entropy coder and may thus be suboptimal.
1 parent 9d8efde commit 4802ddd

File tree

6 files changed

+450
-19
lines changed

6 files changed

+450
-19
lines changed

cjpeg.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,6 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv,
292292

293293
/* No table optimization required for AC */
294294
cinfo->optimize_coding = FALSE;
295-
296-
/* Trellis quantization currently incompatible with AC */
297-
jpeg_c_set_bool_param(cinfo, JBOOLEAN_TRELLIS_QUANT, FALSE);
298295
#else
299296
fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
300297
progname);

jcarith.c

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#define JPEG_INTERNALS
1919
#include "jinclude.h"
2020
#include "jpeglib.h"
21-
21+
#include <math.h>
2222

2323
/* Expanded entropy encoder object for arithmetic encoding. */
2424

@@ -120,6 +120,10 @@ emit_byte (int val, j_compress_ptr cinfo)
120120
{
121121
struct jpeg_destination_mgr * dest = cinfo->dest;
122122

123+
/* Do not emit bytes during trellis passes */
124+
if (cinfo->master->trellis_passes)
125+
return;
126+
123127
*dest->next_output_byte++ = (JOCTET) val;
124128
if (--dest->free_in_buffer == 0)
125129
if (! (*dest->empty_output_buffer) (cinfo))
@@ -826,6 +830,7 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics)
826830
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
827831
int ci, tbl;
828832
jpeg_component_info * compptr;
833+
boolean progressive_mode;
829834

830835
if (gather_statistics)
831836
/* Make sure to avoid that in the master control logic!
@@ -836,8 +841,12 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics)
836841

837842
/* We assume jcmaster.c already validated the progressive scan parameters. */
838843

844+
/* Trellis optimization does DC and AC in same pass and without refinement
845+
* so consider progressive mode to be off in such case */
846+
progressive_mode = (cinfo->master->trellis_passes) ? FALSE : cinfo->progressive_mode;
847+
839848
/* Select execution routines */
840-
if (cinfo->progressive_mode) {
849+
if (progressive_mode) {
841850
if (cinfo->Ah == 0) {
842851
if (cinfo->Ss == 0)
843852
entropy->pub.encode_mcu = encode_mcu_DC_first;
@@ -856,7 +865,7 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics)
856865
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
857866
compptr = cinfo->cur_comp_info[ci];
858867
/* DC needs no table for refinement scan */
859-
if (cinfo->progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
868+
if (progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
860869
tbl = compptr->dc_tbl_no;
861870
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
862871
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
@@ -869,7 +878,7 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics)
869878
entropy->dc_context[ci] = 0;
870879
}
871880
/* AC needs no table when not present */
872-
if (cinfo->progressive_mode == 0 || cinfo->Se) {
881+
if (progressive_mode == 0 || cinfo->Se) {
873882
tbl = compptr->ac_tbl_no;
874883
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
875884
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
@@ -878,7 +887,7 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics)
878887
((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS);
879888
MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS);
880889
#ifdef CALCULATE_SPECTRAL_CONDITIONING
881-
if (cinfo->progressive_mode)
890+
if (progressive_mode)
882891
/* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */
883892
cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4);
884893
#endif
@@ -925,3 +934,29 @@ jinit_arith_encoder (j_compress_ptr cinfo)
925934
/* Initialize index for fixed probability estimation */
926935
entropy->fixed_bin[0] = 113;
927936
}
937+
938+
GLOBAL(void)
939+
jget_arith_rates (j_compress_ptr cinfo, int dc_tbl_no, int ac_tbl_no, arith_rates *r)
940+
{
941+
int i;
942+
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
943+
for (i = 0; i < DC_STAT_BINS; i++) {
944+
int state = entropy->dc_stats[dc_tbl_no][i];
945+
int mps_val = state >> 7;
946+
float prob_lps = (jpeg_aritab[state & 0x7f] >> 16) / 46340.95; /* 32768*sqrt(2) */
947+
float prob_0 = (mps_val) ? prob_lps : 1.0 - prob_lps;
948+
float prob_1 = 1.0 - prob_0;
949+
r->rate_dc[i][0] = -log(prob_0) / log(2.0);
950+
r->rate_dc[i][1] = -log(prob_1) / log(2.0);
951+
}
952+
953+
for (i = 0; i < AC_STAT_BINS; i++) {
954+
int state = entropy->ac_stats[ac_tbl_no][i];
955+
int mps_val = state >> 7;
956+
float prob_lps = (jpeg_aritab[state & 0x7f] >> 16) / 46340.95;
957+
float prob_0 = (mps_val) ? prob_lps : 1.0 - prob_lps;
958+
float prob_1 = 1.0 - prob_0;
959+
r->rate_ac[i][0] = -log(prob_0) / log(2.0);
960+
r->rate_ac[i][1] = -log(prob_1) / log(2.0);
961+
}
962+
}

jccoefct.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "jpeglib.h"
2020
#include "jchuff.h"
2121

22-
2322
/* We use a full-image coefficient buffer when doing Huffman optimization,
2423
* and also for writing multiple-scan JPEG files. In all cases, the DCT
2524
* step is run during the first pass, and subsequent passes need only read
@@ -367,10 +366,18 @@ compress_trellis_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
367366
c_derived_tbl *dctbl = &dctbl_data;
368367
c_derived_tbl actbl_data;
369368
c_derived_tbl *actbl = &actbl_data;
369+
370+
arith_rates arith_r_data;
371+
arith_rates *arith_r = &arith_r_data;
372+
370373
compptr = cinfo->cur_comp_info[ci];
371374

372-
jpeg_make_c_derived_tbl(cinfo, TRUE, compptr->dc_tbl_no, &dctbl);
373-
jpeg_make_c_derived_tbl(cinfo, FALSE, compptr->ac_tbl_no, &actbl);
375+
if (cinfo->arith_code)
376+
jget_arith_rates(cinfo, compptr->dc_tbl_no, compptr->ac_tbl_no, arith_r);
377+
else {
378+
jpeg_make_c_derived_tbl(cinfo, TRUE, compptr->dc_tbl_no, &dctbl);
379+
jpeg_make_c_derived_tbl(cinfo, FALSE, compptr->ac_tbl_no, &actbl);
380+
}
374381

375382
/* Align the virtual buffer for this component. */
376383
buffer = (*cinfo->mem->access_virt_barray)
@@ -406,12 +413,20 @@ compress_trellis_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
406413
for (block_row = 0; block_row < block_rows; block_row++) {
407414
thisblockrow = buffer[block_row];
408415
lastblockrow = (block_row > 0) ? buffer[block_row-1] : NULL;
409-
quantize_trellis(cinfo, dctbl, actbl, thisblockrow,
410-
buffer_dst[block_row], blocks_across,
411-
cinfo->quant_tbl_ptrs[compptr->quant_tbl_no],
412-
cinfo->master->norm_src[compptr->quant_tbl_no],
413-
cinfo->master->norm_coef[compptr->quant_tbl_no],
414-
&lastDC, lastblockrow, buffer_dst[block_row-1]);
416+
if (cinfo->arith_code)
417+
quantize_trellis_arith(cinfo, arith_r, thisblockrow,
418+
buffer_dst[block_row], blocks_across,
419+
cinfo->quant_tbl_ptrs[compptr->quant_tbl_no],
420+
cinfo->master->norm_src[compptr->quant_tbl_no],
421+
cinfo->master->norm_coef[compptr->quant_tbl_no],
422+
&lastDC, lastblockrow, buffer_dst[block_row-1]);
423+
else
424+
quantize_trellis(cinfo, dctbl, actbl, thisblockrow,
425+
buffer_dst[block_row], blocks_across,
426+
cinfo->quant_tbl_ptrs[compptr->quant_tbl_no],
427+
cinfo->master->norm_src[compptr->quant_tbl_no],
428+
cinfo->master->norm_coef[compptr->quant_tbl_no],
429+
&lastDC, lastblockrow, buffer_dst[block_row-1]);
415430

416431
if (ndummy > 0) {
417432
/* Create dummy blocks at the right edge of the image. */

0 commit comments

Comments
 (0)