source: trunk/third/firefox/jpeg/jcmainct.c @ 21695

Revision 21695, 9.0 KB checked in by rbasch, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21694, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * jcmainct.c
3 *
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.
7 *
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.
11 */
12
13#define JPEG_INTERNALS
14#include "jinclude.h"
15#include "jpeglib.h"
16
17
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.
22 */
23#undef FULL_MAIN_BUFFER_SUPPORTED
24
25
26/* Private buffer controller object */
27
28typedef struct {
29  struct jpeg_c_main_controller pub; /* public fields */
30
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 */
35
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.
39   */
40  JSAMPARRAY buffer[MAX_COMPONENTS];
41
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.
45   */
46  jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
47#endif
48} my_main_controller;
49
50typedef my_main_controller * my_main_ptr;
51
52
53/* Forward declarations */
54METHODDEF(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
58METHODDEF(void) process_data_buffer_main
59        JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
60             JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
61#endif
62
63
64/*
65 * Initialize for a processing pass.
66 */
67
68METHODDEF(void)
69start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
70{
71  my_main_ptr main = (my_main_ptr) cinfo->main;
72
73  /* Do nothing in raw-data mode. */
74  if (cinfo->raw_data_in)
75    return;
76
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 */
81
82  switch (pass_mode) {
83  case JBUF_PASS_THRU:
84#ifdef FULL_MAIN_BUFFER_SUPPORTED
85    if (main->whole_image[0] != NULL)
86      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
87#endif
88    main->pub.process_data = process_data_simple_main;
89    break;
90#ifdef FULL_MAIN_BUFFER_SUPPORTED
91  case JBUF_SAVE_SOURCE:
92  case JBUF_CRANK_DEST:
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;
97    break;
98#endif
99  default:
100    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
101    break;
102  }
103}
104
105
106/*
107 * Process some data.
108 * This routine handles the simple pass-through mode,
109 * where we have only a strip buffer.
110 */
111
112METHODDEF(void)
113process_data_simple_main (j_compress_ptr cinfo,
114                          JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
115                          JDIMENSION in_rows_avail)
116{
117  my_main_ptr main = (my_main_ptr) cinfo->main;
118
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);
126
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.
130     */
131    if (main->rowgroup_ctr != DCTSIZE)
132      return;
133
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.
141       */
142      if (! main->suspended) {
143        (*in_row_ctr)--;
144        main->suspended = TRUE;
145      }
146      return;
147    }
148    /* We did finish the row.  Undo our little suspension hack if a previous
149     * call suspended; then mark the main buffer empty.
150     */
151    if (main->suspended) {
152      (*in_row_ctr)++;
153      main->suspended = FALSE;
154    }
155    main->rowgroup_ctr = 0;
156    main->cur_iMCU_row++;
157  }
158}
159
160
161#ifdef FULL_MAIN_BUFFER_SUPPORTED
162
163/*
164 * Process some data.
165 * This routine handles all of the modes that use a full-size buffer.
166 */
167
168METHODDEF(void)
169process_data_buffer_main (j_compress_ptr cinfo,
170                          JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
171                          JDIMENSION in_rows_avail)
172{
173  my_main_ptr main = (my_main_ptr) cinfo->main;
174  int ci;
175  jpeg_component_info *compptr;
176  boolean writing = (main->pass_mode != JBUF_CRANK_DEST);
177
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;
182           ci++, compptr++) {
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);
187      }
188      /* In a read pass, pretend we just read some source data. */
189      if (! writing) {
190        *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE;
191        main->rowgroup_ctr = DCTSIZE;
192      }
193    }
194
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. */
197    if (writing) {
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)
204        return;
205    }
206
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.
215         */
216        if (! main->suspended) {
217          (*in_row_ctr)--;
218          main->suspended = TRUE;
219        }
220        return;
221      }
222      /* We did finish the row.  Undo our little suspension hack if a previous
223       * call suspended; then mark the main buffer empty.
224       */
225      if (main->suspended) {
226        (*in_row_ctr)++;
227        main->suspended = FALSE;
228      }
229    }
230
231    /* If get here, we are done with this iMCU row.  Mark buffer empty. */
232    main->rowgroup_ctr = 0;
233    main->cur_iMCU_row++;
234  }
235}
236
237#endif /* FULL_MAIN_BUFFER_SUPPORTED */
238
239
240/*
241 * Initialize main buffer controller.
242 */
243
244GLOBAL(void)
245jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
246{
247  my_main_ptr main;
248  int ci;
249  jpeg_component_info *compptr;
250
251  main = (my_main_ptr)
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;
256
257  /* We don't need to create a buffer in raw-data mode. */
258  if (cinfo->raw_data_in)
259    return;
260
261  /* Create the buffer.  It holds downsampled data, so each component
262   * may be of a different size.
263   */
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;
269         ci++, compptr++) {
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));
276    }
277#else
278    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
279#endif
280  } else {
281#ifdef FULL_MAIN_BUFFER_SUPPORTED
282    main->whole_image[0] = NULL; /* flag for no virtual arrays */
283#endif
284    /* Allocate a strip buffer for each component */
285    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
286         ci++, compptr++) {
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));
291    }
292  }
293}
Note: See TracBrowser for help on using the repository browser.