/src/libjpeg-turbo.2.1.x/jdpostct.c
Line  | Count  | Source (jump to first uncovered line)  | 
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  |  |  * It was modified by The libjpeg-turbo Project to include only code relevant  | 
7  |  |  * to libjpeg-turbo.  | 
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  |  |  | 
26  |  |  | 
27  |  | /* Private buffer controller object */  | 
28  |  |  | 
29  |  | typedef struct { | 
30  |  |   struct jpeg_d_post_controller pub; /* public fields */  | 
31  |  |  | 
32  |  |   /* Color quantization source buffer: this holds output data from  | 
33  |  |    * the upsample/color conversion step to be passed to the quantizer.  | 
34  |  |    * For two-pass color quantization, we need a full-image buffer;  | 
35  |  |    * for one-pass operation, a strip buffer is sufficient.  | 
36  |  |    */  | 
37  |  |   jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */  | 
38  |  |   JSAMPARRAY buffer;            /* strip buffer, or current strip of virtual */  | 
39  |  |   JDIMENSION strip_height;      /* buffer size in rows */  | 
40  |  |   /* for two-pass mode only: */  | 
41  |  |   JDIMENSION starting_row;      /* row # of first row in current strip */  | 
42  |  |   JDIMENSION next_row;          /* index of next row to fill/empty in strip */  | 
43  |  | } my_post_controller;  | 
44  |  |  | 
45  |  | typedef my_post_controller *my_post_ptr;  | 
46  |  |  | 
47  |  |  | 
48  |  | /* Forward declarations */  | 
49  |  | METHODDEF(void) post_process_1pass(j_decompress_ptr cinfo,  | 
50  |  |                                    JSAMPIMAGE input_buf,  | 
51  |  |                                    JDIMENSION *in_row_group_ctr,  | 
52  |  |                                    JDIMENSION in_row_groups_avail,  | 
53  |  |                                    JSAMPARRAY output_buf,  | 
54  |  |                                    JDIMENSION *out_row_ctr,  | 
55  |  |                                    JDIMENSION out_rows_avail);  | 
56  |  | #ifdef QUANT_2PASS_SUPPORTED  | 
57  |  | METHODDEF(void) post_process_prepass(j_decompress_ptr cinfo,  | 
58  |  |                                      JSAMPIMAGE input_buf,  | 
59  |  |                                      JDIMENSION *in_row_group_ctr,  | 
60  |  |                                      JDIMENSION in_row_groups_avail,  | 
61  |  |                                      JSAMPARRAY output_buf,  | 
62  |  |                                      JDIMENSION *out_row_ctr,  | 
63  |  |                                      JDIMENSION out_rows_avail);  | 
64  |  | METHODDEF(void) post_process_2pass(j_decompress_ptr cinfo,  | 
65  |  |                                    JSAMPIMAGE input_buf,  | 
66  |  |                                    JDIMENSION *in_row_group_ctr,  | 
67  |  |                                    JDIMENSION in_row_groups_avail,  | 
68  |  |                                    JSAMPARRAY output_buf,  | 
69  |  |                                    JDIMENSION *out_row_ctr,  | 
70  |  |                                    JDIMENSION out_rows_avail);  | 
71  |  | #endif  | 
72  |  |  | 
73  |  |  | 
74  |  | /*  | 
75  |  |  * Initialize for a processing pass.  | 
76  |  |  */  | 
77  |  |  | 
78  |  | METHODDEF(void)  | 
79  |  | start_pass_dpost(j_decompress_ptr cinfo, J_BUF_MODE pass_mode)  | 
80  | 0  | { | 
81  | 0  |   my_post_ptr post = (my_post_ptr)cinfo->post;  | 
82  |  | 
  | 
83  | 0  |   switch (pass_mode) { | 
84  | 0  |   case JBUF_PASS_THRU:  | 
85  | 0  |     if (cinfo->quantize_colors) { | 
86  |  |       /* Single-pass processing with color quantization. */  | 
87  | 0  |       post->pub.post_process_data = post_process_1pass;  | 
88  |  |       /* We could be doing buffered-image output before starting a 2-pass  | 
89  |  |        * color quantization; in that case, jinit_d_post_controller did not  | 
90  |  |        * allocate a strip buffer.  Use the virtual-array buffer as workspace.  | 
91  |  |        */  | 
92  | 0  |       if (post->buffer == NULL) { | 
93  | 0  |         post->buffer = (*cinfo->mem->access_virt_sarray)  | 
94  | 0  |           ((j_common_ptr)cinfo, post->whole_image,  | 
95  | 0  |            (JDIMENSION)0, post->strip_height, TRUE);  | 
96  | 0  |       }  | 
97  | 0  |     } else { | 
98  |  |       /* For single-pass processing without color quantization,  | 
99  |  |        * I have no work to do; just call the upsampler directly.  | 
100  |  |        */  | 
101  | 0  |       post->pub.post_process_data = cinfo->upsample->upsample;  | 
102  | 0  |     }  | 
103  | 0  |     break;  | 
104  | 0  | #ifdef QUANT_2PASS_SUPPORTED  | 
105  | 0  |   case JBUF_SAVE_AND_PASS:  | 
106  |  |     /* First pass of 2-pass quantization */  | 
107  | 0  |     if (post->whole_image == NULL)  | 
108  | 0  |       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);  | 
109  | 0  |     post->pub.post_process_data = post_process_prepass;  | 
110  | 0  |     break;  | 
111  | 0  |   case JBUF_CRANK_DEST:  | 
112  |  |     /* Second pass of 2-pass quantization */  | 
113  | 0  |     if (post->whole_image == NULL)  | 
114  | 0  |       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);  | 
115  | 0  |     post->pub.post_process_data = post_process_2pass;  | 
116  | 0  |     break;  | 
117  | 0  | #endif /* QUANT_2PASS_SUPPORTED */  | 
118  | 0  |   default:  | 
119  | 0  |     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);  | 
120  | 0  |     break;  | 
121  | 0  |   }  | 
122  | 0  |   post->starting_row = post->next_row = 0;  | 
123  | 0  | }  | 
124  |  |  | 
125  |  |  | 
126  |  | /*  | 
127  |  |  * Process some data in the one-pass (strip buffer) case.  | 
128  |  |  * This is used for color precision reduction as well as one-pass quantization.  | 
129  |  |  */  | 
130  |  |  | 
131  |  | METHODDEF(void)  | 
132  |  | post_process_1pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,  | 
133  |  |                    JDIMENSION *in_row_group_ctr,  | 
134  |  |                    JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,  | 
135  |  |                    JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)  | 
136  | 0  | { | 
137  | 0  |   my_post_ptr post = (my_post_ptr)cinfo->post;  | 
138  | 0  |   JDIMENSION num_rows, max_rows;  | 
139  |  |  | 
140  |  |   /* Fill the buffer, but not more than what we can dump out in one go. */  | 
141  |  |   /* Note we rely on the upsampler to detect bottom of image. */  | 
142  | 0  |   max_rows = out_rows_avail - *out_row_ctr;  | 
143  | 0  |   if (max_rows > post->strip_height)  | 
144  | 0  |     max_rows = post->strip_height;  | 
145  | 0  |   num_rows = 0;  | 
146  | 0  |   (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr,  | 
147  | 0  |                                 in_row_groups_avail, post->buffer, &num_rows,  | 
148  | 0  |                                 max_rows);  | 
149  |  |   /* Quantize and emit data. */  | 
150  | 0  |   (*cinfo->cquantize->color_quantize) (cinfo, post->buffer,  | 
151  | 0  |                                        output_buf + *out_row_ctr,  | 
152  | 0  |                                        (int)num_rows);  | 
153  | 0  |   *out_row_ctr += num_rows;  | 
154  | 0  | }  | 
155  |  |  | 
156  |  |  | 
157  |  | #ifdef QUANT_2PASS_SUPPORTED  | 
158  |  |  | 
159  |  | /*  | 
160  |  |  * Process some data in the first pass of 2-pass quantization.  | 
161  |  |  */  | 
162  |  |  | 
163  |  | METHODDEF(void)  | 
164  |  | post_process_prepass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,  | 
165  |  |                      JDIMENSION *in_row_group_ctr,  | 
166  |  |                      JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,  | 
167  |  |                      JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)  | 
168  | 0  | { | 
169  | 0  |   my_post_ptr post = (my_post_ptr)cinfo->post;  | 
170  | 0  |   JDIMENSION old_next_row, num_rows;  | 
171  |  |  | 
172  |  |   /* Reposition virtual buffer if at start of strip. */  | 
173  | 0  |   if (post->next_row == 0) { | 
174  | 0  |     post->buffer = (*cinfo->mem->access_virt_sarray)  | 
175  | 0  |         ((j_common_ptr)cinfo, post->whole_image,  | 
176  | 0  |          post->starting_row, post->strip_height, TRUE);  | 
177  | 0  |   }  | 
178  |  |  | 
179  |  |   /* Upsample some data (up to a strip height's worth). */  | 
180  | 0  |   old_next_row = post->next_row;  | 
181  | 0  |   (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr,  | 
182  | 0  |                                 in_row_groups_avail, post->buffer,  | 
183  | 0  |                                 &post->next_row, post->strip_height);  | 
184  |  |  | 
185  |  |   /* Allow quantizer to scan new data.  No data is emitted, */  | 
186  |  |   /* but we advance out_row_ctr so outer loop can tell when we're done. */  | 
187  | 0  |   if (post->next_row > old_next_row) { | 
188  | 0  |     num_rows = post->next_row - old_next_row;  | 
189  | 0  |     (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,  | 
190  | 0  |                                          (JSAMPARRAY)NULL, (int)num_rows);  | 
191  | 0  |     *out_row_ctr += num_rows;  | 
192  | 0  |   }  | 
193  |  |  | 
194  |  |   /* Advance if we filled the strip. */  | 
195  | 0  |   if (post->next_row >= post->strip_height) { | 
196  | 0  |     post->starting_row += post->strip_height;  | 
197  | 0  |     post->next_row = 0;  | 
198  | 0  |   }  | 
199  | 0  | }  | 
200  |  |  | 
201  |  |  | 
202  |  | /*  | 
203  |  |  * Process some data in the second pass of 2-pass quantization.  | 
204  |  |  */  | 
205  |  |  | 
206  |  | METHODDEF(void)  | 
207  |  | post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,  | 
208  |  |                    JDIMENSION *in_row_group_ctr,  | 
209  |  |                    JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,  | 
210  |  |                    JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)  | 
211  | 0  | { | 
212  | 0  |   my_post_ptr post = (my_post_ptr)cinfo->post;  | 
213  | 0  |   JDIMENSION num_rows, max_rows;  | 
214  |  |  | 
215  |  |   /* Reposition virtual buffer if at start of strip. */  | 
216  | 0  |   if (post->next_row == 0) { | 
217  | 0  |     post->buffer = (*cinfo->mem->access_virt_sarray)  | 
218  | 0  |         ((j_common_ptr)cinfo, post->whole_image,  | 
219  | 0  |          post->starting_row, post->strip_height, FALSE);  | 
220  | 0  |   }  | 
221  |  |  | 
222  |  |   /* Determine number of rows to emit. */  | 
223  | 0  |   num_rows = post->strip_height - post->next_row; /* available in strip */  | 
224  | 0  |   max_rows = out_rows_avail - *out_row_ctr; /* available in output area */  | 
225  | 0  |   if (num_rows > max_rows)  | 
226  | 0  |     num_rows = max_rows;  | 
227  |  |   /* We have to check bottom of image here, can't depend on upsampler. */  | 
228  | 0  |   max_rows = cinfo->output_height - post->starting_row;  | 
229  | 0  |   if (num_rows > max_rows)  | 
230  | 0  |     num_rows = max_rows;  | 
231  |  |  | 
232  |  |   /* Quantize and emit data. */  | 
233  | 0  |   (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + post->next_row,  | 
234  | 0  |                                        output_buf + *out_row_ctr,  | 
235  | 0  |                                        (int)num_rows);  | 
236  | 0  |   *out_row_ctr += num_rows;  | 
237  |  |  | 
238  |  |   /* Advance if we filled the strip. */  | 
239  | 0  |   post->next_row += num_rows;  | 
240  | 0  |   if (post->next_row >= post->strip_height) { | 
241  | 0  |     post->starting_row += post->strip_height;  | 
242  | 0  |     post->next_row = 0;  | 
243  | 0  |   }  | 
244  | 0  | }  | 
245  |  |  | 
246  |  | #endif /* QUANT_2PASS_SUPPORTED */  | 
247  |  |  | 
248  |  |  | 
249  |  | /*  | 
250  |  |  * Initialize postprocessing controller.  | 
251  |  |  */  | 
252  |  |  | 
253  |  | GLOBAL(void)  | 
254  |  | jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer)  | 
255  | 0  | { | 
256  | 0  |   my_post_ptr post;  | 
257  |  | 
  | 
258  | 0  |   post = (my_post_ptr)  | 
259  | 0  |     (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,  | 
260  | 0  |                                 sizeof(my_post_controller));  | 
261  | 0  |   cinfo->post = (struct jpeg_d_post_controller *)post;  | 
262  | 0  |   post->pub.start_pass = start_pass_dpost;  | 
263  | 0  |   post->whole_image = NULL;     /* flag for no virtual arrays */  | 
264  | 0  |   post->buffer = NULL;          /* flag for no strip buffer */  | 
265  |  |  | 
266  |  |   /* Create the quantization buffer, if needed */  | 
267  | 0  |   if (cinfo->quantize_colors) { | 
268  |  |     /* The buffer strip height is max_v_samp_factor, which is typically  | 
269  |  |      * an efficient number of rows for upsampling to return.  | 
270  |  |      * (In the presence of output rescaling, we might want to be smarter?)  | 
271  |  |      */  | 
272  | 0  |     post->strip_height = (JDIMENSION)cinfo->max_v_samp_factor;  | 
273  | 0  |     if (need_full_buffer) { | 
274  |  |       /* Two-pass color quantization: need full-image storage. */  | 
275  |  |       /* We round up the number of rows to a multiple of the strip height. */  | 
276  | 0  | #ifdef QUANT_2PASS_SUPPORTED  | 
277  | 0  |       post->whole_image = (*cinfo->mem->request_virt_sarray)  | 
278  | 0  |         ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,  | 
279  | 0  |          cinfo->output_width * cinfo->out_color_components,  | 
280  | 0  |          (JDIMENSION)jround_up((long)cinfo->output_height,  | 
281  | 0  |                                (long)post->strip_height),  | 
282  | 0  |          post->strip_height);  | 
283  |  | #else  | 
284  |  |       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);  | 
285  |  | #endif /* QUANT_2PASS_SUPPORTED */  | 
286  | 0  |     } else { | 
287  |  |       /* One-pass color quantization: just make a strip buffer. */  | 
288  | 0  |       post->buffer = (*cinfo->mem->alloc_sarray)  | 
289  | 0  |         ((j_common_ptr)cinfo, JPOOL_IMAGE,  | 
290  | 0  |          cinfo->output_width * cinfo->out_color_components,  | 
291  | 0  |          post->strip_height);  | 
292  | 0  |     }  | 
293  | 0  |   }  | 
294  | 0  | }  |