diff options
Diffstat (limited to 'jcmarker.c')
-rw-r--r-- | jcmarker.c | 82 |
1 files changed, 58 insertions, 24 deletions
@@ -1,7 +1,7 @@ /* * jcmarker.c * - * Copyright (C) 1991-1994, Thomas G. Lane. + * Copyright (C) 1991-1995, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -295,7 +295,7 @@ LOCAL void emit_sos (j_compress_ptr cinfo) /* Emit a SOS marker */ { - int i; + int i, td, ta; jpeg_component_info *compptr; emit_marker(cinfo, M_SOS); @@ -307,12 +307,28 @@ emit_sos (j_compress_ptr cinfo) for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; emit_byte(cinfo, compptr->component_id); - emit_byte(cinfo, (compptr->dc_tbl_no << 4) + compptr->ac_tbl_no); + td = compptr->dc_tbl_no; + ta = compptr->ac_tbl_no; + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan; + * furthermore, Huffman coding of DC refinement uses no table at all. + * We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + if (cinfo->Ss == 0) { + ta = 0; /* DC scan */ + if (cinfo->Ah != 0 && !cinfo->arith_code) + td = 0; /* no DC table either */ + } else { + td = 0; /* AC scan */ + } + } + emit_byte(cinfo, (td << 4) + ta); } - emit_byte(cinfo, 0); /* Spectral selection start */ - emit_byte(cinfo, DCTSIZE2-1); /* Spectral selection end */ - emit_byte(cinfo, 0); /* Successive approximation */ + emit_byte(cinfo, cinfo->Ss); + emit_byte(cinfo, cinfo->Se); + emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); } @@ -434,7 +450,7 @@ write_any_marker (j_compress_ptr cinfo, int marker, * be used for any other JPEG colorspace. The Adobe marker is helpful * to distinguish RGB, CMYK, and YCCK colorspaces. * Note that an application can write additional header markers after - * jpeg_start_decompress returns. + * jpeg_start_compress returns. */ METHODDEF void @@ -477,27 +493,34 @@ write_frame_header (j_compress_ptr cinfo) /* Check for a non-baseline specification. * Note we assume that Huffman table numbers won't be changed later. */ - is_baseline = TRUE; - if (cinfo->arith_code || (cinfo->data_precision != 8)) + if (cinfo->arith_code || cinfo->progressive_mode || + cinfo->data_precision != 8) { is_baseline = FALSE; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { is_baseline = FALSE; - } - if (prec && is_baseline) { - is_baseline = FALSE; - /* If it's baseline except for quantizer size, warn the user */ - TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + /* If it's baseline except for quantizer size, warn the user */ + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } } /* Emit the proper SOF marker */ - if (cinfo->arith_code) + if (cinfo->arith_code) { emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ - else if (is_baseline) - emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ - else - emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } else { + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } } @@ -525,8 +548,19 @@ write_scan_header (j_compress_ptr cinfo) */ for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } else { + /* Sequential mode: need both DC and AC tables */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } } } |