Imported Upstream version 3.0.1
[platform/upstream/libjpeg-turbo.git] / jdpostct.c
1 /*
2  * jdpostct.c
3  *
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.
10  *
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.
15  *
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.
20  */
21
22 #define JPEG_INTERNALS
23 #include "jinclude.h"
24 #include "jpeglib.h"
25 #include "jsamplecomp.h"
26
27
28 #if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED)
29
30 /* Private buffer controller object */
31
32 typedef struct {
33   struct jpeg_d_post_controller pub; /* public fields */
34
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.
39    */
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;
47
48 typedef my_post_controller *my_post_ptr;
49
50
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
77
78
79 /*
80  * Initialize for a processing pass.
81  */
82
83 METHODDEF(void)
84 start_pass_dpost(j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
85 {
86   my_post_ptr post = (my_post_ptr)cinfo->post;
87
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.
97        */
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);
102       }
103     } else
104 #endif
105     {
106       /* For single-pass processing without color quantization,
107        * I have no work to do; just call the upsampler directly.
108        */
109       post->pub._post_process_data = cinfo->upsample->_upsample;
110     }
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;
129   }
130   post->starting_row = post->next_row = 0;
131 }
132
133
134 /*
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.
137  */
138
139 #if BITS_IN_JSAMPLE != 16
140
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)
146 {
147   my_post_ptr post = (my_post_ptr)cinfo->post;
148   JDIMENSION num_rows, max_rows;
149
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;
164 }
165
166 #endif
167
168
169 #if defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16
170
171 /*
172  * Process some data in the first pass of 2-pass quantization.
173  */
174
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)
180 {
181   my_post_ptr post = (my_post_ptr)cinfo->post;
182   JDIMENSION old_next_row, num_rows;
183
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);
189   }
190
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);
196
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;
204   }
205
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;
210   }
211 }
212
213
214 /*
215  * Process some data in the second pass of 2-pass quantization.
216  */
217
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)
223 {
224   my_post_ptr post = (my_post_ptr)cinfo->post;
225   JDIMENSION num_rows, max_rows;
226
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);
232   }
233
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;
243
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;
249
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;
255   }
256 }
257
258 #endif /* defined(QUANT_2PASS_SUPPORTED) && BITS_IN_JSAMPLE != 16 */
259
260
261 /*
262  * Initialize postprocessing controller.
263  */
264
265 GLOBAL(void)
266 _jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
267 {
268   my_post_ptr post;
269
270   if (cinfo->data_precision != BITS_IN_JSAMPLE)
271     ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
272
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 */
280
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?)
287      */
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);
308     }
309 #else
310     ERREXIT(cinfo, JERR_NOTIMPL);
311 #endif
312   }
313 }
314
315 #endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */