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 main buffer controller for compression. 
   9  * The main buffer lies between the pre-processor and the JPEG 
  10  * compressor proper; it holds downsampled data in the JPEG colorspace. 
  13 #define JPEG_INTERNALS 
  18 /* Note: currently, there is no operating mode in which a full-image buffer 
  19  * is needed at this step.  If there were, that mode could not be used with 
  20  * "raw data" input, since this module is bypassed in that case.  However, 
  21  * we've left the code here for possible use in special applications. 
  23 #undef FULL_MAIN_BUFFER_SUPPORTED 
  26 /* Private buffer controller object */ 
  29   struct jpeg_c_main_controller pub
; /* public fields */ 
  31   JDIMENSION cur_iMCU_row
;      /* number of current iMCU row */ 
  32   JDIMENSION rowgroup_ctr
;      /* counts row groups received in iMCU row */ 
  33   boolean suspended
;            /* remember if we suspended output */ 
  34   J_BUF_MODE pass_mode
;         /* current operating mode */ 
  36   /* If using just a strip buffer, this points to the entire set of buffers 
  37    * (we allocate one for each component).  In the full-image case, this 
  38    * points to the currently accessible strips of the virtual arrays. 
  40   JSAMPARRAY buffer
[MAX_COMPONENTS
]; 
  42 #ifdef FULL_MAIN_BUFFER_SUPPORTED 
  43   /* If using full-image storage, this array holds pointers to virtual-array 
  44    * control blocks for each component.  Unused if not full-image storage. 
  46   jvirt_sarray_ptr whole_image
[MAX_COMPONENTS
]; 
  50 typedef my_main_controller 
* my_main_ptr
; 
  53 /* Forward declarations */ 
  54 METHODDEF(void) process_data_simple_main
 
  55         JPP((j_compress_ptr cinfo
, JSAMPARRAY input_buf
, 
  56              JDIMENSION 
*in_row_ctr
, JDIMENSION in_rows_avail
)); 
  57 #ifdef FULL_MAIN_BUFFER_SUPPORTED 
  58 METHODDEF(void) process_data_buffer_main
 
  59         JPP((j_compress_ptr cinfo
, JSAMPARRAY input_buf
, 
  60              JDIMENSION 
*in_row_ctr
, JDIMENSION in_rows_avail
)); 
  65  * Initialize for a processing pass. 
  69 start_pass_main (j_compress_ptr cinfo
, J_BUF_MODE pass_mode
) 
  71   my_main_ptr main 
= (my_main_ptr
) cinfo
->main
; 
  73   /* Do nothing in raw-data mode. */ 
  74   if (cinfo
->raw_data_in
) 
  77   main
->cur_iMCU_row 
= 0;       /* initialize counters */ 
  78   main
->rowgroup_ctr 
= 0; 
  79   main
->suspended 
= FALSE
; 
  80   main
->pass_mode 
= pass_mode
;  /* save mode for use by process_data */ 
  84 #ifdef FULL_MAIN_BUFFER_SUPPORTED 
  85     if (main
->whole_image
[0] != NULL
) 
  86       ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
  88     main
->pub
.process_data 
= process_data_simple_main
; 
  90 #ifdef FULL_MAIN_BUFFER_SUPPORTED 
  91   case JBUF_SAVE_SOURCE
: 
  93   case JBUF_SAVE_AND_PASS
: 
  94     if (main
->whole_image
[0] == NULL
) 
  95       ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
  96     main
->pub
.process_data 
= process_data_buffer_main
; 
 100     ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
 108  * This routine handles the simple pass-through mode, 
 109  * where we have only a strip buffer. 
 113 process_data_simple_main (j_compress_ptr cinfo
, 
 114                           JSAMPARRAY input_buf
, JDIMENSION 
*in_row_ctr
, 
 115                           JDIMENSION in_rows_avail
) 
 117   my_main_ptr main 
= (my_main_ptr
) cinfo
->main
; 
 119   while (main
->cur_iMCU_row 
< cinfo
->total_iMCU_rows
) { 
 120     /* Read input data if we haven't filled the main buffer yet */ 
 121     if (main
->rowgroup_ctr 
< DCTSIZE
) 
 122       (*cinfo
->prep
->pre_process_data
) (cinfo
, 
 123                                         input_buf
, in_row_ctr
, in_rows_avail
, 
 124                                         main
->buffer
, &main
->rowgroup_ctr
, 
 125                                         (JDIMENSION
) DCTSIZE
); 
 127     /* If we don't have a full iMCU row buffered, return to application for 
 128      * more data.  Note that preprocessor will always pad to fill the iMCU row 
 129      * at the bottom of the image. 
 131     if (main
->rowgroup_ctr 
!= DCTSIZE
) 
 134     /* Send the completed row to the compressor */ 
 135     if (! (*cinfo
->coef
->compress_data
) (cinfo
, main
->buffer
)) { 
 136       /* If compressor did not consume the whole row, then we must need to 
 137        * suspend processing and return to the application.  In this situation 
 138        * we pretend we didn't yet consume the last input row; otherwise, if 
 139        * it happened to be the last row of the image, the application would 
 140        * think we were done. 
 142       if (! main
->suspended
) { 
 144         main
->suspended 
= TRUE
; 
 148     /* We did finish the row.  Undo our little suspension hack if a previous 
 149      * call suspended; then mark the main buffer empty. 
 151     if (main
->suspended
) { 
 153       main
->suspended 
= FALSE
; 
 155     main
->rowgroup_ctr 
= 0; 
 156     main
->cur_iMCU_row
++; 
 161 #ifdef FULL_MAIN_BUFFER_SUPPORTED 
 165  * This routine handles all of the modes that use a full-size buffer. 
 169 process_data_buffer_main (j_compress_ptr cinfo
, 
 170                           JSAMPARRAY input_buf
, JDIMENSION 
*in_row_ctr
, 
 171                           JDIMENSION in_rows_avail
) 
 173   my_main_ptr main 
= (my_main_ptr
) cinfo
->main
; 
 175   jpeg_component_info 
*compptr
; 
 176   boolean writing 
= (main
->pass_mode 
!= JBUF_CRANK_DEST
); 
 178   while (main
->cur_iMCU_row 
< cinfo
->total_iMCU_rows
) { 
 179     /* Realign the virtual buffers if at the start of an iMCU row. */ 
 180     if (main
->rowgroup_ctr 
== 0) { 
 181       for (ci 
= 0, compptr 
= cinfo
->comp_info
; ci 
< cinfo
->num_components
; 
 183         main
->buffer
[ci
] = (*cinfo
->mem
->access_virt_sarray
) 
 184           ((j_common_ptr
) cinfo
, main
->whole_image
[ci
], 
 185            main
->cur_iMCU_row 
* (compptr
->v_samp_factor 
* DCTSIZE
), 
 186            (JDIMENSION
) (compptr
->v_samp_factor 
* DCTSIZE
), writing
); 
 188       /* In a read pass, pretend we just read some source data. */ 
 190         *in_row_ctr 
+= cinfo
->max_v_samp_factor 
* DCTSIZE
; 
 191         main
->rowgroup_ctr 
= DCTSIZE
; 
 195     /* If a write pass, read input data until the current iMCU row is full. */ 
 196     /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ 
 198       (*cinfo
->prep
->pre_process_data
) (cinfo
, 
 199                                         input_buf
, in_row_ctr
, in_rows_avail
, 
 200                                         main
->buffer
, &main
->rowgroup_ctr
, 
 201                                         (JDIMENSION
) DCTSIZE
); 
 202       /* Return to application if we need more data to fill the iMCU row. */ 
 203       if (main
->rowgroup_ctr 
< DCTSIZE
) 
 207     /* Emit data, unless this is a sink-only pass. */ 
 208     if (main
->pass_mode 
!= JBUF_SAVE_SOURCE
) { 
 209       if (! (*cinfo
->coef
->compress_data
) (cinfo
, main
->buffer
)) { 
 210         /* If compressor did not consume the whole row, then we must need to 
 211          * suspend processing and return to the application.  In this situation 
 212          * we pretend we didn't yet consume the last input row; otherwise, if 
 213          * it happened to be the last row of the image, the application would 
 214          * think we were done. 
 216         if (! main
->suspended
) { 
 218           main
->suspended 
= TRUE
; 
 222       /* We did finish the row.  Undo our little suspension hack if a previous 
 223        * call suspended; then mark the main buffer empty. 
 225       if (main
->suspended
) { 
 227         main
->suspended 
= FALSE
; 
 231     /* If get here, we are done with this iMCU row.  Mark buffer empty. */ 
 232     main
->rowgroup_ctr 
= 0; 
 233     main
->cur_iMCU_row
++; 
 237 #endif /* FULL_MAIN_BUFFER_SUPPORTED */ 
 241  * Initialize main buffer controller. 
 245 jinit_c_main_controller (j_compress_ptr cinfo
, boolean need_full_buffer
) 
 249   jpeg_component_info 
*compptr
; 
 252     (*cinfo
->mem
->alloc_small
) ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 253                                 SIZEOF(my_main_controller
)); 
 254   cinfo
->main 
= (struct jpeg_c_main_controller 
*) main
; 
 255   main
->pub
.start_pass 
= start_pass_main
; 
 257   /* We don't need to create a buffer in raw-data mode. */ 
 258   if (cinfo
->raw_data_in
) 
 261   /* Create the buffer.  It holds downsampled data, so each component 
 262    * may be of a different size. 
 264   if (need_full_buffer
) { 
 265 #ifdef FULL_MAIN_BUFFER_SUPPORTED 
 266     /* Allocate a full-image virtual array for each component */ 
 267     /* Note we pad the bottom to a multiple of the iMCU height */ 
 268     for (ci 
= 0, compptr 
= cinfo
->comp_info
; ci 
< cinfo
->num_components
; 
 270       main
->whole_image
[ci
] = (*cinfo
->mem
->request_virt_sarray
) 
 271         ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, FALSE
, 
 272          compptr
->width_in_blocks 
* DCTSIZE
, 
 273          (JDIMENSION
) jround_up((long) compptr
->height_in_blocks
, 
 274                                 (long) compptr
->v_samp_factor
) * DCTSIZE
, 
 275          (JDIMENSION
) (compptr
->v_samp_factor 
* DCTSIZE
)); 
 278     ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
); 
 281 #ifdef FULL_MAIN_BUFFER_SUPPORTED 
 282     main
->whole_image
[0] = NULL
; /* flag for no virtual arrays */ 
 284     /* Allocate a strip buffer for each component */ 
 285     for (ci 
= 0, compptr 
= cinfo
->comp_info
; ci 
< cinfo
->num_components
; 
 287       main
->buffer
[ci
] = (*cinfo
->mem
->alloc_sarray
) 
 288         ((j_common_ptr
) cinfo
, JPOOL_IMAGE
, 
 289          compptr
->width_in_blocks 
* DCTSIZE
, 
 290          (JDIMENSION
) (compptr
->v_samp_factor 
* DCTSIZE
));