source: trunk/third/jpeg/jdpostct.c @ 15227

Revision 15227, 9.5 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15226, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * jdpostct.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 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.
12 *
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
16 * entirely.
17 */
18
19#define JPEG_INTERNALS
20#include "jinclude.h"
21#include "jpeglib.h"
22
23
24/* Private buffer controller object */
25
26typedef struct {
27  struct jpeg_d_post_controller pub; /* public fields */
28
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.
33   */
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 */
40} my_post_controller;
41
42typedef my_post_controller * my_post_ptr;
43
44
45/* Forward declarations */
46METHODDEF(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
53METHODDEF(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));
59METHODDEF(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));
65#endif
66
67
68/*
69 * Initialize for a processing pass.
70 */
71
72METHODDEF(void)
73start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
74{
75  my_post_ptr post = (my_post_ptr) cinfo->post;
76
77  switch (pass_mode) {
78  case JBUF_PASS_THRU:
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.
85       */
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);
90      }
91    } else {
92      /* For single-pass processing without color quantization,
93       * I have no work to do; just call the upsampler directly.
94       */
95      post->pub.post_process_data = cinfo->upsample->upsample;
96    }
97    break;
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;
104    break;
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;
110    break;
111#endif /* QUANT_2PASS_SUPPORTED */
112  default:
113    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
114    break;
115  }
116  post->starting_row = post->next_row = 0;
117}
118
119
120/*
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.
123 */
124
125METHODDEF(void)
126post_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)
131{
132  my_post_ptr post = (my_post_ptr) cinfo->post;
133  JDIMENSION num_rows, max_rows;
134
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;
140  num_rows = 0;
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;
148}
149
150
151#ifdef QUANT_2PASS_SUPPORTED
152
153/*
154 * Process some data in the first pass of 2-pass quantization.
155 */
156
157METHODDEF(void)
158post_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)
163{
164  my_post_ptr post = (my_post_ptr) cinfo->post;
165  JDIMENSION old_next_row, num_rows;
166
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);
172  }
173
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);
179
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;
187  }
188
189  /* Advance if we filled the strip. */
190  if (post->next_row >= post->strip_height) {
191    post->starting_row += post->strip_height;
192    post->next_row = 0;
193  }
194}
195
196
197/*
198 * Process some data in the second pass of 2-pass quantization.
199 */
200
201METHODDEF(void)
202post_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)
207{
208  my_post_ptr post = (my_post_ptr) cinfo->post;
209  JDIMENSION num_rows, max_rows;
210
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);
216  }
217
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)
222    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)
226    num_rows = max_rows;
227
228  /* Quantize and emit data. */
229  (*cinfo->cquantize->color_quantize) (cinfo,
230                post->buffer + post->next_row, output_buf + *out_row_ctr,
231                (int) num_rows);
232  *out_row_ctr += num_rows;
233
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;
238    post->next_row = 0;
239  }
240}
241
242#endif /* QUANT_2PASS_SUPPORTED */
243
244
245/*
246 * Initialize postprocessing controller.
247 */
248
249GLOBAL(void)
250jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
251{
252  my_post_ptr post;
253
254  post = (my_post_ptr)
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 */
261
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?)
267     */
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),
278         post->strip_height);
279#else
280      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
281#endif /* QUANT_2PASS_SUPPORTED */
282    } else {
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,
287         post->strip_height);
288    }
289  }
290}
Note: See TracBrowser for help on using the repository browser.