]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/jpeg6/jdpostct.cpp
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / libs / jpeg6 / jdpostct.cpp
1 /*\r
2 \r
3  * jdpostct.c\r
4 \r
5  *\r
6 \r
7  * Copyright (C) 1994-1995, Thomas G. Lane.\r
8 \r
9  * This file is part of the Independent JPEG Group's software.\r
10 \r
11  * For conditions of distribution and use, see the accompanying README file.\r
12 \r
13  *\r
14 \r
15  * This file contains the decompression postprocessing controller.\r
16 \r
17  * This controller manages the upsampling, color conversion, and color\r
18 \r
19  * quantization/reduction steps; specifically, it controls the buffering\r
20 \r
21  * between upsample/color conversion and color quantization/reduction.\r
22 \r
23  *\r
24 \r
25  * If no color quantization/reduction is required, then this module has no\r
26 \r
27  * work to do, and it just hands off to the upsample/color conversion code.\r
28 \r
29  * An integrated upsample/convert/quantize process would replace this module\r
30 \r
31  * entirely.\r
32 \r
33  */\r
34 \r
35 \r
36 \r
37 #define JPEG_INTERNALS\r
38 \r
39 #include "jinclude.h"\r
40 \r
41 #include "radiant_jpeglib.h"\r
42 \r
43 \r
44 \r
45 \r
46 \r
47 /* Private buffer controller object */\r
48 \r
49 \r
50 \r
51 typedef struct {\r
52 \r
53   struct jpeg_d_post_controller pub; /* public fields */\r
54 \r
55 \r
56 \r
57   /* Color quantization source buffer: this holds output data from\r
58 \r
59    * the upsample/color conversion step to be passed to the quantizer.\r
60 \r
61    * For two-pass color quantization, we need a full-image buffer;\r
62 \r
63    * for one-pass operation, a strip buffer is sufficient.\r
64 \r
65    */\r
66 \r
67   jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */\r
68 \r
69   JSAMPARRAY buffer;            /* strip buffer, or current strip of virtual */\r
70 \r
71   JDIMENSION strip_height;      /* buffer size in rows */\r
72 \r
73   /* for two-pass mode only: */\r
74 \r
75   JDIMENSION starting_row;      /* row # of first row in current strip */\r
76 \r
77   JDIMENSION next_row;          /* index of next row to fill/empty in strip */\r
78 \r
79 } my_post_controller;\r
80 \r
81 \r
82 \r
83 typedef my_post_controller * my_post_ptr;\r
84 \r
85 \r
86 \r
87 \r
88 \r
89 /* Forward declarations */\r
90 \r
91 METHODDEF void post_process_1pass\r
92 \r
93         JPP((j_decompress_ptr cinfo,\r
94 \r
95              JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,\r
96 \r
97              JDIMENSION in_row_groups_avail,\r
98 \r
99              JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,\r
100 \r
101              JDIMENSION out_rows_avail));\r
102 \r
103 #ifdef QUANT_2PASS_SUPPORTED\r
104 \r
105 METHODDEF void post_process_prepass\r
106 \r
107         JPP((j_decompress_ptr cinfo,\r
108 \r
109              JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,\r
110 \r
111              JDIMENSION in_row_groups_avail,\r
112 \r
113              JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,\r
114 \r
115              JDIMENSION out_rows_avail));\r
116 \r
117 METHODDEF void post_process_2pass\r
118 \r
119         JPP((j_decompress_ptr cinfo,\r
120 \r
121              JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,\r
122 \r
123              JDIMENSION in_row_groups_avail,\r
124 \r
125              JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,\r
126 \r
127              JDIMENSION out_rows_avail));\r
128 \r
129 #endif\r
130 \r
131 \r
132 \r
133 \r
134 \r
135 /*\r
136 \r
137  * Initialize for a processing pass.\r
138 \r
139  */\r
140 \r
141 \r
142 \r
143 METHODDEF void\r
144 \r
145 start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)\r
146 \r
147 {\r
148 \r
149   my_post_ptr post = (my_post_ptr) cinfo->post;\r
150 \r
151 \r
152 \r
153   switch (pass_mode) {\r
154 \r
155   case JBUF_PASS_THRU:\r
156 \r
157     if (cinfo->quantize_colors) {\r
158 \r
159       /* Single-pass processing with color quantization. */\r
160 \r
161       post->pub.post_process_data = post_process_1pass;\r
162 \r
163       /* We could be doing buffered-image output before starting a 2-pass\r
164 \r
165        * color quantization; in that case, jinit_d_post_controller did not\r
166 \r
167        * allocate a strip buffer.  Use the virtual-array buffer as workspace.\r
168 \r
169        */\r
170 \r
171       if (post->buffer == NULL) {\r
172 \r
173         post->buffer = (*cinfo->mem->access_virt_sarray)\r
174 \r
175           ((j_common_ptr) cinfo, post->whole_image,\r
176 \r
177            (JDIMENSION) 0, post->strip_height, TRUE);\r
178 \r
179       }\r
180 \r
181     } else {\r
182 \r
183       /* For single-pass processing without color quantization,\r
184 \r
185        * I have no work to do; just call the upsampler directly.\r
186 \r
187        */\r
188 \r
189       post->pub.post_process_data = cinfo->upsample->upsample;\r
190 \r
191     }\r
192 \r
193     break;\r
194 \r
195 #ifdef QUANT_2PASS_SUPPORTED\r
196 \r
197   case JBUF_SAVE_AND_PASS:\r
198 \r
199     /* First pass of 2-pass quantization */\r
200 \r
201     if (post->whole_image == NULL)\r
202 \r
203       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);\r
204 \r
205     post->pub.post_process_data = post_process_prepass;\r
206 \r
207     break;\r
208 \r
209   case JBUF_CRANK_DEST:\r
210 \r
211     /* Second pass of 2-pass quantization */\r
212 \r
213     if (post->whole_image == NULL)\r
214 \r
215       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);\r
216 \r
217     post->pub.post_process_data = post_process_2pass;\r
218 \r
219     break;\r
220 \r
221 #endif /* QUANT_2PASS_SUPPORTED */\r
222 \r
223   default:\r
224 \r
225     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);\r
226 \r
227     break;\r
228 \r
229   }\r
230 \r
231   post->starting_row = post->next_row = 0;\r
232 \r
233 }\r
234 \r
235 \r
236 \r
237 \r
238 \r
239 /*\r
240 \r
241  * Process some data in the one-pass (strip buffer) case.\r
242 \r
243  * This is used for color precision reduction as well as one-pass quantization.\r
244 \r
245  */\r
246 \r
247 \r
248 \r
249 METHODDEF void\r
250 \r
251 post_process_1pass (j_decompress_ptr cinfo,\r
252 \r
253                     JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,\r
254 \r
255                     JDIMENSION in_row_groups_avail,\r
256 \r
257                     JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,\r
258 \r
259                     JDIMENSION out_rows_avail)\r
260 \r
261 {\r
262 \r
263   my_post_ptr post = (my_post_ptr) cinfo->post;\r
264 \r
265   JDIMENSION num_rows, max_rows;\r
266 \r
267 \r
268 \r
269   /* Fill the buffer, but not more than what we can dump out in one go. */\r
270 \r
271   /* Note we rely on the upsampler to detect bottom of image. */\r
272 \r
273   max_rows = out_rows_avail - *out_row_ctr;\r
274 \r
275   if (max_rows > post->strip_height)\r
276 \r
277     max_rows = post->strip_height;\r
278 \r
279   num_rows = 0;\r
280 \r
281   (*cinfo->upsample->upsample) (cinfo,\r
282 \r
283                 input_buf, in_row_group_ctr, in_row_groups_avail,\r
284 \r
285                 post->buffer, &num_rows, max_rows);\r
286 \r
287   /* Quantize and emit data. */\r
288 \r
289   (*cinfo->cquantize->color_quantize) (cinfo,\r
290 \r
291                 post->buffer, output_buf + *out_row_ctr, (int) num_rows);\r
292 \r
293   *out_row_ctr += num_rows;\r
294 \r
295 }\r
296 \r
297 \r
298 \r
299 \r
300 \r
301 #ifdef QUANT_2PASS_SUPPORTED\r
302 \r
303 \r
304 \r
305 /*\r
306 \r
307  * Process some data in the first pass of 2-pass quantization.\r
308 \r
309  */\r
310 \r
311 \r
312 \r
313 METHODDEF void\r
314 \r
315 post_process_prepass (j_decompress_ptr cinfo,\r
316 \r
317                       JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,\r
318 \r
319                       JDIMENSION in_row_groups_avail,\r
320 \r
321                       JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,\r
322 \r
323                       JDIMENSION out_rows_avail)\r
324 \r
325 {\r
326 \r
327   my_post_ptr post = (my_post_ptr) cinfo->post;\r
328 \r
329   JDIMENSION old_next_row, num_rows;\r
330 \r
331 \r
332 \r
333   /* Reposition virtual buffer if at start of strip. */\r
334 \r
335   if (post->next_row == 0) {\r
336 \r
337     post->buffer = (*cinfo->mem->access_virt_sarray)\r
338 \r
339         ((j_common_ptr) cinfo, post->whole_image,\r
340 \r
341          post->starting_row, post->strip_height, TRUE);\r
342 \r
343   }\r
344 \r
345 \r
346 \r
347   /* Upsample some data (up to a strip height's worth). */\r
348 \r
349   old_next_row = post->next_row;\r
350 \r
351   (*cinfo->upsample->upsample) (cinfo,\r
352 \r
353                 input_buf, in_row_group_ctr, in_row_groups_avail,\r
354 \r
355                 post->buffer, &post->next_row, post->strip_height);\r
356 \r
357 \r
358 \r
359   /* Allow quantizer to scan new data.  No data is emitted, */\r
360 \r
361   /* but we advance out_row_ctr so outer loop can tell when we're done. */\r
362 \r
363   if (post->next_row > old_next_row) {\r
364 \r
365     num_rows = post->next_row - old_next_row;\r
366 \r
367     (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,\r
368 \r
369                                          (JSAMPARRAY) NULL, (int) num_rows);\r
370 \r
371     *out_row_ctr += num_rows;\r
372 \r
373   }\r
374 \r
375 \r
376 \r
377   /* Advance if we filled the strip. */\r
378 \r
379   if (post->next_row >= post->strip_height) {\r
380 \r
381     post->starting_row += post->strip_height;\r
382 \r
383     post->next_row = 0;\r
384 \r
385   }\r
386 \r
387 }\r
388 \r
389 \r
390 \r
391 \r
392 \r
393 /*\r
394 \r
395  * Process some data in the second pass of 2-pass quantization.\r
396 \r
397  */\r
398 \r
399 \r
400 \r
401 METHODDEF void\r
402 \r
403 post_process_2pass (j_decompress_ptr cinfo,\r
404 \r
405                     JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,\r
406 \r
407                     JDIMENSION in_row_groups_avail,\r
408 \r
409                     JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,\r
410 \r
411                     JDIMENSION out_rows_avail)\r
412 \r
413 {\r
414 \r
415   my_post_ptr post = (my_post_ptr) cinfo->post;\r
416 \r
417   JDIMENSION num_rows, max_rows;\r
418 \r
419 \r
420 \r
421   /* Reposition virtual buffer if at start of strip. */\r
422 \r
423   if (post->next_row == 0) {\r
424 \r
425     post->buffer = (*cinfo->mem->access_virt_sarray)\r
426 \r
427         ((j_common_ptr) cinfo, post->whole_image,\r
428 \r
429          post->starting_row, post->strip_height, FALSE);\r
430 \r
431   }\r
432 \r
433 \r
434 \r
435   /* Determine number of rows to emit. */\r
436 \r
437   num_rows = post->strip_height - post->next_row; /* available in strip */\r
438 \r
439   max_rows = out_rows_avail - *out_row_ctr; /* available in output area */\r
440 \r
441   if (num_rows > max_rows)\r
442 \r
443     num_rows = max_rows;\r
444 \r
445   /* We have to check bottom of image here, can't depend on upsampler. */\r
446 \r
447   max_rows = cinfo->output_height - post->starting_row;\r
448 \r
449   if (num_rows > max_rows)\r
450 \r
451     num_rows = max_rows;\r
452 \r
453 \r
454 \r
455   /* Quantize and emit data. */\r
456 \r
457   (*cinfo->cquantize->color_quantize) (cinfo,\r
458 \r
459                 post->buffer + post->next_row, output_buf + *out_row_ctr,\r
460 \r
461                 (int) num_rows);\r
462 \r
463   *out_row_ctr += num_rows;\r
464 \r
465 \r
466 \r
467   /* Advance if we filled the strip. */\r
468 \r
469   post->next_row += num_rows;\r
470 \r
471   if (post->next_row >= post->strip_height) {\r
472 \r
473     post->starting_row += post->strip_height;\r
474 \r
475     post->next_row = 0;\r
476 \r
477   }\r
478 \r
479 }\r
480 \r
481 \r
482 \r
483 #endif /* QUANT_2PASS_SUPPORTED */\r
484 \r
485 \r
486 \r
487 \r
488 \r
489 /*\r
490 \r
491  * Initialize postprocessing controller.\r
492 \r
493  */\r
494 \r
495 \r
496 \r
497 GLOBAL void\r
498 \r
499 jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)\r
500 \r
501 {\r
502 \r
503   my_post_ptr post;\r
504 \r
505 \r
506 \r
507   post = (my_post_ptr)\r
508 \r
509     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,\r
510 \r
511                                 SIZEOF(my_post_controller));\r
512 \r
513   cinfo->post = (struct jpeg_d_post_controller *) post;\r
514 \r
515   post->pub.start_pass = start_pass_dpost;\r
516 \r
517   post->whole_image = NULL;     /* flag for no virtual arrays */\r
518 \r
519   post->buffer = NULL;          /* flag for no strip buffer */\r
520 \r
521 \r
522 \r
523   /* Create the quantization buffer, if needed */\r
524 \r
525   if (cinfo->quantize_colors) {\r
526 \r
527     /* The buffer strip height is max_v_samp_factor, which is typically\r
528 \r
529      * an efficient number of rows for upsampling to return.\r
530 \r
531      * (In the presence of output rescaling, we might want to be smarter?)\r
532 \r
533      */\r
534 \r
535     post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;\r
536 \r
537     if (need_full_buffer) {\r
538 \r
539       /* Two-pass color quantization: need full-image storage. */\r
540 \r
541       /* We round up the number of rows to a multiple of the strip height. */\r
542 \r
543 #ifdef QUANT_2PASS_SUPPORTED\r
544 \r
545       post->whole_image = (*cinfo->mem->request_virt_sarray)\r
546 \r
547         ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,\r
548 \r
549          cinfo->output_width * cinfo->out_color_components,\r
550 \r
551          (JDIMENSION) jround_up((long) cinfo->output_height,\r
552 \r
553                                 (long) post->strip_height),\r
554 \r
555          post->strip_height);\r
556 \r
557 #else\r
558 \r
559       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);\r
560 \r
561 #endif /* QUANT_2PASS_SUPPORTED */\r
562 \r
563     } else {\r
564 \r
565       /* One-pass color quantization: just make a strip buffer. */\r
566 \r
567       post->buffer = (*cinfo->mem->alloc_sarray)\r
568 \r
569         ((j_common_ptr) cinfo, JPOOL_IMAGE,\r
570 \r
571          cinfo->output_width * cinfo->out_color_components,\r
572 \r
573          post->strip_height);\r
574 \r
575     }\r
576 \r
577   }\r
578 \r
579 }\r
580 \r