Add optimization of quantization matrix
Optimizes quantization matrix by minimizing reconstruction error based on quantized coefficients. Feature is controlled by cinfo->trellis_q_opt; disabled by default.
This commit is contained in:
@@ -363,7 +363,6 @@ compress_trellis_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
||||
c_derived_tbl actbl_data;
|
||||
c_derived_tbl *actbl = &actbl_data;
|
||||
|
||||
compptr = cinfo->cur_comp_info[ci];
|
||||
|
||||
jpeg_make_c_derived_tbl(cinfo, FALSE, compptr->ac_tbl_no, &actbl);
|
||||
@@ -398,7 +397,7 @@ compress_trellis_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
*/
|
||||
for (block_row = 0; block_row < block_rows; block_row++) {
|
||||
thisblockrow = buffer[block_row];
|
||||
quantize_trellis(cinfo, actbl, thisblockrow, buffer_dst[block_row], blocks_across, cinfo->quant_tbl_ptrs[compptr->quant_tbl_no]);
|
||||
quantize_trellis(cinfo, actbl, thisblockrow, buffer_dst[block_row], blocks_across, cinfo->quant_tbl_ptrs[compptr->quant_tbl_no], cinfo->norm_src[compptr->quant_tbl_no], cinfo->norm_coef[compptr->quant_tbl_no]);
|
||||
|
||||
if (ndummy > 0) {
|
||||
/* Create dummy blocks at the right edge of the image. */
|
||||
@@ -435,6 +434,7 @@ compress_trellis_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: compress_output will increment iMCU_row_num if successful.
|
||||
* A suspension return will result in redoing all the work above next time.
|
||||
*/
|
||||
|
||||
11
jcdctmgr.c
11
jcdctmgr.c
@@ -576,7 +576,7 @@ static const float jpeg_lambda_weights_csf_luma[64] = {
|
||||
|
||||
GLOBAL(void)
|
||||
quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_blocks, JBLOCKROW src, JDIMENSION num_blocks,
|
||||
JQUANT_TBL * qtbl)
|
||||
JQUANT_TBL * qtbl, double *norm_src, double *norm_coef)
|
||||
{
|
||||
int i, j, k;
|
||||
float accumulated_zero_dist[DCTSIZE2];
|
||||
@@ -821,6 +821,15 @@ quantize_trellis(j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_bloc
|
||||
free(block_run_start);
|
||||
free(requires_eob);
|
||||
}
|
||||
|
||||
if (cinfo->trellis_q_opt) {
|
||||
for (bi = 0; bi < num_blocks; bi++) {
|
||||
for (i = 1; i < DCTSIZE2; i++) {
|
||||
norm_src[i] += src[bi][i] * coef_blocks[bi][i];
|
||||
norm_coef[i] += 8 * coef_blocks[bi][i] * coef_blocks[bi][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
2
jchuff.h
2
jchuff.h
@@ -50,4 +50,4 @@ EXTERN(void) jpeg_gen_optimal_table
|
||||
|
||||
EXTERN(void) quantize_trellis
|
||||
JPP((j_compress_ptr cinfo, c_derived_tbl *actbl, JBLOCKROW coef_blocks, JBLOCKROW src, JDIMENSION num_blocks,
|
||||
JQUANT_TBL * qtbl));
|
||||
JQUANT_TBL * qtbl, double *norm_src, double *norm_coef));
|
||||
|
||||
24
jcmaster.c
24
jcmaster.c
@@ -550,6 +550,16 @@ prepare_for_pass (j_compress_ptr cinfo)
|
||||
master->pub.call_pass_startup = FALSE;
|
||||
break;
|
||||
case trellis_pass:
|
||||
if (master->pass_number%(cinfo->num_components*(cinfo->use_scans_in_trellis?4:2)) == 1 && cinfo->trellis_q_opt) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < NUM_QUANT_TBLS; i++) {
|
||||
for (j = 1; j < DCTSIZE2; j++) {
|
||||
cinfo->norm_src[i][j] = 0.0;
|
||||
cinfo->norm_coef[i][j] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
(*cinfo->entropy->start_pass) (cinfo, TRUE);
|
||||
(*cinfo->coef->start_pass) (cinfo, JBUF_REQUANT);
|
||||
master->pub.call_pass_startup = FALSE;
|
||||
@@ -838,6 +848,20 @@ finish_pass_master (j_compress_ptr cinfo)
|
||||
break;
|
||||
case trellis_pass:
|
||||
master->pass_type = (cinfo->optimize_scans || master->pass_number < master->pass_number_scan_opt_base-1) ? huff_opt_pass : output_pass;
|
||||
|
||||
if ((master->pass_number+1)%(cinfo->num_components*(cinfo->use_scans_in_trellis?4:2)) == 0 && cinfo->trellis_q_opt) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < NUM_QUANT_TBLS; i++) {
|
||||
for (j = 1; j < DCTSIZE2; j++) {
|
||||
if (cinfo->norm_coef[i][j] != 0.0) {
|
||||
int q = (int)(cinfo->norm_src[i][j] / cinfo->norm_coef[i][j] + 0.5);
|
||||
if (q > 254) q = 254;
|
||||
if (q < 1) q = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -433,6 +433,7 @@ jpeg_set_defaults (j_compress_ptr cinfo)
|
||||
cinfo->use_scans_in_trellis = FALSE;
|
||||
cinfo->trellis_freq_split = 8;
|
||||
cinfo->trellis_num_loops = 1;
|
||||
cinfo->trellis_q_opt = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -384,6 +384,10 @@ struct jpeg_compress_struct {
|
||||
boolean use_lambda_weight_tbl; /* TRUE=use lambda weighting table */
|
||||
boolean use_scans_in_trellis; /* TRUE=use scans in trellis optimization */
|
||||
boolean trellis_passes; /* TRUE=currently doing trellis-related passes */
|
||||
boolean trellis_q_opt; /* TRUE=optimize quant table in trellis loop */
|
||||
|
||||
double norm_src[NUM_QUANT_TBLS][DCTSIZE2];
|
||||
double norm_coef[NUM_QUANT_TBLS][DCTSIZE2];
|
||||
|
||||
int trellis_freq_split; /* splitting point for frequency in trellis quantization */
|
||||
int trellis_num_loops; /* number of trellis loops */
|
||||
|
||||
Reference in New Issue
Block a user