Home | History | Annotate | Download | only in libjpeg
      1 #if !defined(_FX_JPEG_TURBO_)
      2 /*
      3  * jdpostct.c
      4  *
      5  * Copyright (C) 1994-1996, Thomas G. Lane.
      6  * This file is part of the Independent JPEG Group's software.
      7  * For conditions of distribution and use, see the accompanying README file.
      8  *
      9  * This file contains the decompression postprocessing controller.
     10  * This controller manages the upsampling, color conversion, and color
     11  * quantization/reduction steps; specifically, it controls the buffering
     12  * between upsample/color conversion and color quantization/reduction.
     13  *
     14  * If no color quantization/reduction is required, then this module has no
     15  * work to do, and it just hands off to the upsample/color conversion code.
     16  * An integrated upsample/convert/quantize process would replace this module
     17  * entirely.
     18  */
     19 
     20 #define JPEG_INTERNALS
     21 #include "jinclude.h"
     22 #include "jpeglib.h"
     23 
     24 
     25 /* Private buffer controller object */
     26 
     27 typedef struct {
     28   struct jpeg_d_post_controller pub; /* public fields */
     29 
     30   /* Color quantization source buffer: this holds output data from
     31    * the upsample/color conversion step to be passed to the quantizer.
     32    * For two-pass color quantization, we need a full-image buffer;
     33    * for one-pass operation, a strip buffer is sufficient.
     34    */
     35   jvirt_sarray_ptr whole_image;	/* virtual array, or NULL if one-pass */
     36   JSAMPARRAY buffer;		/* strip buffer, or current strip of virtual */
     37   JDIMENSION strip_height;	/* buffer size in rows */
     38   /* for two-pass mode only: */
     39   JDIMENSION starting_row;	/* row # of first row in current strip */
     40   JDIMENSION next_row;		/* index of next row to fill/empty in strip */
     41 } my_post_controller;
     42 
     43 typedef my_post_controller * my_post_ptr;
     44 
     45 
     46 /* Forward declarations */
     47 METHODDEF(void) post_process_1pass
     48 	JPP((j_decompress_ptr cinfo,
     49 	     JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
     50 	     JDIMENSION in_row_groups_avail,
     51 	     JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
     52 	     JDIMENSION out_rows_avail));
     53 #ifdef QUANT_2PASS_SUPPORTED
     54 METHODDEF(void) post_process_prepass
     55 	JPP((j_decompress_ptr cinfo,
     56 	     JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
     57 	     JDIMENSION in_row_groups_avail,
     58 	     JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
     59 	     JDIMENSION out_rows_avail));
     60 METHODDEF(void) post_process_2pass
     61 	JPP((j_decompress_ptr cinfo,
     62 	     JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
     63 	     JDIMENSION in_row_groups_avail,
     64 	     JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
     65 	     JDIMENSION out_rows_avail));
     66 #endif
     67 
     68 
     69 /*
     70  * Initialize for a processing pass.
     71  */
     72 
     73 METHODDEF(void)
     74 start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
     75 {
     76   my_post_ptr post = (my_post_ptr) cinfo->post;
     77 
     78   switch (pass_mode) {
     79   case JBUF_PASS_THRU:
     80     if (cinfo->quantize_colors) {
     81       /* Single-pass processing with color quantization. */
     82       post->pub.post_process_data = post_process_1pass;
     83       /* We could be doing buffered-image output before starting a 2-pass
     84        * color quantization; in that case, jinit_d_post_controller did not
     85        * allocate a strip buffer.  Use the virtual-array buffer as workspace.
     86        */
     87       if (post->buffer == NULL) {
     88 	post->buffer = (*cinfo->mem->access_virt_sarray)
     89 	  ((j_common_ptr) cinfo, post->whole_image,
     90 	   (JDIMENSION) 0, post->strip_height, TRUE);
     91       }
     92     } else {
     93       /* For single-pass processing without color quantization,
     94        * I have no work to do; just call the upsampler directly.
     95        */
     96       post->pub.post_process_data = cinfo->upsample->upsample;
     97     }
     98     break;
     99 #ifdef QUANT_2PASS_SUPPORTED
    100   case JBUF_SAVE_AND_PASS:
    101     /* First pass of 2-pass quantization */
    102     if (post->whole_image == NULL)
    103       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    104     post->pub.post_process_data = post_process_prepass;
    105     break;
    106   case JBUF_CRANK_DEST:
    107     /* Second pass of 2-pass quantization */
    108     if (post->whole_image == NULL)
    109       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    110     post->pub.post_process_data = post_process_2pass;
    111     break;
    112 #endif /* QUANT_2PASS_SUPPORTED */
    113   default:
    114     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    115     break;
    116   }
    117   post->starting_row = post->next_row = 0;
    118 }
    119 
    120 
    121 /*
    122  * Process some data in the one-pass (strip buffer) case.
    123  * This is used for color precision reduction as well as one-pass quantization.
    124  */
    125 
    126 METHODDEF(void)
    127 post_process_1pass (j_decompress_ptr cinfo,
    128 		    JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
    129 		    JDIMENSION in_row_groups_avail,
    130 		    JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
    131 		    JDIMENSION out_rows_avail)
    132 {
    133   my_post_ptr post = (my_post_ptr) cinfo->post;
    134   JDIMENSION num_rows, max_rows;
    135 
    136   /* Fill the buffer, but not more than what we can dump out in one go. */
    137   /* Note we rely on the upsampler to detect bottom of image. */
    138   max_rows = out_rows_avail - *out_row_ctr;
    139   if (max_rows > post->strip_height)
    140     max_rows = post->strip_height;
    141   num_rows = 0;
    142   (*cinfo->upsample->upsample) (cinfo,
    143 		input_buf, in_row_group_ctr, in_row_groups_avail,
    144 		post->buffer, &num_rows, max_rows);
    145   /* Quantize and emit data. */
    146   (*cinfo->cquantize->color_quantize) (cinfo,
    147 		post->buffer, output_buf + *out_row_ctr, (int) num_rows);
    148   *out_row_ctr += num_rows;
    149 }
    150 
    151 
    152 #ifdef QUANT_2PASS_SUPPORTED
    153 
    154 /*
    155  * Process some data in the first pass of 2-pass quantization.
    156  */
    157 
    158 METHODDEF(void)
    159 post_process_prepass (j_decompress_ptr cinfo,
    160 		      JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
    161 		      JDIMENSION in_row_groups_avail,
    162 		      JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
    163 		      JDIMENSION out_rows_avail)
    164 {
    165   my_post_ptr post = (my_post_ptr) cinfo->post;
    166   JDIMENSION old_next_row, num_rows;
    167 
    168   /* Reposition virtual buffer if at start of strip. */
    169   if (post->next_row == 0) {
    170     post->buffer = (*cinfo->mem->access_virt_sarray)
    171 	((j_common_ptr) cinfo, post->whole_image,
    172 	 post->starting_row, post->strip_height, TRUE);
    173   }
    174 
    175   /* Upsample some data (up to a strip height's worth). */
    176   old_next_row = post->next_row;
    177   (*cinfo->upsample->upsample) (cinfo,
    178 		input_buf, in_row_group_ctr, in_row_groups_avail,
    179 		post->buffer, &post->next_row, post->strip_height);
    180 
    181   /* Allow quantizer to scan new data.  No data is emitted, */
    182   /* but we advance out_row_ctr so outer loop can tell when we're done. */
    183   if (post->next_row > old_next_row) {
    184     num_rows = post->next_row - old_next_row;
    185     (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
    186 					 (JSAMPARRAY) NULL, (int) num_rows);
    187     *out_row_ctr += num_rows;
    188   }
    189 
    190   /* Advance if we filled the strip. */
    191   if (post->next_row >= post->strip_height) {
    192     post->starting_row += post->strip_height;
    193     post->next_row = 0;
    194   }
    195 }
    196 
    197 
    198 /*
    199  * Process some data in the second pass of 2-pass quantization.
    200  */
    201 
    202 METHODDEF(void)
    203 post_process_2pass (j_decompress_ptr cinfo,
    204 		    JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
    205 		    JDIMENSION in_row_groups_avail,
    206 		    JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
    207 		    JDIMENSION out_rows_avail)
    208 {
    209   my_post_ptr post = (my_post_ptr) cinfo->post;
    210   JDIMENSION num_rows, max_rows;
    211 
    212   /* Reposition virtual buffer if at start of strip. */
    213   if (post->next_row == 0) {
    214     post->buffer = (*cinfo->mem->access_virt_sarray)
    215 	((j_common_ptr) cinfo, post->whole_image,
    216 	 post->starting_row, post->strip_height, FALSE);
    217   }
    218 
    219   /* Determine number of rows to emit. */
    220   num_rows = post->strip_height - post->next_row; /* available in strip */
    221   max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
    222   if (num_rows > max_rows)
    223     num_rows = max_rows;
    224   /* We have to check bottom of image here, can't depend on upsampler. */
    225   max_rows = cinfo->output_height - post->starting_row;
    226   if (num_rows > max_rows)
    227     num_rows = max_rows;
    228 
    229   /* Quantize and emit data. */
    230   (*cinfo->cquantize->color_quantize) (cinfo,
    231 		post->buffer + post->next_row, output_buf + *out_row_ctr,
    232 		(int) num_rows);
    233   *out_row_ctr += num_rows;
    234 
    235   /* Advance if we filled the strip. */
    236   post->next_row += num_rows;
    237   if (post->next_row >= post->strip_height) {
    238     post->starting_row += post->strip_height;
    239     post->next_row = 0;
    240   }
    241 }
    242 
    243 #endif /* QUANT_2PASS_SUPPORTED */
    244 
    245 
    246 /*
    247  * Initialize postprocessing controller.
    248  */
    249 
    250 GLOBAL(void)
    251 jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
    252 {
    253   my_post_ptr post;
    254 
    255   post = (my_post_ptr)
    256     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
    257 				SIZEOF(my_post_controller));
    258   cinfo->post = (struct jpeg_d_post_controller *) post;
    259   post->pub.start_pass = start_pass_dpost;
    260   post->whole_image = NULL;	/* flag for no virtual arrays */
    261   post->buffer = NULL;		/* flag for no strip buffer */
    262 
    263   /* Create the quantization buffer, if needed */
    264   if (cinfo->quantize_colors) {
    265     /* The buffer strip height is max_v_samp_factor, which is typically
    266      * an efficient number of rows for upsampling to return.
    267      * (In the presence of output rescaling, we might want to be smarter?)
    268      */
    269     post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
    270     if (need_full_buffer) {
    271       /* Two-pass color quantization: need full-image storage. */
    272       /* We round up the number of rows to a multiple of the strip height. */
    273 #ifdef QUANT_2PASS_SUPPORTED
    274       post->whole_image = (*cinfo->mem->request_virt_sarray)
    275 	((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
    276 	 cinfo->output_width * cinfo->out_color_components,
    277 	 (JDIMENSION) jround_up((long) cinfo->output_height,
    278 				(long) post->strip_height),
    279 	 post->strip_height);
    280 #else
    281       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
    282 #endif /* QUANT_2PASS_SUPPORTED */
    283     } else {
    284       /* One-pass color quantization: just make a strip buffer. */
    285       post->buffer = (*cinfo->mem->alloc_sarray)
    286 	((j_common_ptr) cinfo, JPOOL_IMAGE,
    287 	 cinfo->output_width * cinfo->out_color_components,
    288 	 post->strip_height);
    289     }
    290   }
    291 }
    292 
    293 #endif //_FX_JPEG_TURBO_
    294