4  * Copyright (C) 1994-1996, Thomas G. Lane. 
   5  * This file is part of the Independent JPEG Group's software. 
   6  * For conditions of distribution and use, see the accompanying README file. 
   8  * This file contains the decompression postprocessing controller. 
   9  * This controller manages the upsampling, color conversion, and color 
  10  * quantization/reduction steps; specifically, it controls the buffering 
  11  * between upsample/color conversion and color quantization/reduction. 
  13  * If no color quantization/reduction is required, then this module has no 
  14  * work to do, and it just hands off to the upsample/color conversion code. 
  15  * An integrated upsample/convert/quantize process would replace this module 
  19 #define JPEG_INTERNALS 
  24 /* Private buffer controller object */ 
  27   struct jpeg_d_post_controller pub
; /* public fields */ 
  29   /* Color quantization source buffer: this holds output data from 
  30    * the upsample/color conversion step to be passed to the quantizer. 
  31    * For two-pass color quantization, we need a full-image buffer; 
  32    * for one-pass operation, a strip buffer is sufficient. 
  34   jvirt_sarray_ptr whole_image
; /* virtual array, or NULL if one-pass */ 
  35   JSAMPARRAY buffer
;            /* strip buffer, or current strip of virtual */ 
  36   JDIMENSION strip_height
;      /* buffer size in rows */ 
  37   /* for two-pass mode only: */ 
  38   JDIMENSION starting_row
;      /* row # of first row in current strip */ 
  39   JDIMENSION next_row
;          /* index of next row to fill/empty in strip */ 
  42 typedef my_post_controller 
* my_post_ptr
; 
  45 /* Forward declarations */ 
  46 METHODDEF(void) post_process_1pass
 
  47         JPP((j_decompress_ptr cinfo
, 
  48              JSAMPIMAGE input_buf
, JDIMENSION 
*in_row_group_ctr
, 
  49              JDIMENSION in_row_groups_avail
, 
  50              JSAMPARRAY output_buf
, JDIMENSION 
*out_row_ctr
, 
  51              JDIMENSION out_rows_avail
)); 
  52 #ifdef QUANT_2PASS_SUPPORTED 
  53 METHODDEF(void) post_process_prepass
 
  54         JPP((j_decompress_ptr cinfo
, 
  55              JSAMPIMAGE input_buf
, JDIMENSION 
*in_row_group_ctr
, 
  56              JDIMENSION in_row_groups_avail
, 
  57              JSAMPARRAY output_buf
, JDIMENSION 
*out_row_ctr
, 
  58              JDIMENSION out_rows_avail
)); 
  59 METHODDEF(void) post_process_2pass
 
  60         JPP((j_decompress_ptr cinfo
, 
  61              JSAMPIMAGE input_buf
, JDIMENSION 
*in_row_group_ctr
, 
  62              JDIMENSION in_row_groups_avail
, 
  63              JSAMPARRAY output_buf
, JDIMENSION 
*out_row_ctr
, 
  64              JDIMENSION out_rows_avail
)); 
  69  * Initialize for a processing pass. 
  73 start_pass_dpost (j_decompress_ptr cinfo
, J_BUF_MODE pass_mode
) 
  75   my_post_ptr post 
