Merge autoland to mozilla-central. a=merge
[gecko.git] / media / libjpeg / jdpostct.c
blobd38495f5f316a569e3bc8594f1785ffdaf231f96
1 /*
2 * jdpostct.c
4 * This file was part of the Independent JPEG Group's software:
5 * Copyright (C) 1994-1996, Thomas G. Lane.
6 * libjpeg-turbo Modifications:
7 * Copyright (C) 2022-2023, D. R. Commander.
8 * For conditions of distribution and use, see the accompanying README.ijg
9 * file.
11 * This file contains the decompression postprocessing controller.
12 * This controller manages the upsampling, color conversion, and color
13 * quantization/reduction steps; specifically, it controls the buffering
14 * between upsample/color conversion and color quantization/reduction.
16 * If no color quantization/reduction is required, then this module has no
17 * work to do, and it just hands off to the upsample/color conversion code.
18 * An integrated upsample/convert/quantize process would replace this module
19 * entirely.
22 #define JPEG_INTERNALS
23 #include "jinclude.h"
24 #include "jpeglib.h"
25 #include "jsamplecomp.h"
28 #if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
30 /* Private buffer controller object */
32 typedef struct {
33 struct jpeg_d_post_controller pub; /* public fields */
35 /* Color quantization source buffer: this holds output data from
36 * the upsample/color conversion step to be passed to the quantizer.
37 * For two-pass color quantization, we need a full-image buffer;
38 * for one-pass operation, a strip buffer is sufficient.
40 jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */
41 _JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */
42 JDIMENSION strip_height; /* buffer size in rows */
43 /* for two-pass mode only: */
44 JDIMENSION starting_row; /* row # of first row in current strip */
45 JDIMENSION next_row; /* index of next row to fill/empty in strip */
46 } my_post_controller;
48 typedef my_post_controller *my_post_ptr;
51 /* Forward declarations */
52 #if BITS_IN_JSAMPLE != 16
53 METHODDEF(void) post_process_1pass(j_decompress_ptr cinfo,
54 _JSAMPIMAGE input_buf,
55 JDIMENSION *in_row_group_ctr,
56 JDIMENSION in_row_groups_avail,
57 _JSAMPARRAY output_buf,
58 JDIMENSION *out_row_ctr,
59 JDIMENSION out_rows_avail);
60 #endif
61 #if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16
62 METHODDEF(void) post_process_prepass(j_decompress_ptr cinfo,
63 _JSAMPIMAGE input_buf,
64 JDIMENSION *in_row_group_ctr,
65 JDIMENSION in_row_groups_avail,
66 _JSAMPARRAY output_buf,
67 JDIMENSION *out_row_ctr,
68 JDIMENSION out_rows_avail);
69 METHODDEF(void) post_process_2pass(j_decompress_ptr cinfo,
70 _JSAMPIMAGE input_buf,
71 JDIMENSION *in_row_group_ctr,
72 JDIMENSION in_row_groups_avail,
73 _JSAMPARRAY output_buf,
74 JDIMENSION *out_row_ctr,
75 JDIMENSION out_rows_avail);
76 #endif
80 * Initialize for a processing pass.
83 METHODDEF(void)
84 start_pass_dpost(j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
86 my_post_ptr post = (my_post_ptr)cinfo->post;
88 switch (pass_mode) {
89 case JBUF_PASS_THRU:
90 #if BITS_IN_JSAMPLE != 16
91 if (cinfo->quantize_colors) {
92 /* Single-pass processing with color quantization. */
93 post->pub._post_process_data = post_process_1pass;
94 /* We could be doing buffered-image output before starting a 2-pass
95 * color quantization; in that case, jinit_d_post_controller did not
96 * allocate a strip buffer. Use the virtual-array buffer as workspace.
98 if (post->buffer == NULL) {
99 post->buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray)
100 ((j_common_ptr)cinfo, post->whole_image,
101 (JDIMENSION)0, post->strip_height, TRUE);
103 } else
104 #endif
106 /* For single-pass processing without color quantization,
107 * I have no work to do; just call the upsampler directly.
109 post->pub._post_process_data = cinfo->upsample->_upsample;
111 break;
112 #if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16
113 case JBUF_SAVE_AND_PASS:
114 /* First pass of 2-pass quantization */
115 if (post->whole_image == NULL)
116 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
117 post->pub._post_process_data = post_process_prepass;
118 break;
119 case JBUF_CRANK_DEST:
120 /* Second pass of 2-pass quantization */
121 if (post->whole_image == NULL)
122 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
123 post->pub._post_process_data = post_process_2pass;
124 break;
125 #endif /* defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */
126 default:
127 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
128 break;
130 post->starting_row = post->next_row = 0;
135 * Process some data in the one-pass (strip buffer) case.
136 * This is used for color precision reduction as well as one-pass quantization.
139 #if BITS_IN_JSAMPLE != 16
141 METHODDEF(void)
142 post_process_1pass(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
143 JDIMENSION *in_row_group_ctr,
144 JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf,
145 JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
147 my_post_ptr post = (my_post_ptr)cinfo->post;
148 JDIMENSION num_rows, max_rows;
150 /* Fill the buffer, but not more than what we can dump out in one go. */
151 /* Note we rely on the upsampler to detect bottom of image. */
152 max_rows = out_rows_avail - *out_row_ctr;
153 if (max_rows > post->strip_height)
154 max_rows = post->strip_height;
155 num_rows = 0;
156 (*cinfo->upsample->_upsample) (cinfo, input_buf, in_row_group_ctr,
157 in_row_groups_avail, post->buffer, &num_rows,
158 max_rows);
159 /* Quantize and emit data. */
160 (*cinfo->cquantize->_color_quantize) (cinfo, post->buffer,
161 output_buf + *out_row_ctr,
162 (int)num_rows);
163 *out_row_ctr += num_rows;
166 #endif
169 #if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16
172 * Process some data in the first pass of 2-pass quantization.
175 METHODDEF(void)
176 post_process_prepass(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
177 JDIMENSION *in_row_group_ctr,
178 JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf,
179 JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
181 my_post_ptr post = (my_post_ptr)cinfo->post;
182 JDIMENSION old_next_row, num_rows;
184 /* Reposition virtual buffer if at start of strip. */
185 if (post->next_row == 0) {
186 post->buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray)
187 ((j_common_ptr)cinfo, post->whole_image,
188 post->starting_row, post->strip_height, TRUE);
191 /* Upsample some data (up to a strip height's worth). */
192 old_next_row = post->next_row;
193 (*cinfo->upsample->_upsample) (cinfo, input_buf, in_row_group_ctr,
194 in_row_groups_avail, post->buffer,
195 &post->next_row, post->strip_height);
197 /* Allow quantizer to scan new data. No data is emitted, */
198 /* but we advance out_row_ctr so outer loop can tell when we're done. */
199 if (post->next_row > old_next_row) {
200 num_rows = post->next_row - old_next_row;
201 (*cinfo->cquantize->_color_quantize) (cinfo, post->buffer + old_next_row,
202 (_JSAMPARRAY)NULL, (int)num_rows);
203 *out_row_ctr += num_rows;
206 /* Advance if we filled the strip. */
207 if (post->next_row >= post->strip_height) {
208 post->starting_row += post->strip_height;
209 post->next_row = 0;
215 * Process some data in the second pass of 2-pass quantization.
218 METHODDEF(void)
219 post_process_2pass(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf,
220 JDIMENSION *in_row_group_ctr,
221 JDIMENSION in_row_groups_avail, _JSAMPARRAY output_buf,
222 JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
224 my_post_ptr post = (my_post_ptr)cinfo->post;
225 JDIMENSION num_rows, max_rows;
227 /* Reposition virtual buffer if at start of strip. */
228 if (post->next_row == 0) {
229 post->buffer = (_JSAMPARRAY)(*cinfo->mem->access_virt_sarray)
230 ((j_common_ptr)cinfo, post->whole_image,
231 post->starting_row, post->strip_height, FALSE);
234 /* Determine number of rows to emit. */
235 num_rows = post->strip_height - post->next_row; /* available in strip */
236 max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
237 if (num_rows > max_rows)
238 num_rows = max_rows;
239 /* We have to check bottom of image here, can't depend on upsampler. */
240 max_rows = cinfo->output_height - post->starting_row;
241 if (num_rows > max_rows)
242 num_rows = max_rows;
244 /* Quantize and emit data. */
245 (*cinfo->cquantize->_color_quantize) (cinfo, post->buffer + post->next_row,
246 output_buf + *out_row_ctr,
247 (int)num_rows);
248 *out_row_ctr += num_rows;
250 /* Advance if we filled the strip. */
251 post->next_row += num_rows;
252 if (post->next_row >= post->strip_height) {
253 post->starting_row += post->strip_height;
254 post->next_row = 0;
258 #endif /* defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */
262 * Initialize postprocessing controller.
265 GLOBAL(void)
266 _jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
268 my_post_ptr post;
270 if (cinfo->data_precision != BITS_IN_JSAMPLE)
271 ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
273 post = (my_post_ptr)
274 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
275 sizeof(my_post_controller));
276 cinfo->post = (struct jpeg_d_post_controller *)post;
277 post->pub.start_pass = start_pass_dpost;
278 post->whole_image = NULL; /* flag for no virtual arrays */
279 post->buffer = NULL; /* flag for no strip buffer */
281 /* Create the quantization buffer, if needed */
282 if (cinfo->quantize_colors) {
283 #if BITS_IN_JSAMPLE != 16
284 /* The buffer strip height is max_v_samp_factor, which is typically
285 * an efficient number of rows for upsampling to return.
286 * (In the presence of output rescaling, we might want to be smarter?)
288 post->strip_height = (JDIMENSION)cinfo->max_v_samp_factor;
289 if (need_full_buffer) {
290 /* Two-pass color quantization: need full-image storage. */
291 /* We round up the number of rows to a multiple of the strip height. */
292 #ifdef QUANT_2PASS_SUPPORTED
293 post->whole_image = (*cinfo->mem->request_virt_sarray)
294 ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
295 cinfo->output_width * cinfo->out_color_components,
296 (JDIMENSION)jround_up((long)cinfo->output_height,
297 (long)post->strip_height),
298 post->strip_height);
299 #else
300 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
301 #endif /* QUANT_2PASS_SUPPORTED */
302 } else {
303 /* One-pass color quantization: just make a strip buffer. */
304 post->buffer = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray)
305 ((j_common_ptr)cinfo, JPOOL_IMAGE,
306 cinfo->output_width * cinfo->out_color_components,
307 post->strip_height);
309 #else
310 ERREXIT(cinfo, JERR_NOTIMPL);
311 #endif
315 #endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */