Clean up scan optimisation code

Remove hard coded values and restructure code.
This commit is contained in:
fbossen
2014-02-14 17:11:56 -05:00
parent 71f953d0be
commit 09fde9eaf6
3 changed files with 205 additions and 223 deletions

View File

@@ -551,7 +551,7 @@ pass_startup (j_compress_ptr cinfo)
LOCAL(void)
copy_buffer (j_compress_ptr cinfo, int scan_idx)
{
int size = cinfo->scan_size[scan_idx];
unsigned long size = cinfo->scan_size[scan_idx];
unsigned char * src = cinfo->scan_buffer[scan_idx];
while (size >= cinfo->dest->free_in_buffer)
@@ -569,6 +569,170 @@ copy_buffer (j_compress_ptr cinfo, int scan_idx)
cinfo->dest->free_in_buffer -= size;
}
LOCAL(void)
select_scans (j_compress_ptr cinfo, int next_scan_number)
{
unsigned long size[8];
int base_scan_idx;
if (next_scan_number == cinfo->num_scans_luma_dc) {
copy_buffer(cinfo, 0);
} else if (next_scan_number == cinfo->num_scans_luma_dc+3*cinfo->Al_max_luma+2) {
int Al;
int i;
cinfo->best_Al = 0;
for (Al = 0; Al <= cinfo->Al_max_luma; Al++) {
size[Al] = cinfo->scan_size[1 + 2 * Al];
size[Al] += cinfo->scan_size[2 + 2 * Al];
for (i = 0; i < Al; i++)
size[Al] += cinfo->scan_size[3 + 2*cinfo->Al_max_luma + i];
if (size[Al] < size[cinfo->best_Al])
cinfo->best_Al = Al;
}
/* HACK! casting a const to a non-const :-( */
jpeg_scan_info *scanptr = (jpeg_scan_info *)&cinfo->scan_info[next_scan_number];
for (i = 0; i < 2*cinfo->num_frequency_splits+1; i++)
scanptr[i].Al = cinfo->best_Al;
} else if (next_scan_number == cinfo->num_scans_luma) {
int i;
int best = 0;
base_scan_idx = next_scan_number - (2*cinfo->num_frequency_splits+1);
int Al;
size[0] = cinfo->scan_size[base_scan_idx];
for (i = 0; i < cinfo->num_frequency_splits; i++) {
size[i+1] = cinfo->scan_size[base_scan_idx+2*i+1];
size[i+1] += cinfo->scan_size[base_scan_idx+2*i+2];
}
if (size[1] < size[best])
best = 1;
if (size[2] < size[best])
best = 2;
if (best != 0) {
if (size[3] < size[best])
best = 3;
if (best == 2) {
if (size[4] < size[best]) {
best = 4;
if (size[5] < size[best])
best = 5;
}
}
}
if (best == 0)
copy_buffer(cinfo, base_scan_idx);
else {
copy_buffer(cinfo, base_scan_idx+2*(best-1)+1);
copy_buffer(cinfo, base_scan_idx+2*(best-1)+2);
}
/* copy the LSB refinements as well */
for (Al = cinfo->best_Al-1; Al >= 0; Al--)
copy_buffer(cinfo, 2*cinfo->Al_max_luma + 3 + Al);
/* free the memory allocated for the luma buffers */
for (i = 0; i < cinfo->num_scans_luma; i++)
free(cinfo->scan_buffer[i]);
} else if (next_scan_number == cinfo->num_scans_luma+cinfo->num_scans_chroma_dc) {
base_scan_idx = cinfo->num_scans_luma;
if (cinfo->scan_size[base_scan_idx] <= cinfo->scan_size[base_scan_idx+1] + cinfo->scan_size[base_scan_idx+2])
copy_buffer(cinfo, base_scan_idx);
else {
copy_buffer(cinfo, base_scan_idx+1);
copy_buffer(cinfo, base_scan_idx+2);
}
} else if (next_scan_number == cinfo->num_scans_luma+cinfo->num_scans_chroma_dc+(6*cinfo->Al_max_chroma+4)) {
int Al;
int i;
base_scan_idx = cinfo->num_scans_luma + cinfo->num_scans_chroma_dc;
cinfo->best_Al = 0;
for (Al = 0; Al <= cinfo->Al_max_chroma; Al++) {
size[Al] = cinfo->scan_size[base_scan_idx + 0 + 4 * Al];
size[Al] += cinfo->scan_size[base_scan_idx + 1 + 4 * Al];
size[Al] += cinfo->scan_size[base_scan_idx + 2 + 4 * Al];
size[Al] += cinfo->scan_size[base_scan_idx + 3 + 4 * Al];
for (i = 0; i < Al; i++) {
size[Al] += cinfo->scan_size[base_scan_idx + 4 + 4*cinfo->Al_max_chroma + 2*i];
size[Al] += cinfo->scan_size[base_scan_idx + 5 + 4*cinfo->Al_max_chroma + 2*i];
}
if (size[Al] < size[cinfo->best_Al])
cinfo->best_Al = Al;
}
jpeg_scan_info *scanptr = (jpeg_scan_info *)&cinfo->scan_info[next_scan_number];
for (i = 0; i < 4*cinfo->num_frequency_splits+2; i++)
scanptr[i].Al = cinfo->best_Al;
} else if (next_scan_number == cinfo->num_scans) {
int Al;
int i;
base_scan_idx = next_scan_number - (4*cinfo->num_frequency_splits+2);
size[0] = cinfo->scan_size[base_scan_idx];
size[0] += cinfo->scan_size[base_scan_idx+1];
for (i = 0; i < cinfo->num_frequency_splits; i++) {
size[i+1] = cinfo->scan_size[base_scan_idx+0+4*i] + cinfo->scan_size[base_scan_idx+1+4*i];
size[i+1] += cinfo->scan_size[base_scan_idx+2+4*i] + cinfo->scan_size[base_scan_idx+3+4*i];
}
int best = 0;
if (size[1] < size[best])
best = 1;
if (size[2] < size[best])
best = 2;
if (best != 0) {
if (size[3] < size[best])
best = 3;
if (best == 2) {
if (size[4] < size[best]) {
best = 4;
if (size[5] < size[best])
best = 5;
}
}
}
if (best == 0) {
copy_buffer(cinfo, base_scan_idx);
copy_buffer(cinfo, base_scan_idx+1);
}
else {
copy_buffer(cinfo, base_scan_idx-2+4*best);
copy_buffer(cinfo, base_scan_idx-1+4*best);
copy_buffer(cinfo, base_scan_idx+0+4*best);
copy_buffer(cinfo, base_scan_idx-1+4*best);
}
base_scan_idx = cinfo->num_scans_luma + cinfo->num_scans_chroma_dc;
for (Al = cinfo->best_Al-1; Al >= 0; Al--) {
copy_buffer(cinfo, base_scan_idx + 4*(cinfo->Al_max_chroma+1) + 2*Al + 0);
copy_buffer(cinfo, base_scan_idx + 4*(cinfo->Al_max_chroma+1) + 2*Al + 1);
}
/* free the memory allocated for the chroma buffers */
for (i = cinfo->num_scans_luma; i < cinfo->num_scans; i++)
free(cinfo->scan_buffer[i]);
}
}
/*
* Finish up at end of pass.
*/
@@ -604,160 +768,7 @@ finish_pass_master (j_compress_ptr cinfo)
if (cinfo->optimize_scans) {
(*cinfo->dest->term_destination)(cinfo);
cinfo->dest = cinfo->saved_dest;
if (master->scan_number == 0) {
copy_buffer(cinfo, 0);
} else if (master->scan_number == 3*cinfo->Al_max_luma+2) {
int Al;
int size[4];
int i;
cinfo->best_Al = 0;
for (Al = 0; Al <= cinfo->Al_max_luma; Al++) {
size[Al] = cinfo->scan_size[1 + 2 * Al];
size[Al] += cinfo->scan_size[2 + 2 * Al];
for (i = 0; i < Al; i++)
size[Al] += cinfo->scan_size[3 + 2*cinfo->Al_max_luma + i];
if (size[Al] < size[cinfo->best_Al])
cinfo->best_Al = Al;
}
/* HACK! casting a const to a non-const :-( */
jpeg_scan_info *scanptr = (jpeg_scan_info *)&cinfo->scan_info[3*cinfo->Al_max_luma+3];
for (i = 0; i < 11; i++)
scanptr[i].Al = cinfo->best_Al;
} else if (master->scan_number == cinfo->num_scans_luma-1) {
int size[6];
int i;
int best = 0;
int scan_number_base = 3*cinfo->Al_max_luma+3;
int Al;
size[0] = cinfo->scan_size[scan_number_base];
for (i = 1; i < 6; i++) {
size[i] = cinfo->scan_size[scan_number_base+2*i-1];
size[i] += cinfo->scan_size[scan_number_base+2*i];
}
if (size[1] < size[best])
best = 1;
if (size[2] < size[best])
best = 2;
if (best != 0) {
if (size[3] < size[best])
best = 3;
if (best == 2) {
if (size[4] < size[best]) {
best = 4;
if (size[5] < size[best])
best = 5;
}
}
}
if (best == 0)
copy_buffer(cinfo, scan_number_base);
else {
copy_buffer(cinfo, scan_number_base+2*best-1);
copy_buffer(cinfo, scan_number_base+2*best);
}
/* copy the LSB refinements as well */
for (Al = cinfo->best_Al-1; Al >= 0; Al--)
copy_buffer(cinfo, 2*cinfo->Al_max_luma + 3 + Al);
/* free the memory allocated for the luma buffers */
for (i = 0; i < cinfo->num_scans_luma; i++)
free(cinfo->scan_buffer[i]);
} else if (master->scan_number == cinfo->num_scans_luma+2) {
if (cinfo->scan_size[cinfo->num_scans_luma] <= cinfo->scan_size[cinfo->num_scans_luma+1] + cinfo->scan_size[cinfo->num_scans_luma+2])
copy_buffer(cinfo, cinfo->num_scans_luma);
else {
copy_buffer(cinfo, cinfo->num_scans_luma+1);
copy_buffer(cinfo, cinfo->num_scans_luma+2);
}
} else if (master->scan_number == 41) {
int size[3];
size[0] = cinfo->scan_size[26] + cinfo->scan_size[27];
size[0] += cinfo->scan_size[28] + cinfo->scan_size[29];
size[1] = cinfo->scan_size[30] + cinfo->scan_size[31] + cinfo->scan_size[32];
size[1] += cinfo->scan_size[33] + cinfo->scan_size[34] + cinfo->scan_size[35];
size[2] = cinfo->scan_size[36] + cinfo->scan_size[37] + cinfo->scan_size[38] + cinfo->scan_size[39];
size[2] += cinfo->scan_size[40] + cinfo->scan_size[41] + cinfo->scan_size[34] + cinfo->scan_size[35];
int Al = 0;
int i;
for (i = 1; i <= 3; i++)
if (size[i] < size[Al])
Al = i;
cinfo->best_Al = Al;
jpeg_scan_info *scanptr = (jpeg_scan_info *)&cinfo->scan_info[42];
for (i = 0; i < 22; i++)
scanptr[i].Al = Al;
} else if (master->scan_number == 63) {
int size[6];
size[0] = cinfo->scan_size[42];
size[0] += cinfo->scan_size[43];
size[1] = cinfo->scan_size[44] + cinfo->scan_size[45];
size[1] += cinfo->scan_size[46] + cinfo->scan_size[47];
size[2] = cinfo->scan_size[48] + cinfo->scan_size[49];
size[2] += cinfo->scan_size[50] + cinfo->scan_size[51];
size[3] = cinfo->scan_size[52] + cinfo->scan_size[53];
size[3] += cinfo->scan_size[54] + cinfo->scan_size[55];
size[4] = cinfo->scan_size[56] + cinfo->scan_size[57];
size[4] += cinfo->scan_size[58] + cinfo->scan_size[59];
size[5] = cinfo->scan_size[60] + cinfo->scan_size[61];
size[5] += cinfo->scan_size[62] + cinfo->scan_size[63];
int best = 0;
if (size[1] < size[best])
best = 1;
if (size[2] < size[best])
best = 2;
if (best != 0) {
if (size[3] < size[best])
best = 3;
if (best == 2) {
if (size[4] < size[best]) {
best = 4;
if (size[5] < size[best])
best = 5;
}
}
}
if (best == 0) {
copy_buffer(cinfo, 42);
copy_buffer(cinfo, 43);
}
else {
copy_buffer(cinfo, 40+4*best);
copy_buffer(cinfo, 41+4*best);
copy_buffer(cinfo, 42+4*best);
copy_buffer(cinfo, 43+4*best);
}
if (cinfo->best_Al >= 2) {
copy_buffer(cinfo, 40);
copy_buffer(cinfo, 41);
}
if (cinfo->best_Al >= 1) {
copy_buffer(cinfo, 34);
copy_buffer(cinfo, 35);
}
int i;
for (i = 23; i < 64; i++)
free(cinfo->scan_buffer[i]);
}
select_scans(cinfo, master->scan_number + 1);
}
master->scan_number++;