= (my_post_ptr
) cinfo
->post
; 
  79     if (cinfo
->quantize_colors
) { 
  80       /* Single-pass processing with color quantization. */ 
  81       post
->pub
.post_process_data 
= post_process_1pass
; 
  82       /* We could be doing buffered-image output before starting a 2-pass 
  83        * color quantization; in that case, jinit_d_post_controller did not 
  84        * allocate a strip buffer.  Use the virtual-array buffer as workspace. 
  86       if (post
->buffer 
== NULL
) { 
  87         post
->buffer 
= (*cinfo
->mem
->access_virt_sarray
) 
  88           ((j_common_ptr
) cinfo
, post
->whole_image
, 
  89            (JDIMENSION
) 0, post
->strip_height
, TRUE
); 
  92       /* For single-pass processing without color quantization, 
  93        * I have no work to do; just call the upsampler directly. 
  95       post
->pub
.post_process_data 
= cinfo
->upsample
->upsample
; 
  98 #ifdef QUANT_2PASS_SUPPORTED 
  99   case JBUF_SAVE_AND_PASS
: 
 100     /* First pass of 2-pass quantization */ 
 101     if (post
->whole_image 
== NULL
) 
 102       ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
 103     post
->pub
.post_process_data 
= post_process_prepass
; 
 105   case JBUF_CRANK_DEST
: 
 106     /* Second pass of 2-pass quantization */ 
 107     if (post
->whole_image 
== NULL
) 
 108       ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
 109     post
->pub
.post_process_data 
= post_process_2pass
; 
 111 #endif /* QUANT_2PASS_SUPPORTED */ 
 113     ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
 116   post
->starting_row 
= post
->next_row 
= 0; 
 121  * Process some data in the one-pass (strip buffer) case. 
 122  * This is used for color precision reduction as well as one-pass quantization. 
 126 post_process_1pass (j_decompress_ptr cinfo
, 
 127                     JSAMPIMAGE input_buf
, JDIMENSION 
*in_row_group_ctr
, 
 128                     JDIMENSION in_row_groups_avail
, 
 129                     JSAMPARRAY output_buf
, JDIMENSION 
*out_row_ctr
, 
 130                     JDIMENSION out_rows_avail
) 
 132   my_post_ptr post 
= (my_post_ptr
) cinfo
->post
; 
 133   JDIMENSION num_rows
, max_rows
; 
 135   /* Fill the buffer, but not more than what we can dump out in one go. */ 
 136   /* Note we rely on the upsampler to detect bottom of image. */ 
 137   max_rows 
= out_rows_avail 
- *out_row_ctr
; 
 138   if (max_rows 
> post
->strip_height
) 
 139     max_rows 
= post
->strip_height
; 
 141   (*cinfo
->upsample
->upsample
) (cinfo
, 
 142                 input_buf
, in_row_group_ctr
, in_row_groups_avail
, 
 143                 post
->buffer
, &num_rows
, max_rows
); 
 144   /* Quantize and emit data. */ 
 145   (*cinfo
->cquantize
->color_quantize
) (cinfo
, 
 146                 post
->buffer
, output_buf 
+ *out_row_ctr
, (int) num_rows
); 
 147   *out_row_ctr 
+= num_rows
; 
 151 #ifdef QUANT_2PASS_SUPPORTED 
 154  * Process some data in the first pass of 2-pass quantization. 
 158 post_process_prepass (j_decompress_ptr cinfo
, 
 159                       JSAMPIMAGE input_buf
, JDIMENSION 
*in_row_group_ctr
, 
 160                       JDIMENSION in_row_groups_avail
, 
 161                       JSAMPARRAY output_buf
, JDIMENSION 
*out_row_ctr
, 
 162                       JDIMENSION out_rows_avail
) 
 164   my_post_ptr post 
= (my_post_ptr
) cinfo
->post
; 
 165   JDIMENSION old_next_row
, num_rows
; 
 167   /* Reposition virtual buffer if at start of strip. */ 
 168   if (post
->next_row 
== 0) { 
 169     post
->buffer 
= (*cinfo
->mem
->access_virt_sarray
) 
 170         ((j_common_ptr
) cinfo
, post
->whole_image
, 
 171          post
->starting_row
, post
->strip_height
, TRUE
); 
 174   /* Upsample some data (up to a strip height's worth). */ 
 175   old_next_row 
= post
->next_row
; 
 176   (*cinfo
->upsample
->upsample
) (cinfo
, 
 177                 input_buf
, in_row_group_ctr
, in_row_groups_avail
, 
 178                 post
->buffer
, &post
->next_row
, post
->strip_height
); 
 180   /* Allow quantizer to scan new data.  No data is emitted, */ 
 181   /* but we advance out_row_ctr so outer loop can tell when we're done. */ 
 182   if (post
->next_row 
> old_next_row
) { 
 183     num_rows 
= post
->next_row 
- old_next_row
; 
 184     (*cinfo
->cquantize
->color_quantize
) (cinfo
, post
->buffer 
+ old_next_row
, 
 185                                          (JSAMPARRAY
) NULL
, (int) num_rows
); 
 186     *out_row_ctr 
+= num_rows
; 
 189   /* Advance if we filled the strip. */ 
 190   if (post
->next_row 
>= post
->strip_height
) { 
 191     post
->starting_row 
+= post
->strip_height
; 
 198  * Process some data in the second pass of 2-pass quantization. 
 202 post_process_2pass (j_decompress_ptr cinfo
, 
 203                     JSAMPIMAGE input_buf
, JDIMENSION 
*in_row_group_ctr
, 
 204                     JDIMENSION in_row_groups_avail
, 
 205                     JSAMPARRAY output_buf
, JDIMENSION 
*out_row_ctr
, 
 206                     JDIMENSION out_rows_avail
) 
 208   my_post_ptr post 
= (my_post_ptr
) cinfo
->post
; 
 209   JDIMENSION num_rows
, max_rows
; 
 211   /* Reposition virtual buffer if at start of strip. */ 
 212   if (post
->next_row 
== 0) { 
 213     post
->buffer 
= (*cinfo
->mem
->access_virt_sarray
) 
 214         ((j_common_ptr
) cinfo
, post
->whole_image
, 
 215          post
->starting_row
, post
->strip_height
, FALSE
); 
 218   /* Determine number of rows to emit. */ 
 219   num_rows 
= post
->strip_height 
- post
->next_row
; /* available in strip */ 
 220   max_rows 
= out_rows_avail 
- *out_row_ctr
; /* available in output area */ 
 221   if (num_rows 
> max_rows
) 
 223   /* We have to check bottom of image here, can't depend on upsampler. */ 
 224   max_rows 
= cinfo
->output_height 
- post
->starting_row
; 
 225   if (num_rows 
> max_rows
) 
 228   /* Quantize and emit data. */ 
 229   (*cinfo
->cquantize
->color_quantize
) (cinfo
, 
 230                 post
->buffer 
+ post
->next_row
, output_buf 
+ *out_row_ctr
, 
 232   *out_row_ctr 
+= num_rows
; 
 234   /* Advance if we filled the strip. */ 
 235   post
->next_row 
+= num_rows
; 
 236   if (post
->next_row 
>= post
->strip_height
) { 
 237     post
->starting_row 
+= post
->strip_height
; 
 242 #endif /* QUANT_2PASS_SUPPORTED */ 
 246  * Initialize postprocessing controller. 
 250 jinit_d_post_controller (j_decompress_ptr cinfo
, boolean need_full_buffer
) 
 255     (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 256                                 SIZEOF(my_post_controller
)); 
 257   cinfo
->post 
= (struct jpeg_d_post_controller 
*) post
; 
 258   post
->pub
.start_pass 
= start_pass_dpost
; 
 259   post
->whole_image 
= NULL
;     /* flag for no virtual arrays */ 
 260   post
->buffer 
= NULL
;          /* flag for no strip buffer */ 
 262   /* Create the quantization buffer, if needed */ 
 263   if (cinfo
->quantize_colors
) { 
 264     /* The buffer strip height is max_v_samp_factor, which is typically 
 265      * an efficient number of rows for upsampling to return. 
 266      * (In the presence of output rescaling, we might want to be smarter?) 
 268     post
->strip_height 
= (JDIMENSION
) cinfo
->max_v_samp_factor
; 
 269     if (need_full_buffer
) { 
 270       /* Two-pass color quantization: need full-image storage. */ 
 271       /* We round up the number of rows to a multiple of the strip height. */ 
 272 #ifdef QUANT_2PASS_SUPPORTED 
 273       post
->whole_image 
= (*cinfo
->mem
->request_virt_sarray
) 
 274         ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, FALSE
, 
 275          cinfo
->output_width 
* cinfo
->out_color_components
, 
 276          (JDIMENSION
) jround_up((long) cinfo
->output_height
, 
 277                                 (long) post
->strip_height
), 
 280       ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
 281 #endif /* QUANT_2PASS_SUPPORTED */ 
 283       /* One-pass color quantization: just make a strip buffer. */ 
 284       post
->buffer 
= (*cinfo
->mem
->alloc_sarray
) 
 285         ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 286          cinfo
->output_width 
* cinfo
->out_color_components
,