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 compression preprocessing controller. 
   9  * This controller manages the color conversion, downsampling, 
  10  * and edge expansion steps. 
  12  * Most of the complexity here is associated with buffering input rows 
  13  * as required by the downsampler.  See the comments at the head of 
  14  * jcsample.c for the downsampler's needs. 
  17 #define JPEG_INTERNALS 
  22 /* At present, jcsample.c can request context rows only for smoothing. 
  23  * In the future, we might also need context rows for CCIR601 sampling 
  24  * or other more-complex downsampling procedures.  The code to support 
  25  * context rows should be compiled only if needed. 
  27 #ifdef INPUT_SMOOTHING_SUPPORTED 
  28 #define CONTEXT_ROWS_SUPPORTED 
  33  * For the simple (no-context-row) case, we just need to buffer one 
  34  * row group's worth of pixels for the downsampling step.  At the bottom of 
  35  * the image, we pad to a full row group by replicating the last pixel row. 
  36  * The downsampler's last output row is then replicated if needed to pad 
  37  * out to a full iMCU row. 
  39  * When providing context rows, we must buffer three row groups' worth of 
  40  * pixels.  Three row groups are physically allocated, but the row pointer 
  41  * arrays are made five row groups high, with the extra pointers above and 
  42  * below "wrapping around" to point to the last and first real row groups. 
  43  * This allows the downsampler to access the proper context rows. 
  44  * At the top and bottom of the image, we create dummy context rows by 
  45  * copying the first or last real pixel row.  This copying could be avoided 
  46  * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the 
  47  * trouble on the compression side. 
  51 /* Private buffer controller object */ 
  54   struct jpeg_c_prep_controller pub
; /* public fields */ 
  56   /* Downsampling input buffer.  This buffer holds color-converted data 
  57    * until we have enough to do a downsample step. 
  59   JSAMPARRAY color_buf
[MAX_COMPONENTS
]; 
  61   JDIMENSION rows_to_go
;        /* counts rows remaining in source image */ 
  62   int next_buf_row
;             /* index of next row to store in color_buf */ 
  64 #ifdef CONTEXT_ROWS_SUPPORTED   /* only needed for context case */ 
  65   int this_row_group
;           /* starting row index of group to process */ 
  66   int next_buf_stop
;            /* downsample when we reach this index */ 
  70 typedef my_prep_controller 
* my_prep_ptr
; 
  74  * Initialize for a processing pass. 
  78 start_pass_prep (j_compress_ptr cinfo
, J_BUF_MODE pass_mode
) 
  80   my_prep_ptr prep 
= (my_prep_ptr
) cinfo
->prep
; 
  82   if (pass_mode 
!= JBUF_PASS_THRU
) 
  83     ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
  85   /* Initialize total-height counter for detecting bottom of image */ 
  86   prep
->rows_to_go 
= cinfo
->image_height
; 
  87   /* Mark the conversion buffer empty */ 
  88   prep
->next_buf_row 
= 0; 
  89 #ifdef CONTEXT_ROWS_SUPPORTED 
  90   /* Preset additional state variables for context mode. 
  91    * These aren't used in non-context mode, so we needn't test which mode. 
  93   prep
->this_row_group 
= 0; 
  94   /* Set next_buf_stop to stop after two row groups have been read in. */ 
  95   prep
