diff --git a/jcapistd.c b/jcapistd.c index c0320b1b..a0dbf8be 100644 --- a/jcapistd.c +++ b/jcapistd.c @@ -3,6 +3,8 @@ * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. + * mozjpeg Modifications: + * Copyright (C) 2014, Mozilla Corporation. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the compression half @@ -43,6 +45,10 @@ jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) if (write_all_tables) jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + /* setting up scan optimisation pattern failed, disable scan optimisation */ + if (cinfo->num_scans_luma == 0) + cinfo->optimize_scans = FALSE; + /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); diff --git a/jcmaster.c b/jcmaster.c index 47d7387e..1f7b80f6 100644 --- a/jcmaster.c +++ b/jcmaster.c @@ -644,92 +644,95 @@ select_scans (j_compress_ptr cinfo, int next_scan_number) 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; + } else if (cinfo->num_scans > 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]; + if (next_scan_number == cinfo->num_scans_luma+cinfo->num_scans_chroma_dc) { + base_scan_idx = cinfo->num_scans_luma; - 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 (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); } - 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; + } 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]); } - - 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]); } } diff --git a/jcparam.c b/jcparam.c index 781679f2..4621c979 100644 --- a/jcparam.c +++ b/jcparam.c @@ -612,12 +612,15 @@ fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) * cinfo->num_components and cinfo->jpeg_color_space must be correct. */ -LOCAL(void) +LOCAL(boolean) jpeg_search_progression (j_compress_ptr cinfo) { int ncomps = cinfo->num_components; int nscans; jpeg_scan_info * scanptr; + int Al; + int frequency_split[] = { 2, 8, 5, 12, 18 }; + int i; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) @@ -627,19 +630,11 @@ jpeg_search_progression (j_compress_ptr cinfo) if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { /* Custom script for YCbCr color images. */ nscans = 64; + } else if (ncomps == 1) { + nscans = 23; } else { - /* All-purpose script for other color spaces. */ - if (cinfo->use_moz_defaults) { - if (ncomps > MAX_COMPS_IN_SCAN) - nscans = 5 * ncomps; /* 2 DC + 4 AC scans per component */ - else - nscans = 1 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ - } else { - if (ncomps > MAX_COMPS_IN_SCAN) - nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ - else - nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ - } + cinfo->num_scans_luma = 0; + return FALSE; } /* Allocate space for script. @@ -650,7 +645,7 @@ jpeg_search_progression (j_compress_ptr cinfo) * enough space to handle YCbCr even if initially asked for grayscale. */ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { - cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space_size = MAX(nscans, 64); cinfo->script_space = (jpeg_scan_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, cinfo->script_space_size * SIZEOF(jpeg_scan_info)); @@ -659,44 +654,43 @@ jpeg_search_progression (j_compress_ptr cinfo) cinfo->scan_info = scanptr; cinfo->num_scans = nscans; - 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_luma = 3; + cinfo->num_scans_luma_dc = 1; + 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 */ + /* 11 scans to determine successive approximation */ + /* 11 scans to determine frequency approximation */ + /* after 12 scans need to update following 11 */ + /* after 23 scans need to determine which to keep */ + /* last 4 done conditionally */ + + /* luma DC by itself */ + scanptr = fill_dc_scans(scanptr, 1, 0, 0); + + 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); + + scanptr = fill_a_scan(scanptr, 0, 1, 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); + } + + if (ncomps == 1) { + cinfo->Al_max_chroma = 0; + cinfo->num_scans_chroma_dc = 0; + } else { cinfo->Al_max_chroma = 2; - 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 */ - /* 11 scans to determine successive approximation */ - /* 11 scans to determine frequency approximation */ - /* after 12 scans need to update following 11 */ - /* after 23 scans need to determine which to keep */ - /* last 4 done conditionally */ - - /* luma DC by itself */ - scanptr = fill_dc_scans(scanptr, 1, 0, 0); - - 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); - - scanptr = fill_a_scan(scanptr, 0, 1, 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 */ /* chroma DC combined */ @@ -726,9 +720,9 @@ jpeg_search_progression (j_compress_ptr cinfo) 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 */ } + + return TRUE; } /* @@ -740,9 +734,10 @@ GLOBAL(void) jpeg_simple_progression (j_compress_ptr cinfo) { if (cinfo->optimize_scans) { - jpeg_search_progression(cinfo); - return; + if (jpeg_search_progression(cinfo) == TRUE) + return; } + int ncomps = cinfo->num_components; int nscans; jpeg_scan_info * scanptr;