diff --git a/jcmaster.c b/jcmaster.c index 19b20616..47d7387e 100644 --- a/jcmaster.c +++ b/jcmaster.c @@ -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++; diff --git a/jcparam.c b/jcparam.c index c47b97d6..781679f2 100644 --- a/jcparam.c +++ b/jcparam.c @@ -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 */ } diff --git a/jpeglib.h b/jpeglib.h index cccc9c03..41fbedfa 100644 --- a/jpeglib.h +++ b/jpeglib.h @@ -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 */