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 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.
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
19 #define JPEG_INTERNALS
24 /* Private buffer controller object */
27 struct jpeg_d_post_controller pub
; /* public fields */
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.
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 */
42 typedef my_post_controller
* my_post_ptr
;
45 /* Forward declarations */
46 METHODDEF(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
53 METHODDEF(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
));
59 METHODDEF(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
));
69 * Initialize for a processing pass.
73 start_pass_dpost (j_decompress_ptr cinfo
, J_BUF_MODE pass_mode
)
75 my_post_ptr post
= (my_post_ptr
) cinfo
->post
;
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.
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
);
92 /* For single-pass processing without color quantization,
93 * I have no work to do; just call the upsampler directly.
95 post
->pub
.post_process_data
= cinfo
->upsample
->upsample
;
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
;
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
;
111 #endif /* QUANT_2PASS_SUPPORTED */
113 ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
);
116 post
->starting_row
= post
->next_row
= 0;
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.
126 post_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
)
132 my_post_ptr post
= (my_post_ptr
) cinfo
->post
;
133 JDIMENSION num_rows
, max_rows
;
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
;
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
;
151 #ifdef QUANT_2PASS_SUPPORTED
154 * Process some data in the first pass of 2-pass quantization.
158 post_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
)
164 my_post_ptr post
= (my_post_ptr
) cinfo
->post
;
165 JDIMENSION old_next_row
, num_rows
;
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
);
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
);
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
;
189 /* Advance if we filled the strip. */
190 if (post
->next_row
>= post
->strip_height
) {
191 post
->starting_row
+= post
->strip_height
;
198 * Process some data in the second pass of 2-pass quantization.
202 post_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
)
208 my_post_ptr post
= (my_post_ptr
) cinfo
->post
;
209 JDIMENSION num_rows
, max_rows
;
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
);
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
)
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
)
228 /* Quantize and emit data. */
229 (*cinfo
->cquantize
->color_quantize
) (cinfo
,
230 post
->buffer
+ post
->next_row
, output_buf
+ *out_row_ctr
,
232 *out_row_ctr
+= num_rows
;
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
;
242 #endif /* QUANT_2PASS_SUPPORTED */
246 * Initialize postprocessing controller.
250 jinit_d_post_controller (j_decompress_ptr cinfo
, boolean need_full_buffer
)
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 */
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?)
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
),
280 ERREXIT(cinfo
, JERR_BAD_BUFFER_MODE
);
281 #endif /* QUANT_2PASS_SUPPORTED */
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
,