DEADSOFTWARE

hopefully no more windows
[d2df-editor.git] / src / lib / vampimg / JpegLib / imjdsample.pas
1 unit imjdsample;
3 { Original: jdsample.c; Copyright (C) 1991-1996, Thomas G. Lane. }
5 { This file contains upsampling routines.
7 Upsampling input data is counted in "row groups". A row group
8 is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
9 sample rows of each component. Upsampling will normally produce
10 max_v_samp_factor pixel rows from each row group (but this could vary
11 if the upsampler is applying a scale factor of its own).
13 An excellent reference for image resampling is
14 Digital Image Warping, George Wolberg, 1990.
15 Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.}
17 interface
19 {$I imjconfig.inc}
21 uses
22 imjmorecfg,
23 imjinclude,
24 imjutils,
25 imjpeglib,
26 imjdeferr,
27 imjerror;
30 { Pointer to routine to upsample a single component }
31 type
32 upsample1_ptr = procedure (cinfo : j_decompress_ptr;
33 compptr : jpeg_component_info_ptr;
34 input_data : JSAMPARRAY;
35 var output_data_ptr : JSAMPARRAY);
37 { Module initialization routine for upsampling. }
39 {GLOBAL}
40 procedure jinit_upsampler (cinfo : j_decompress_ptr);
42 implementation
44 { Private subobject }
46 type
47 my_upsample_ptr = ^my_upsampler;
48 my_upsampler = record
49 pub : jpeg_upsampler; { public fields }
51 { Color conversion buffer. When using separate upsampling and color
52 conversion steps, this buffer holds one upsampled row group until it
53 has been color converted and output.
54 Note: we do not allocate any storage for component(s) which are full-size,
55 ie do not need rescaling. The corresponding entry of color_buf[] is
56 simply set to point to the input data array, thereby avoiding copying.}
58 color_buf : array[0..MAX_COMPONENTS-1] of JSAMPARRAY;
60 { Per-component upsampling method pointers }
61 methods : array[0..MAX_COMPONENTS-1] of upsample1_ptr;
63 next_row_out : int; { counts rows emitted from color_buf }
64 rows_to_go : JDIMENSION; { counts rows remaining in image }
66 { Height of an input row group for each component. }
67 rowgroup_height : array[0..MAX_COMPONENTS-1] of int;
69 { These arrays save pixel expansion factors so that int_expand need not
70 recompute them each time. They are unused for other upsampling methods.}
71 h_expand : array[0..MAX_COMPONENTS-1] of UINT8 ;
72 v_expand : array[0..MAX_COMPONENTS-1] of UINT8 ;
73 end;
76 { Initialize for an upsampling pass. }
78 {METHODDEF}
79 procedure start_pass_upsample (cinfo : j_decompress_ptr);
80 var
81 upsample : my_upsample_ptr;
82 begin
83 upsample := my_upsample_ptr (cinfo^.upsample);
85 { Mark the conversion buffer empty }
86 upsample^.next_row_out := cinfo^.max_v_samp_factor;
87 { Initialize total-height counter for detecting bottom of image }
88 upsample^.rows_to_go := cinfo^.output_height;
89 end;
92 { Control routine to do upsampling (and color conversion).
94 In this version we upsample each component independently.
95 We upsample one row group into the conversion buffer, then apply
96 color conversion a row at a time. }
98 {METHODDEF}
99 procedure sep_upsample (cinfo : j_decompress_ptr;
100 input_buf : JSAMPIMAGE;
101 var in_row_group_ctr : JDIMENSION;
102 in_row_groups_avail : JDIMENSION;
103 output_buf : JSAMPARRAY;
104 var out_row_ctr : JDIMENSION;
105 out_rows_avail : JDIMENSION);
106 var
107 upsample : my_upsample_ptr;
108 ci : int;
109 compptr : jpeg_component_info_ptr;
110 num_rows : JDIMENSION;
111 begin
112 upsample := my_upsample_ptr (cinfo^.upsample);
114 { Fill the conversion buffer, if it's empty }
115 if (upsample^.next_row_out >= cinfo^.max_v_samp_factor) then
116 begin
117 compptr := jpeg_component_info_ptr(cinfo^.comp_info);
118 for ci := 0 to pred(cinfo^.num_components) do
119 begin
120 { Invoke per-component upsample method. Notice we pass a POINTER
121 to color_buf[ci], so that fullsize_upsample can change it. }
123 upsample^.methods[ci] (cinfo, compptr,
124 JSAMPARRAY(@ input_buf^[ci]^
125 [LongInt(in_row_group_ctr) * upsample^.rowgroup_height[ci]]),
126 upsample^.color_buf[ci]);
128 Inc(compptr);
129 end;
130 upsample^.next_row_out := 0;
131 end;
133 { Color-convert and emit rows }
135 { How many we have in the buffer: }
136 num_rows := JDIMENSION (cinfo^.max_v_samp_factor - upsample^.next_row_out);
137 { Not more than the distance to the end of the image. Need this test
138 in case the image height is not a multiple of max_v_samp_factor: }
140 if (num_rows > upsample^.rows_to_go) then
141 num_rows := upsample^.rows_to_go;
142 { And not more than what the client can accept: }
143 Dec(out_rows_avail, out_row_ctr);
144 if (num_rows > out_rows_avail) then
145 num_rows := out_rows_avail;
147 cinfo^.cconvert^.color_convert (cinfo,
148 JSAMPIMAGE(@(upsample^.color_buf)),
149 JDIMENSION (upsample^.next_row_out),
150 JSAMPARRAY(@(output_buf^[out_row_ctr])),
151 int (num_rows));
153 { Adjust counts }
154 Inc(out_row_ctr, num_rows);
155 Dec(upsample^.rows_to_go, num_rows);
156 Inc(upsample^.next_row_out, num_rows);
157 { When the buffer is emptied, declare this input row group consumed }
158 if (upsample^.next_row_out >= cinfo^.max_v_samp_factor) then
159 Inc(in_row_group_ctr);
160 end;
163 { These are the routines invoked by sep_upsample to upsample pixel values
164 of a single component. One row group is processed per call. }
167 { For full-size components, we just make color_buf[ci] point at the
168 input buffer, and thus avoid copying any data. Note that this is
169 safe only because sep_upsample doesn't declare the input row group
170 "consumed" until we are done color converting and emitting it. }
172 {METHODDEF}
173 procedure fullsize_upsample (cinfo : j_decompress_ptr;
174 compptr : jpeg_component_info_ptr;
175 input_data : JSAMPARRAY;
176 var output_data_ptr : JSAMPARRAY);
177 begin
178 output_data_ptr := input_data;
179 end;
182 { This is a no-op version used for "uninteresting" components.
183 These components will not be referenced by color conversion. }
185 {METHODDEF}
186 procedure noop_upsample (cinfo : j_decompress_ptr;
187 compptr : jpeg_component_info_ptr;
188 input_data : JSAMPARRAY;
189 var output_data_ptr : JSAMPARRAY);
190 begin
191 output_data_ptr := NIL; { safety check }
192 end;
195 { This version handles any integral sampling ratios.
196 This is not used for typical JPEG files, so it need not be fast.
197 Nor, for that matter, is it particularly accurate: the algorithm is
198 simple replication of the input pixel onto the corresponding output
199 pixels. The hi-falutin sampling literature refers to this as a
200 "box filter". A box filter tends to introduce visible artifacts,
201 so if you are actually going to use 3:1 or 4:1 sampling ratios
202 you would be well advised to improve this code. }
204 {METHODDEF}
205 procedure int_upsample (cinfo : j_decompress_ptr;
206 compptr : jpeg_component_info_ptr;
207 input_data : JSAMPARRAY;
208 var output_data_ptr : JSAMPARRAY);
209 var
210 upsample : my_upsample_ptr;
211 output_data : JSAMPARRAY;
212 {register} inptr, outptr : JSAMPLE_PTR;
213 {register} invalue : JSAMPLE;
214 {register} h : int;
215 {outend}
216 h_expand, v_expand : int;
217 inrow, outrow : int;
218 var
219 outcount : int; { Nomssi: avoid pointer arithmetic }
220 begin
221 upsample := my_upsample_ptr (cinfo^.upsample);
222 output_data := output_data_ptr;
224 h_expand := upsample^.h_expand[compptr^.component_index];
225 v_expand := upsample^.v_expand[compptr^.component_index];
227 inrow := 0;
228 outrow := 0;
229 while (outrow < cinfo^.max_v_samp_factor) do
230 begin
231 { Generate one output row with proper horizontal expansion }
232 inptr := JSAMPLE_PTR(input_data^[inrow]);
233 outptr := JSAMPLE_PTR(output_data^[outrow]);
234 outcount := cinfo^.output_width;
235 while (outcount > 0) do { Nomssi }
236 begin
237 invalue := inptr^; { don't need GETJSAMPLE() here }
238 Inc(inptr);
239 for h := pred(h_expand) downto 0 do
240 begin
241 outptr^ := invalue;
242 inc(outptr); { <-- fix: this was left out in PasJpeg 1.0 }
243 Dec(outcount); { thanks to Jannie Gerber for the report }
244 end;
245 end;
247 { Generate any additional output rows by duplicating the first one }
248 if (v_expand > 1) then
249 begin
250 jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
251 v_expand-1, cinfo^.output_width);
252 end;
253 Inc(inrow);
254 Inc(outrow, v_expand);
255 end;
256 end;
259 { Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
260 It's still a box filter. }
262 {METHODDEF}
263 procedure h2v1_upsample (cinfo : j_decompress_ptr;
264 compptr : jpeg_component_info_ptr;
265 input_data : JSAMPARRAY;
266 var output_data_ptr : JSAMPARRAY);
267 var
268 output_data : JSAMPARRAY;
269 {register} inptr, outptr : JSAMPLE_PTR;
270 {register} invalue : JSAMPLE;
271 {outend : JSAMPROW;}
272 outcount : int;
273 inrow : int;
274 begin
275 output_data := output_data_ptr;
277 for inrow := 0 to pred(cinfo^.max_v_samp_factor) do
278 begin
279 inptr := JSAMPLE_PTR(input_data^[inrow]);
280 outptr := JSAMPLE_PTR(output_data^[inrow]);
281 {outend := outptr + cinfo^.output_width;}
282 outcount := cinfo^.output_width;
283 while (outcount > 0) do
284 begin
285 invalue := inptr^; { don't need GETJSAMPLE() here }
286 Inc(inptr);
287 outptr^ := invalue;
288 Inc(outptr);
289 outptr^ := invalue;
290 Inc(outptr);
291 Dec(outcount, 2); { Nomssi: to avoid pointer arithmetic }
292 end;
293 end;
294 end;
297 { Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
298 It's still a box filter. }
300 {METHODDEF}
301 procedure h2v2_upsample (cinfo : j_decompress_ptr;
302 compptr : jpeg_component_info_ptr;
303 input_data : JSAMPARRAY;
304 var output_data_ptr : JSAMPARRAY);
305 var
306 output_data : JSAMPARRAY;
307 {register} inptr, outptr : JSAMPLE_PTR;
308 {register} invalue : JSAMPLE;
309 {outend : JSAMPROW;}
310 outcount : int;
311 inrow, outrow : int;
312 begin
313 output_data := output_data_ptr;
315 inrow := 0;
316 outrow := 0;
317 while (outrow < cinfo^.max_v_samp_factor) do
318 begin
319 inptr := JSAMPLE_PTR(input_data^[inrow]);
320 outptr := JSAMPLE_PTR(output_data^[outrow]);
321 {outend := outptr + cinfo^.output_width;}
322 outcount := cinfo^.output_width;
323 while (outcount > 0) do
324 begin
325 invalue := inptr^; { don't need GETJSAMPLE() here }
326 Inc(inptr);
327 outptr^ := invalue;
328 Inc(outptr);
329 outptr^ := invalue;
330 Inc(outptr);
331 Dec(outcount, 2);
332 end;
333 jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
334 1, cinfo^.output_width);
335 Inc(inrow);
336 Inc(outrow, 2);
337 end;
338 end;
341 { Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
343 The upsampling algorithm is linear interpolation between pixel centers,
344 also known as a "triangle filter". This is a good compromise between
345 speed and visual quality. The centers of the output pixels are 1/4 and 3/4
346 of the way between input pixel centers.
348 A note about the "bias" calculations: when rounding fractional values to
349 integer, we do not want to always round 0.5 up to the next integer.
350 If we did that, we'd introduce a noticeable bias towards larger values.
351 Instead, this code is arranged so that 0.5 will be rounded up or down at
352 alternate pixel locations (a simple ordered dither pattern). }
354 {METHODDEF}
355 procedure h2v1_fancy_upsample (cinfo : j_decompress_ptr;
356 compptr : jpeg_component_info_ptr;
357 input_data : JSAMPARRAY;
358 var output_data_ptr : JSAMPARRAY);
359 var
360 output_data : JSAMPARRAY;
361 {register} pre_inptr, inptr, outptr : JSAMPLE_PTR;
362 {register} invalue : int;
363 {register} colctr : JDIMENSION;
364 inrow : int;
365 begin
366 output_data := output_data_ptr;
368 for inrow := 0 to pred(cinfo^.max_v_samp_factor) do
369 begin
370 inptr := JSAMPLE_PTR(input_data^[inrow]);
371 outptr := JSAMPLE_PTR(output_data^[inrow]);
372 { Special case for first column }
373 pre_inptr := inptr;
374 invalue := GETJSAMPLE(inptr^);
375 Inc(inptr);
376 outptr^ := JSAMPLE (invalue);
377 Inc(outptr);
378 outptr^ := JSAMPLE ((invalue * 3 + GETJSAMPLE(inptr^) + 2) shr 2);
379 Inc(outptr);
381 for colctr := pred(compptr^.downsampled_width - 2) downto 0 do
382 begin
383 { General case: 3/4 * nearer pixel + 1/4 * further pixel }
384 invalue := GETJSAMPLE(inptr^) * 3;
385 Inc(inptr);
386 outptr^ := JSAMPLE ((invalue + GETJSAMPLE(pre_inptr^) + 1) shr 2);
387 Inc(pre_inptr);
388 Inc(outptr);
389 outptr^ := JSAMPLE ((invalue + GETJSAMPLE(inptr^) + 2) shr 2);
390 Inc(outptr);
391 end;
393 { Special case for last column }
394 invalue := GETJSAMPLE(inptr^);
395 outptr^ := JSAMPLE ((invalue * 3 + GETJSAMPLE(pre_inptr^) + 1) shr 2);
396 Inc(outptr);
397 outptr^ := JSAMPLE (invalue);
398 {Inc(outptr); - value never used }
399 end;
400 end;
403 { Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
404 Again a triangle filter; see comments for h2v1 case, above.
406 It is OK for us to reference the adjacent input rows because we demanded
407 context from the main buffer controller (see initialization code). }
409 {METHODDEF}
410 procedure h2v2_fancy_upsample (cinfo : j_decompress_ptr;
411 compptr : jpeg_component_info_ptr;
412 input_data : JSAMPARRAY;
413 var output_data_ptr : JSAMPARRAY);
414 var
415 output_data : JSAMPARRAY;
416 {register} inptr0, inptr1, outptr : JSAMPLE_PTR;
417 {$ifdef BITS_IN_JSAMPLE_IS_8}
418 {register} thiscolsum, lastcolsum, nextcolsum : int;
419 {$else}
420 {register} thiscolsum, lastcolsum, nextcolsum : INT32;
421 {$endif}
422 {register} colctr : JDIMENSION;
423 inrow, outrow, v : int;
424 var
425 prev_input_data : JSAMPARRAY; { Nomssi work around }
426 begin
427 output_data := output_data_ptr;
429 outrow := 0;
430 inrow := 0;
431 while (outrow < cinfo^.max_v_samp_factor) do
432 begin
433 for v := 0 to pred(2) do
434 begin
435 { inptr0 points to nearest input row, inptr1 points to next nearest }
436 inptr0 := JSAMPLE_PTR(input_data^[inrow]);
437 if (v = 0) then { next nearest is row above }
438 begin
439 {inptr1 := JSAMPLE_PTR(input_data^[inrow-1]);}
440 prev_input_data := input_data; { work around }
441 Dec(JSAMPROW_PTR(prev_input_data)); { negative offsets }
442 inptr1 := JSAMPLE_PTR(prev_input_data^[inrow]);
443 end
444 else { next nearest is row below }
445 inptr1 := JSAMPLE_PTR(input_data^[inrow+1]);
446 outptr := JSAMPLE_PTR(output_data^[outrow]);
447 Inc(outrow);
449 { Special case for first column }
450 thiscolsum := GETJSAMPLE(inptr0^) * 3 + GETJSAMPLE(inptr1^);
451 Inc(inptr0);
452 Inc(inptr1);
453 nextcolsum := GETJSAMPLE(inptr0^) * 3 + GETJSAMPLE(inptr1^);
454 Inc(inptr0);
455 Inc(inptr1);
457 outptr^ := JSAMPLE ((thiscolsum * 4 + 8) shr 4);
458 Inc(outptr);
459 outptr^ := JSAMPLE ((thiscolsum * 3 + nextcolsum + 7) shr 4);
460 Inc(outptr);
461 lastcolsum := thiscolsum; thiscolsum := nextcolsum;
463 for colctr := pred(compptr^.downsampled_width - 2) downto 0 do
464 begin
465 { General case: 3/4 * nearer pixel + 1/4 * further pixel in each }
466 { dimension, thus 9/16, 3/16, 3/16, 1/16 overall }
467 nextcolsum := GETJSAMPLE(inptr0^) * 3 + GETJSAMPLE(inptr1^);
468 Inc(inptr0);
469 Inc(inptr1);
470 outptr^ := JSAMPLE ((thiscolsum * 3 + lastcolsum + 8) shr 4);
471 Inc(outptr);
472 outptr^ := JSAMPLE ((thiscolsum * 3 + nextcolsum + 7) shr 4);
473 Inc(outptr);
474 lastcolsum := thiscolsum;
475 thiscolsum := nextcolsum;
476 end;
478 { Special case for last column }
479 outptr^ := JSAMPLE ((thiscolsum * 3 + lastcolsum + 8) shr 4);
480 Inc(outptr);
481 outptr^ := JSAMPLE ((thiscolsum * 4 + 7) shr 4);
482 {Inc(outptr); - value never used }
483 end;
484 Inc(inrow);
485 end;
486 end;
489 { Module initialization routine for upsampling. }
491 {GLOBAL}
492 procedure jinit_upsampler (cinfo : j_decompress_ptr);
493 var
494 upsample : my_upsample_ptr;
495 ci : int;
496 compptr : jpeg_component_info_ptr;
497 need_buffer, do_fancy : boolean;
498 h_in_group, v_in_group, h_out_group, v_out_group : int;
499 begin
500 upsample := my_upsample_ptr (
501 cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
502 SIZEOF(my_upsampler)) );
503 cinfo^.upsample := jpeg_upsampler_ptr (upsample);
504 upsample^.pub.start_pass := start_pass_upsample;
505 upsample^.pub.upsample := sep_upsample;
506 upsample^.pub.need_context_rows := FALSE; { until we find out differently }
508 if (cinfo^.CCIR601_sampling) then { this isn't supported }
509 ERREXIT(j_common_ptr(cinfo), JERR_CCIR601_NOTIMPL);
511 { jdmainct.c doesn't support context rows when min_DCT_scaled_size := 1,
512 so don't ask for it. }
514 do_fancy := cinfo^.do_fancy_upsampling and (cinfo^.min_DCT_scaled_size > 1);
516 { Verify we can handle the sampling factors, select per-component methods,
517 and create storage as needed. }
519 compptr := jpeg_component_info_ptr(cinfo^.comp_info);
520 for ci := 0 to pred(cinfo^.num_components) do
521 begin
522 { Compute size of an "input group" after IDCT scaling. This many samples
523 are to be converted to max_h_samp_factor * max_v_samp_factor pixels. }
525 h_in_group := (compptr^.h_samp_factor * compptr^.DCT_scaled_size) div
526 cinfo^.min_DCT_scaled_size;
527 v_in_group := (compptr^.v_samp_factor * compptr^.DCT_scaled_size) div
528 cinfo^.min_DCT_scaled_size;
529 h_out_group := cinfo^.max_h_samp_factor;
530 v_out_group := cinfo^.max_v_samp_factor;
531 upsample^.rowgroup_height[ci] := v_in_group; { save for use later }
532 need_buffer := TRUE;
533 if (not compptr^.component_needed) then
534 begin
535 { Don't bother to upsample an uninteresting component. }
536 upsample^.methods[ci] := noop_upsample;
537 need_buffer := FALSE;
538 end
539 else
540 if (h_in_group = h_out_group) and (v_in_group = v_out_group) then
541 begin
542 { Fullsize components can be processed without any work. }
543 upsample^.methods[ci] := fullsize_upsample;
544 need_buffer := FALSE;
545 end
546 else
547 if (h_in_group * 2 = h_out_group) and
548 (v_in_group = v_out_group) then
549 begin
550 { Special cases for 2h1v upsampling }
551 if (do_fancy) and (compptr^.downsampled_width > 2) then
552 upsample^.methods[ci] := h2v1_fancy_upsample
553 else
554 upsample^.methods[ci] := h2v1_upsample;
555 end
556 else
557 if (h_in_group * 2 = h_out_group) and
558 (v_in_group * 2 = v_out_group) then
559 begin
560 { Special cases for 2h2v upsampling }
561 if (do_fancy) and (compptr^.downsampled_width > 2) then
562 begin
563 upsample^.methods[ci] := h2v2_fancy_upsample;
564 upsample^.pub.need_context_rows := TRUE;
565 end
566 else
567 upsample^.methods[ci] := h2v2_upsample;
568 end
569 else
570 if ((h_out_group mod h_in_group) = 0) and
571 ((v_out_group mod v_in_group) = 0) then
572 begin
573 { Generic integral-factors upsampling method }
574 upsample^.methods[ci] := int_upsample;
575 upsample^.h_expand[ci] := UINT8 (h_out_group div h_in_group);
576 upsample^.v_expand[ci] := UINT8 (v_out_group div v_in_group);
577 end
578 else
579 ERREXIT(j_common_ptr(cinfo), JERR_FRACT_SAMPLE_NOTIMPL);
580 if (need_buffer) then
581 begin
582 upsample^.color_buf[ci] := cinfo^.mem^.alloc_sarray
583 (j_common_ptr(cinfo), JPOOL_IMAGE,
584 JDIMENSION (jround_up( long (cinfo^.output_width),
585 long (cinfo^.max_h_samp_factor))),
586 JDIMENSION (cinfo^.max_v_samp_factor));
587 end;
588 Inc(compptr);
589 end;
590 end;
592 end.