->next_buf_stop 
= 2 * cinfo
->max_v_samp_factor
; 
 101  * Expand an image vertically from height input_rows to height output_rows, 
 102  * by duplicating the bottom row. 
 106 expand_bottom_edge (JSAMPARRAY image_data
, JDIMENSION num_cols
, 
 107                     int input_rows
, int output_rows
) 
 111   for (row 
= input_rows
; row 
< output_rows
; row
++) { 
 112     jcopy_sample_rows(image_data
, input_rows
-1, image_data
, row
, 
 119  * Process some data in the simple no-context case. 
 121  * Preprocessor output data is counted in "row groups".  A row group 
 122  * is defined to be v_samp_factor sample rows of each component. 
 123  * Downsampling will produce this much data from each max_v_samp_factor 
 128 pre_process_data (j_compress_ptr cinfo
, 
 129                   JSAMPARRAY input_buf
, JDIMENSION 
*in_row_ctr
, 
 130                   JDIMENSION in_rows_avail
, 
 131                   JSAMPIMAGE output_buf
, JDIMENSION 
*out_row_group_ctr
, 
 132                   JDIMENSION out_row_groups_avail
) 
 134   my_prep_ptr prep 
= (my_prep_ptr
) cinfo
->prep
; 
 137   jpeg_component_info 
* compptr
; 
 139   while (*in_row_ctr 
< in_rows_avail 
&& 
 140          *out_row_group_ctr 
< out_row_groups_avail
) { 
 141     /* Do color conversion to fill the conversion buffer. */ 
 142     inrows 
= in_rows_avail 
- *in_row_ctr
; 
 143     numrows 
= cinfo
->max_v_samp_factor 
- prep
->next_buf_row
; 
 144     numrows 
= (int) MIN((JDIMENSION
) numrows
, inrows
); 
 145     (*cinfo
->cconvert
->color_convert
) (cinfo
, input_buf 
+ *in_row_ctr
, 
 147                                        (JDIMENSION
) prep
->next_buf_row
, 
 149     *in_row_ctr 
+= numrows
; 
 150     prep
->next_buf_row 
+= numrows
; 
 151     prep
->rows_to_go 
-= numrows
; 
 152     /* If at bottom of image, pad to fill the conversion buffer. */ 
 153     if (prep
->rows_to_go 
== 0 && 
 154         prep
->next_buf_row 
< cinfo
->max_v_samp_factor
) { 
 155       for (ci 
= 0; ci 
< cinfo
->num_components
; ci
++) { 
 156         expand_bottom_edge(prep
->color_buf
[ci
], cinfo
->image_width
, 
 157                            prep
->next_buf_row
, cinfo
->max_v_samp_factor
); 
 159       prep
->next_buf_row 
= cinfo
->max_v_samp_factor
; 
 161     /* If we've filled the conversion buffer, empty it. */ 
 162     if (prep
->next_buf_row 
== cinfo
->max_v_samp_factor
) { 
 163       (*cinfo
->downsample
->downsample
) (cinfo
, 
 164                                         prep
->color_buf
, (JDIMENSION
) 0, 
 165                                         output_buf
, *out_row_group_ctr
); 
 166       prep
->next_buf_row 
= 0; 
 167       (*out_row_group_ctr
)++; 
 169     /* If at bottom of image, pad the output to a full iMCU height. 
 170      * Note we assume the caller is providing a one-iMCU-height output buffer! 
 172     if (prep
->rows_to_go 
== 0 && 
 173         *out_row_group_ctr 
< out_row_groups_avail
) { 
 174       for (ci 
= 0, compptr 
= cinfo
->comp_info
; ci 
< cinfo
->num_components
; 
 176         expand_bottom_edge(output_buf
[ci
], 
 177                            compptr
->width_in_blocks 
* DCTSIZE
, 
 178                            (int) (*out_row_group_ctr 
* compptr
->v_samp_factor
), 
 179                            (int) (out_row_groups_avail 
* compptr
->v_samp_factor
)); 
 181       *out_row_group_ctr 
= out_row_groups_avail
; 
 182       break;                    /* can exit outer loop without test */ 
 188 #ifdef CONTEXT_ROWS_SUPPORTED 
 191  * Process some data in the context case. 
 195 pre_process_context (j_compress_ptr cinfo
, 
 196                      JSAMPARRAY input_buf
, JDIMENSION 
*in_row_ctr
, 
 197                      JDIMENSION in_rows_avail
, 
 198                      JSAMPIMAGE output_buf
, JDIMENSION 
*out_row_group_ctr
, 
 199                      JDIMENSION out_row_groups_avail
) 
 201   my_prep_ptr prep 
= (my_prep_ptr
) cinfo
->prep
; 
 203   int buf_height 
= cinfo
->max_v_samp_factor 
* 3; 
 206   while (*out_row_group_ctr 
< out_row_groups_avail
) { 
 207     if (*in_row_ctr 
< in_rows_avail
) { 
 208       /* Do color conversion to fill the conversion buffer. */ 
 209       inrows 
= in_rows_avail 
- *in_row_ctr
; 
 210       numrows 
= prep
->next_buf_stop 
- prep
->next_buf_row
; 
 211       numrows 
= (int) MIN((JDIMENSION
) numrows
, inrows
); 
 212       (*cinfo
->cconvert
->color_convert
) (cinfo
, input_buf 
+ *in_row_ctr
, 
 214                                          (JDIMENSION
) prep
->next_buf_row
, 
 216       /* Pad at top of image, if first time through */ 
 217       if (prep
->rows_to_go 
== cinfo
->image_height
) { 
 218         for (ci 
= 0; ci 
< cinfo
->num_components
; ci
++) { 
 220           for (row 
= 1; row 
<= cinfo
->max_v_samp_factor
; row
++) { 
 221             jcopy_sample_rows(prep
->color_buf
[ci
], 0, 
 222                               prep
->color_buf
[ci
], -row
, 
 223                               1, cinfo
->image_width
); 
 227       *in_row_ctr 
+= numrows
; 
 228       prep
->next_buf_row 
+= numrows
; 
 229       prep
->rows_to_go 
-= numrows
; 
 231       /* Return for more data, unless we are at the bottom of the image. */ 
 232       if (prep
->rows_to_go 
!= 0) 
 234       /* When at bottom of image, pad to fill the conversion buffer. */ 
 235       if (prep
->next_buf_row 
< prep
->next_buf_stop
) { 
 236         for (ci 
= 0; ci 
< cinfo
->num_components
; ci
++) { 
 237           expand_bottom_edge(prep
->color_buf
[ci
], cinfo
->image_width
, 
 238                              prep
->next_buf_row
, prep
->next_buf_stop
); 
 240         prep
->next_buf_row 
= prep
->next_buf_stop
; 
 243     /* If we've gotten enough data, downsample a row group. */ 
 244     if (prep
->next_buf_row 
== prep
->next_buf_stop
) { 
 245       (*cinfo
->downsample
->downsample
) (cinfo
, 
 247                                         (JDIMENSION
) prep
->this_row_group
, 
 248                                         output_buf
, *out_row_group_ctr
); 
 249       (*out_row_group_ctr
)++; 
 250       /* Advance pointers with wraparound as necessary. */ 
 251       prep
->this_row_group 
+= cinfo
->max_v_samp_factor
; 
 252       if (prep
->this_row_group 
>= buf_height
) 
 253         prep
->this_row_group 
= 0; 
 254       if (prep
->next_buf_row 
>= buf_height
) 
 255         prep
->next_buf_row 
= 0; 
 256       prep
->next_buf_stop 
= prep
->next_buf_row 
+ cinfo
->max_v_samp_factor
; 
 263  * Create the wrapped-around downsampling input buffer needed for context mode. 
 267 create_context_buffer (j_compress_ptr cinfo
) 
 269   my_prep_ptr prep 
= (my_prep_ptr
) cinfo
->prep
; 
 270   int rgroup_height 
= cinfo
->max_v_samp_factor
; 
 272   jpeg_component_info 
* compptr
; 
 273   JSAMPARRAY true_buffer
, fake_buffer
; 
 275   /* Grab enough space for fake row pointers for all the components; 
 276    * we need five row groups' worth of pointers for each component. 
 278   fake_buffer 
= (JSAMPARRAY
) 
 279     (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 280                                 (cinfo
->num_components 
* 5 * rgroup_height
) * 
 283   for (ci 
= 0, compptr 
= cinfo
->comp_info
; ci 
< cinfo
->num_components
; 
 285     /* Allocate the actual buffer space (3 row groups) for this component. 
 286      * We make the buffer wide enough to allow the downsampler to edge-expand 
 287      * horizontally within the buffer, if it so chooses. 
 289     true_buffer 
= (*cinfo
->mem
->alloc_sarray
) 
 290       ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 291        (JDIMENSION
) (((long) compptr
->width_in_blocks 
* DCTSIZE 
* 
 292                       cinfo
->max_h_samp_factor
) / compptr
->h_samp_factor
), 
 293        (JDIMENSION
) (3 * rgroup_height
)); 
 294     /* Copy true buffer row pointers into the middle of the fake row array */ 
 295     MEMCOPY(fake_buffer 
+ rgroup_height
, true_buffer
, 
 296             3 * rgroup_height 
* SIZEOF(JSAMPROW
)); 
 297     /* Fill in the above and below wraparound pointers */ 
 298     for (i 
= 0; i 
< rgroup_height
; i
++) { 
 299       fake_buffer
[i
] = true_buffer
[2 * rgroup_height 
+ i
]; 
 300       fake_buffer
[4 * rgroup_height 
+ i
] = true_buffer
[i
]; 
 302     prep
->color_buf
[ci
] = fake_buffer 
+ rgroup_height
; 
 303     fake_buffer 
+= 5 * rgroup_height
; /* point to space for next component */ 
 307 #endif /* CONTEXT_ROWS_SUPPORTED */ 
 311  * Initialize preprocessing controller. 
 315 jinit_c_prep_controller (j_compress_ptr cinfo
, boolean need_full_buffer
) 
 319   jpeg_component_info 
* compptr
; 
 321   if (need_full_buffer
)         /* safety check */ 
 322     ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
 325     (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 326                                 SIZEOF(my_prep_controller
)); 
 327   cinfo
->prep 
= (struct jpeg_c_prep_controller 
*) prep
; 
 328   prep
->pub
.start_pass 
= start_pass_prep
; 
 330   /* Allocate the color conversion buffer. 
 331    * We make the buffer wide enough to allow the downsampler to edge-expand 
 332    * horizontally within the buffer, if it so chooses. 
 334   if (cinfo
->downsample
->need_context_rows
) { 
 335     /* Set up to provide context rows */ 
 336 #ifdef CONTEXT_ROWS_SUPPORTED 
 337     prep
->pub
.pre_process_data 
= pre_process_context
; 
 338     create_context_buffer(cinfo
); 
 340     ERREXIT(cinfo
, JERR_NOT_COMPILED
); 
 343     /* No context, just make it tall enough for one row group */ 
 344     prep
->pub
.pre_process_data 
= pre_process_data
; 
 345     for (ci 
= 0, compptr 
= cinfo
->comp_info
; ci 
< cinfo
->num_components
; 
 347       prep
->color_buf
[ci
] = (*cinfo
->mem
->alloc_sarray
) 
 348         ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 349          (JDIMENSION
) (((long) compptr
->width_in_blocks 
* DCTSIZE 
* 
 350                         cinfo
->max_h_samp_factor
) / compptr
->h_samp_factor
), 
 351          (JDIMENSION
) cinfo
->max_v_samp_factor
);