103
jcparam.c
View File

@@ -661,10 +661,15 @@ jpeg_search_progression (j_compress_ptr cinfo)
if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
int Al;
int frequency_split[] = { 2, 8, 5, 12, 18 };
int i;
cinfo->Al_max_luma = 3;
cinfo->Al_max_chroma = 2;
cinfo->num_scans_luma = 3 * cinfo->Al_max_luma + 14;
cinfo->num_scans_luma_dc = 1;
cinfo->num_scans_chroma_dc = 3;
cinfo->num_frequency_splits = 5;
cinfo->num_scans_luma = cinfo->num_scans_luma_dc + (3 * cinfo->Al_max_luma + 2) + (2 * cinfo->num_frequency_splits + 1);
/* 23 scans for luma */
/* 1 scan for DC */
@@ -677,33 +682,20 @@ jpeg_search_progression (j_compress_ptr cinfo)
/* luma DC by itself */
scanptr = fill_dc_scans(scanptr, 1, 0, 0);
for (Al = 0; Al <= cinfo->Al_max_luma; Al++)
{
for (Al = 0; Al <= cinfo->Al_max_luma; Al++) {
scanptr = fill_a_scan(scanptr, 0, 1, 8, 0, Al);
scanptr = fill_a_scan(scanptr, 0, 9, 63, 0, Al);
}
for (Al = 0; Al < cinfo->Al_max_luma; Al++)
{
scanptr = fill_a_scan(scanptr, 0, 1, 63, Al+1, Al);
}
/* luma frequency split 1 */
for (Al = 0; Al < cinfo->Al_max_luma; Al++)
scanptr = fill_a_scan(scanptr, 0, 1, 63, Al+1, Al);
scanptr = fill_a_scan(scanptr, 0, 1, 63, 0, 0);
/* luma frequency split 2 */
scanptr = fill_a_scan(scanptr, 0, 1, 2, 0, 0);
scanptr = fill_a_scan(scanptr, 0, 3, 63, 0, 0);
/* luma frequency split 3 */
scanptr = fill_a_scan(scanptr, 0, 1, 8, 0, 0);
scanptr = fill_a_scan(scanptr, 0, 9, 63, 0, 0);
/* luma frequency split 4, don't do if 2 and 3 didn't help */
scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 0);
scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 0);
/* luma frequency split 5, do only if 3 is best */
scanptr = fill_a_scan(scanptr, 0, 1, 12, 0, 0);
scanptr = fill_a_scan(scanptr, 0, 13, 63, 0, 0);
/* luma frequency split 6, don't do if 5 didn't help */
scanptr = fill_a_scan(scanptr, 0, 1, 18, 0, 0);
scanptr = fill_a_scan(scanptr, 0, 19, 63, 0, 0);
for (i = 0; i < cinfo->num_frequency_splits; i++) {
scanptr = fill_a_scan(scanptr, 0, 1, frequency_split[i], 0, 0);
scanptr = fill_a_scan(scanptr, 0, frequency_split[i]+1, 63, 0, 0);
}
/* 41 scans for chroma */
@@ -712,53 +704,28 @@ jpeg_search_progression (j_compress_ptr cinfo)
/* chroma DC separate */
scanptr = fill_a_scan(scanptr, 1, 0, 0, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 0, 0, 0, 0);
/* chroma approximation 1 */
scanptr = fill_a_scan(scanptr, 1, 1, 8, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 9, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 8, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 9, 63, 0, 0);
/* chroma approximation 2 */
scanptr = fill_a_scan(scanptr, 1, 1, 8, 0, 1);
scanptr = fill_a_scan(scanptr, 1, 9, 63, 0, 1);
scanptr = fill_a_scan(scanptr, 2, 1, 8, 0, 1);
scanptr = fill_a_scan(scanptr, 2, 9, 63, 0, 1);
scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0);
/* chroma approximation 3 */
scanptr = fill_a_scan(scanptr, 1, 1, 8, 0, 2);
scanptr = fill_a_scan(scanptr, 1, 9, 63, 0, 2);
scanptr = fill_a_scan(scanptr, 2, 1, 8, 0, 2);
scanptr = fill_a_scan(scanptr, 2, 9, 63, 0, 2);
scanptr = fill_a_scan(scanptr, 1, 1, 63, 2, 1);
scanptr = fill_a_scan(scanptr, 2, 1, 63, 2, 1);
/* chroma frequency split 1 */
for (Al = 0; Al <= cinfo->Al_max_chroma; Al++) {
scanptr = fill_a_scan(scanptr, 1, 1, 8, 0, Al);
scanptr = fill_a_scan(scanptr, 1, 9, 63, 0, Al);
scanptr = fill_a_scan(scanptr, 2, 1, 8, 0, Al);
scanptr = fill_a_scan(scanptr, 2, 9, 63, 0, Al);
}
for (Al = 0; Al < cinfo->Al_max_chroma; Al++) {
scanptr = fill_a_scan(scanptr, 1, 1, 63, Al+1, Al);
scanptr = fill_a_scan(scanptr, 2, 1, 63, Al+1, Al);
}
scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 0);
/* chroma frequency split 2 */
scanptr = fill_a_scan(scanptr, 1, 1, 2, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 3, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 2, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 3, 63, 0, 0);
/* chroma frequency split 3 */
scanptr = fill_a_scan(scanptr, 1, 1, 8, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 9, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 8, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 9, 63, 0, 0);
/* chroma frequency split 4 */
scanptr = fill_a_scan(scanptr, 1, 1, 5, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 6, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 5, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 6, 63, 0, 0);
/* chroma frequency split 5 */
scanptr = fill_a_scan(scanptr, 1, 1, 12, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 13, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 12, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 13, 63, 0, 0);
/* chroma frequency split 6 */
scanptr = fill_a_scan(scanptr, 1, 1, 18, 0, 0);
scanptr = fill_a_scan(scanptr, 1, 19, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, 18, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 19, 63, 0, 0);
for (i = 0; i < cinfo->num_frequency_splits; i++) {
scanptr = fill_a_scan(scanptr, 1, 1, frequency_split[i], 0, 0);
scanptr = fill_a_scan(scanptr, 1, frequency_split[i]+1, 63, 0, 0);
scanptr = fill_a_scan(scanptr, 2, 1, frequency_split[i], 0, 0);
scanptr = fill_a_scan(scanptr, 2, frequency_split[i]+1, 63, 0, 0);
}
} else {
/* TODO */
}

View File

@@ -380,6 +380,10 @@ struct jpeg_compress_struct {
boolean optimize_scans; /* TRUE=optimize progressive coding scans */
int num_scans_luma; /* # of entries in scan_info array pertaining to luma (used when optimize_scans is TRUE */
int num_scans_luma_dc;
int num_scans_chroma_dc;
int num_frequency_splits;
struct jpeg_destination_mgr * saved_dest; /* saved value of dest */
unsigned char * scan_buffer[64]; /* buffer for a given scan */
unsigned long scan_size[64]; /* size for a given scan */