DEADSOFTWARE

hopefully no more windows
[d2df-editor.git] / src / lib / vampimg / JpegLib / imjdpostct.pas
1 unit imjdpostct;
3 { Original: jdpostct.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
5 { This file contains the decompression postprocessing controller.
6 This controller manages the upsampling, color conversion, and color
7 quantization/reduction steps; specifically, it controls the buffering
8 between upsample/color conversion and color quantization/reduction.
10 If no color quantization/reduction is required, then this module has no
11 work to do, and it just hands off to the upsample/color conversion code.
12 An integrated upsample/convert/quantize process would replace this module
13 entirely. }
15 interface
17 {$I imjconfig.inc}
19 uses
20 imjmorecfg,
21 imjinclude,
22 imjdeferr,
23 imjerror,
24 imjutils,
25 imjpeglib;
27 { Initialize postprocessing controller. }
29 {GLOBAL}
30 procedure jinit_d_post_controller (cinfo : j_decompress_ptr;
31 need_full_buffer : boolean);
32 implementation
35 { Private buffer controller object }
37 type
38 my_post_ptr = ^my_post_controller;
39 my_post_controller = record
40 pub : jpeg_d_post_controller; { public fields }
42 { Color quantization source buffer: this holds output data from
43 the upsample/color conversion step to be passed to the quantizer.
44 For two-pass color quantization, we need a full-image buffer;
45 for one-pass operation, a strip buffer is sufficient. }
47 whole_image : jvirt_sarray_ptr; { virtual array, or NIL if one-pass }
48 buffer : JSAMPARRAY; { strip buffer, or current strip of virtual }
49 strip_height : JDIMENSION; { buffer size in rows }
50 { for two-pass mode only: }
51 starting_row : JDIMENSION; { row # of first row in current strip }
52 next_row : JDIMENSION; { index of next row to fill/empty in strip }
53 end;
55 { Forward declarations }
56 {METHODDEF}
57 procedure post_process_1pass(cinfo : j_decompress_ptr;
58 input_buf : JSAMPIMAGE;
59 var in_row_group_ctr : JDIMENSION;
60 in_row_groups_avail : JDIMENSION;
61 output_buf : JSAMPARRAY;
62 var out_row_ctr : JDIMENSION;
63 out_rows_avail : JDIMENSION); forward;
64 {$ifdef QUANT_2PASS_SUPPORTED}
65 {METHODDEF}
66 procedure post_process_prepass(cinfo : j_decompress_ptr;
67 input_buf : JSAMPIMAGE;
68 var in_row_group_ctr : JDIMENSION;
69 in_row_groups_avail : JDIMENSION;
70 output_buf : JSAMPARRAY;
71 var out_row_ctr : JDIMENSION;
72 out_rows_avail : JDIMENSION); forward;
73 {METHODDEF}
74 procedure post_process_2pass(cinfo : j_decompress_ptr;
75 input_buf : JSAMPIMAGE;
76 var in_row_group_ctr : JDIMENSION;
77 in_row_groups_avail : JDIMENSION;
78 output_buf : JSAMPARRAY;
79 var out_row_ctr : JDIMENSION;
80 out_rows_avail : JDIMENSION); forward;
81 {$endif}
84 { Initialize for a processing pass. }
86 {METHODDEF}
87 procedure start_pass_dpost (cinfo : j_decompress_ptr;
88 pass_mode : J_BUF_MODE);
89 var
90 post : my_post_ptr;
91 begin
92 post := my_post_ptr(cinfo^.post);
94 case (pass_mode) of
95 JBUF_PASS_THRU:
96 if (cinfo^.quantize_colors) then
97 begin
98 { Single-pass processing with color quantization. }
99 post^.pub.post_process_data := post_process_1pass;
100 { We could be doing buffered-image output before starting a 2-pass
101 color quantization; in that case, jinit_d_post_controller did not
102 allocate a strip buffer. Use the virtual-array buffer as workspace. }
103 if (post^.buffer = NIL) then
104 begin
105 post^.buffer := cinfo^.mem^.access_virt_sarray
106 (j_common_ptr(cinfo), post^.whole_image,
107 JDIMENSION(0), post^.strip_height, TRUE);
108 end;
109 end
110 else
111 begin
112 { For single-pass processing without color quantization,
113 I have no work to do; just call the upsampler directly. }
115 post^.pub.post_process_data := cinfo^.upsample^.upsample;
116 end;
118 {$ifdef QUANT_2PASS_SUPPORTED}
119 JBUF_SAVE_AND_PASS:
120 begin
121 { First pass of 2-pass quantization }
122 if (post^.whole_image = NIL) then
123 ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
124 post^.pub.post_process_data := post_process_prepass;
125 end;
126 JBUF_CRANK_DEST:
127 begin
128 { Second pass of 2-pass quantization }
129 if (post^.whole_image = NIL) then
130 ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
131 post^.pub.post_process_data := post_process_2pass;
132 end;
133 {$endif} { QUANT_2PASS_SUPPORTED }
134 else
135 ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
136 end;
137 post^.next_row := 0;
138 post^.starting_row := 0;
139 end;
142 { Process some data in the one-pass (strip buffer) case.
143 This is used for color precision reduction as well as one-pass quantization. }
145 {METHODDEF}
146 procedure post_process_1pass (cinfo : j_decompress_ptr;
147 input_buf : JSAMPIMAGE;
148 var in_row_group_ctr : JDIMENSION;
149 in_row_groups_avail : JDIMENSION;
150 output_buf : JSAMPARRAY;
151 var out_row_ctr : JDIMENSION;
152 out_rows_avail : JDIMENSION);
153 var
154 post : my_post_ptr;
155 num_rows, max_rows : JDIMENSION;
156 begin
157 post := my_post_ptr (cinfo^.post);
159 { Fill the buffer, but not more than what we can dump out in one go. }
160 { Note we rely on the upsampler to detect bottom of image. }
161 max_rows := out_rows_avail - out_row_ctr;
162 if (max_rows > post^.strip_height) then
163 max_rows := post^.strip_height;
164 num_rows := 0;
165 cinfo^.upsample^.upsample (cinfo,
166 input_buf,
167 in_row_group_ctr,
168 in_row_groups_avail,
169 post^.buffer,
170 num_rows, { var }
171 max_rows);
172 { Quantize and emit data. }
174 cinfo^.cquantize^.color_quantize (cinfo,
175 post^.buffer,
176 JSAMPARRAY(@ output_buf^[out_row_ctr]),
177 int(num_rows));
179 Inc(out_row_ctr, num_rows);
180 end;
183 {$ifdef QUANT_2PASS_SUPPORTED}
185 { Process some data in the first pass of 2-pass quantization. }
187 {METHODDEF}
188 procedure post_process_prepass (cinfo : j_decompress_ptr;
189 input_buf : JSAMPIMAGE;
190 var in_row_group_ctr : JDIMENSION;
191 in_row_groups_avail : JDIMENSION;
192 output_buf : JSAMPARRAY;
193 var out_row_ctr : JDIMENSION;
194 out_rows_avail:JDIMENSION);
195 var
196 post : my_post_ptr;
197 old_next_row, num_rows : JDIMENSION;
198 begin
199 post := my_post_ptr(cinfo^.post);
201 { Reposition virtual buffer if at start of strip. }
202 if (post^.next_row = 0) then
203 begin
204 post^.buffer := cinfo^.mem^.access_virt_sarray
205 (j_common_ptr(cinfo), post^.whole_image,
206 post^.starting_row, post^.strip_height, TRUE);
207 end;
209 { Upsample some data (up to a strip height's worth). }
210 old_next_row := post^.next_row;
211 cinfo^.upsample^.upsample (cinfo,
212 input_buf, in_row_group_ctr, in_row_groups_avail,
213 post^.buffer, post^.next_row, post^.strip_height);
215 { Allow quantizer to scan new data. No data is emitted, }
216 { but we advance out_row_ctr so outer loop can tell when we're done. }
217 if (post^.next_row > old_next_row) then
218 begin
219 num_rows := post^.next_row - old_next_row;
222 cinfo^.cquantize^.color_quantize (cinfo,
223 JSAMPARRAY(@ post^.buffer^[old_next_row]),
224 JSAMPARRAY(NIL),
225 int(num_rows));
226 Inc(out_row_ctr, num_rows);
227 end;
229 { Advance if we filled the strip. }
230 if (post^.next_row >= post^.strip_height) then
231 begin
232 Inc(post^.starting_row, post^.strip_height);
233 post^.next_row := 0;
234 end;
235 end;
238 { Process some data in the second pass of 2-pass quantization. }
240 {METHODDEF}
241 procedure post_process_2pass (cinfo : j_decompress_ptr;
242 input_buf : JSAMPIMAGE;
243 var in_row_group_ctr : JDIMENSION;
244 in_row_groups_avail : JDIMENSION;
245 output_buf : JSAMPARRAY;
246 var out_row_ctr : JDIMENSION;
247 out_rows_avail : JDIMENSION);
248 var
249 post : my_post_ptr;
250 num_rows, max_rows : JDIMENSION;
251 begin
252 post := my_post_ptr(cinfo^.post);
254 { Reposition virtual buffer if at start of strip. }
255 if (post^.next_row = 0) then
256 begin
257 post^.buffer := cinfo^.mem^.access_virt_sarray
258 (j_common_ptr(cinfo), post^.whole_image,
259 post^.starting_row, post^.strip_height, FALSE);
260 end;
262 { Determine number of rows to emit. }
263 num_rows := post^.strip_height - post^.next_row; { available in strip }
264 max_rows := out_rows_avail - out_row_ctr; { available in output area }
265 if (num_rows > max_rows) then
266 num_rows := max_rows;
267 { We have to check bottom of image here, can't depend on upsampler. }
268 max_rows := cinfo^.output_height - post^.starting_row;
269 if (num_rows > max_rows) then
270 num_rows := max_rows;
272 { Quantize and emit data. }
273 cinfo^.cquantize^.color_quantize (cinfo,
274 JSAMPARRAY(@ post^.buffer^[post^.next_row]),
275 JSAMPARRAY(@ output_buf^[out_row_ctr]),
276 int(num_rows));
277 Inc(out_row_ctr, num_rows);
279 { Advance if we filled the strip. }
280 Inc(post^.next_row, num_rows);
281 if (post^.next_row >= post^.strip_height) then
282 begin
283 Inc(post^.starting_row, post^.strip_height);
284 post^.next_row := 0;
285 end;
286 end;
288 {$endif} { QUANT_2PASS_SUPPORTED }
291 { Initialize postprocessing controller. }
293 {GLOBAL}
294 procedure jinit_d_post_controller (cinfo : j_decompress_ptr;
295 need_full_buffer : boolean);
296 var
297 post : my_post_ptr;
298 begin
299 post := my_post_ptr(
300 cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
301 SIZEOF(my_post_controller)) );
302 cinfo^.post := jpeg_d_post_controller_ptr (post);
303 post^.pub.start_pass := start_pass_dpost;
304 post^.whole_image := NIL; { flag for no virtual arrays }
305 post^.buffer := NIL; { flag for no strip buffer }
307 { Create the quantization buffer, if needed }
308 if (cinfo^.quantize_colors) then
309 begin
310 { The buffer strip height is max_v_samp_factor, which is typically
311 an efficient number of rows for upsampling to return.
312 (In the presence of output rescaling, we might want to be smarter?) }
314 post^.strip_height := JDIMENSION (cinfo^.max_v_samp_factor);
315 if (need_full_buffer) then
316 begin
317 { Two-pass color quantization: need full-image storage. }
318 { We round up the number of rows to a multiple of the strip height. }
319 {$ifdef QUANT_2PASS_SUPPORTED}
320 post^.whole_image := cinfo^.mem^.request_virt_sarray
321 (j_common_ptr(cinfo), JPOOL_IMAGE, FALSE,
322 LongInt(cinfo^.output_width) * cinfo^.out_color_components,
323 JDIMENSION (jround_up( long(cinfo^.output_height),
324 long(post^.strip_height)) ),
325 post^.strip_height);
326 {$else}
327 ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE);
328 {$endif} { QUANT_2PASS_SUPPORTED }
329 end
330 else
331 begin
332 { One-pass color quantization: just make a strip buffer. }
333 post^.buffer := cinfo^.mem^.alloc_sarray
334 (j_common_ptr (cinfo), JPOOL_IMAGE,
335 LongInt(cinfo^.output_width) * cinfo^.out_color_components,
336 post^.strip_height);
337 end;
338 end;
339 end;
341 end.