/src/freeimage-svn/FreeImage/trunk/Source/LibJPEG/jdpostct.c
Line  | Count  | Source  | 
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  |  |  | 
26  |  | typedef 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  |  |  | 
42  |  | typedef my_post_controller * my_post_ptr;  | 
43  |  |  | 
44  |  |  | 
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));  | 
65  |  | #endif  | 
66  |  |  | 
67  |  |  | 
68  |  | /*  | 
69  |  |  * Initialize for a processing pass.  | 
70  |  |  */  | 
71  |  |  | 
72  |  | METHODDEF(void)  | 
73  |  | start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)  | 
74  | 0  | { | 
75  | 0  |   my_post_ptr post = (my_post_ptr) cinfo->post;  | 
76  |  | 
  | 
77  | 0  |   switch (pass_mode) { | 
78  | 0  |   case JBUF_PASS_THRU:  | 
79  | 0  |     if (cinfo->quantize_colors) { | 
80  |  |       /* Single-pass processing with color quantization. */  | 
81  | 0  |       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  | 0  |       if (post->buffer == NULL) { | 
87  | 0  |   post->buffer = (*cinfo->mem->access_virt_sarray)  | 
88  | 0  |     ((j_common_ptr) cinfo, post->whole_image,  | 
89  | 0  |      (JDIMENSION) 0, post->strip_height, TRUE);  | 
90  | 0  |       }  | 
91  | 0  |     } else { | 
92  |  |       /* For single-pass processing without color quantization,  | 
93  |  |        * I have no work to do; just call the upsampler directly.  | 
94  |  |        */  | 
95  | 0  |       post->pub.post_process_data = cinfo->upsample->upsample;  | 
96  | 0  |     }  | 
97  | 0  |     break;  | 
98  | 0  | #ifdef QUANT_2PASS_SUPPORTED  | 
99  | 0  |   case JBUF_SAVE_AND_PASS:  | 
100  |  |     /* First pass of 2-pass quantization */  | 
101  | 0  |     if (post->whole_image == NULL)  | 
102  | 0  |       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);  | 
103  | 0  |     post->pub.post_process_data = post_process_prepass;  | 
104  | 0  |     break;  | 
105  | 0  |   case JBUF_CRANK_DEST:  | 
106  |  |     /* Second 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_2pass;  | 
110  | 0  |     break;  | 
111  | 0  | #endif /* QUANT_2PASS_SUPPORTED */  | 
112  | 0  |   default:  | 
113  | 0  |     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);  | 
114  | 0  |     break;  | 
115  | 0  |   }  | 
116  | 0  |   post->starting_row = post->next_row = 0;  | 
117  | 0  | }  | 
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  |  |  | 
125  |  | METHODDEF(void)  | 
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)  | 
131  | 0  | { | 
132  | 0  |   my_post_ptr post = (my_post_ptr) cinfo->post;  | 
133  | 0  |   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  | 0  |   max_rows = out_rows_avail - *out_row_ctr;  | 
138  | 0  |   if (max_rows > post->strip_height)  | 
139  | 0  |     max_rows = post->strip_height;  | 
140  | 0  |   num_rows = 0;  | 
141  | 0  |   (*cinfo->upsample->upsample) (cinfo,  | 
142  | 0  |     input_buf, in_row_group_ctr, in_row_groups_avail,  | 
143  | 0  |     post->buffer, &num_rows, max_rows);  | 
144  |  |   /* Quantize and emit data. */  | 
145  | 0  |   (*cinfo->cquantize->color_quantize) (cinfo,  | 
146  | 0  |     post->buffer, output_buf + *out_row_ctr, (int) num_rows);  | 
147  | 0  |   *out_row_ctr += num_rows;  | 
148  | 0  | }  | 
149  |  |  | 
150  |  |  | 
151  |  | #ifdef QUANT_2PASS_SUPPORTED  | 
152  |  |  | 
153  |  | /*  | 
154  |  |  * Process some data in the first pass of 2-pass quantization.  | 
155  |  |  */  | 
156  |  |  | 
157  |  | METHODDEF(void)  | 
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)  | 
163  | 0  | { | 
164  | 0  |   my_post_ptr post = (my_post_ptr) cinfo->post;  | 
165  | 0  |   JDIMENSION old_next_row, num_rows;  | 
166  |  |  | 
167  |  |   /* Reposition virtual buffer if at start of strip. */  | 
168  | 0  |   if (post->next_row == 0) { | 
169  | 0  |     post->buffer = (*cinfo->mem->access_virt_sarray)  | 
170  | 0  |   ((j_common_ptr) cinfo, post->whole_image,  | 
171  | 0  |    post->starting_row, post->strip_height, TRUE);  | 
172  | 0  |   }  | 
173  |  |  | 
174  |  |   /* Upsample some data (up to a strip height's worth). */  | 
175  | 0  |   old_next_row = post->next_row;  | 
176  | 0  |   (*cinfo->upsample->upsample) (cinfo,  | 
177  | 0  |     input_buf, in_row_group_ctr, in_row_groups_avail,  | 
178  | 0  |     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  | 0  |   if (post->next_row > old_next_row) { | 
183  | 0  |     num_rows = post->next_row - old_next_row;  | 
184  | 0  |     (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,  | 
185  | 0  |            (JSAMPARRAY) NULL, (int) num_rows);  | 
186  | 0  |     *out_row_ctr += num_rows;  | 
187  | 0  |   }  | 
188  |  |  | 
189  |  |   /* Advance if we filled the strip. */  | 
190  | 0  |   if (post->next_row >= post->strip_height) { | 
191  | 0  |     post->starting_row += post->strip_height;  | 
192  | 0  |     post->next_row = 0;  | 
193  | 0  |   }  | 
194  | 0  | }  | 
195  |  |  | 
196  |  |  | 
197  |  | /*  | 
198  |  |  * Process some data in the second pass of 2-pass quantization.  | 
199  |  |  */  | 
200  |  |  | 
201  |  | METHODDEF(void)  | 
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)  | 
207  | 0  | { | 
208  | 0  |   my_post_ptr post = (my_post_ptr) cinfo->post;  | 
209  | 0  |   JDIMENSION num_rows, max_rows;  | 
210  |  |  | 
211  |  |   /* Reposition virtual buffer if at start of strip. */  | 
212  | 0  |   if (post->next_row == 0) { | 
213  | 0  |     post->buffer = (*cinfo->mem->access_virt_sarray)  | 
214  | 0  |   ((j_common_ptr) cinfo, post->whole_image,  | 
215  | 0  |    post->starting_row, post->strip_height, FALSE);  | 
216  | 0  |   }  | 
217  |  |  | 
218  |  |   /* Determine number of rows to emit. */  | 
219  | 0  |   num_rows = post->strip_height - post->next_row; /* available in strip */  | 
220  | 0  |   max_rows = out_rows_avail - *out_row_ctr; /* available in output area */  | 
221  | 0  |   if (num_rows > max_rows)  | 
222  | 0  |     num_rows = max_rows;  | 
223  |  |   /* We have to check bottom of image here, can't depend on upsampler. */  | 
224  | 0  |   max_rows = cinfo->output_height - post->starting_row;  | 
225  | 0  |   if (num_rows > max_rows)  | 
226  | 0  |     num_rows = max_rows;  | 
227  |  |  | 
228  |  |   /* Quantize and emit data. */  | 
229  | 0  |   (*cinfo->cquantize->color_quantize) (cinfo,  | 
230  | 0  |     post->buffer + post->next_row, output_buf + *out_row_ctr,  | 
231  | 0  |     (int) num_rows);  | 
232  | 0  |   *out_row_ctr += num_rows;  | 
233  |  |  | 
234  |  |   /* Advance if we filled the strip. */  | 
235  | 0  |   post->next_row += num_rows;  | 
236  | 0  |   if (post->next_row >= post->strip_height) { | 
237  | 0  |     post->starting_row += post->strip_height;  | 
238  | 0  |     post->next_row = 0;  | 
239  | 0  |   }  | 
240  | 0  | }  | 
241  |  |  | 
242  |  | #endif /* QUANT_2PASS_SUPPORTED */  | 
243  |  |  | 
244  |  |  | 
245  |  | /*  | 
246  |  |  * Initialize postprocessing controller.  | 
247  |  |  */  | 
248  |  |  | 
249  |  | GLOBAL(void)  | 
250  |  | jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)  | 
251  | 0  | { | 
252  | 0  |   my_post_ptr post;  | 
253  |  | 
  | 
254  | 0  |   post = (my_post_ptr)  | 
255  | 0  |     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,  | 
256  | 0  |         SIZEOF(my_post_controller));  | 
257  | 0  |   cinfo->post = (struct jpeg_d_post_controller *) post;  | 
258  | 0  |   post->pub.start_pass = start_pass_dpost;  | 
259  | 0  |   post->whole_image = NULL; /* flag for no virtual arrays */  | 
260  | 0  |   post->buffer = NULL;   /* flag for no strip buffer */  | 
261  |  |  | 
262  |  |   /* Create the quantization buffer, if needed */  | 
263  | 0  |   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  | 0  |     post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;  | 
269  | 0  |     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  | 0  | #ifdef QUANT_2PASS_SUPPORTED  | 
273  | 0  |       post->whole_image = (*cinfo->mem->request_virt_sarray)  | 
274  | 0  |   ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,  | 
275  | 0  |    cinfo->output_width * cinfo->out_color_components,  | 
276  | 0  |    (JDIMENSION) jround_up((long) cinfo->output_height,  | 
277  | 0  |         (long) post->strip_height),  | 
278  | 0  |    post->strip_height);  | 
279  |  | #else  | 
280  |  |       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);  | 
281  |  | #endif /* QUANT_2PASS_SUPPORTED */  | 
282  | 0  |     } else { | 
283  |  |       /* One-pass color quantization: just make a strip buffer. */  | 
284  | 0  |       post->buffer = (*cinfo->mem->alloc_sarray)  | 
285  | 0  |   ((j_common_ptr) cinfo, JPOOL_IMAGE,  | 
286  | 0  |    cinfo->output_width * cinfo->out_color_components,  | 
287  | 0  |    post->strip_height);  | 
288  | 0  |     }  | 
289  | 0  |   }  | 
290  | 0  | }  |