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.}
30 { Pointer to routine to upsample a single component }
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. }
40 procedure jinit_upsampler (cinfo
: j_decompress_ptr
);
47 my_upsample_ptr
= ^my_upsampler
;
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
;
76 { Initialize for an upsampling pass. }
79 procedure start_pass_upsample (cinfo
: j_decompress_ptr
);
81 upsample
: my_upsample_ptr
;
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
;
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. }
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
);
107 upsample
: my_upsample_ptr
;
109 compptr
: jpeg_component_info_ptr
;
110 num_rows
: JDIMENSION
;
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
117 compptr
:= jpeg_component_info_ptr(cinfo
^.comp_info
);
118 for ci
:= 0 to pred(cinfo
^.num_components
) do
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
]);
130 upsample
^.next_row_out
:= 0;
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
])),
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
);
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. }
173 procedure fullsize_upsample (cinfo
: j_decompress_ptr
;
174 compptr
: jpeg_component_info_ptr
;
175 input_data
: JSAMPARRAY
;
176 var output_data_ptr
: JSAMPARRAY
);
178 output_data_ptr
:= input_data
;
182 { This is a no-op version used for "uninteresting" components.
183 These components will not be referenced by color conversion. }
186 procedure noop_upsample (cinfo
: j_decompress_ptr
;
187 compptr
: jpeg_component_info_ptr
;
188 input_data
: JSAMPARRAY
;
189 var output_data_ptr
: JSAMPARRAY
);
191 output_data_ptr
:= NIL; { safety check }
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. }
205 procedure int_upsample (cinfo
: j_decompress_ptr
;
206 compptr
: jpeg_component_info_ptr
;
207 input_data
: JSAMPARRAY
;
208 var output_data_ptr
: JSAMPARRAY
);
210 upsample
: my_upsample_ptr
;
211 output_data
: JSAMPARRAY
;
212 {register} inptr
, outptr
: JSAMPLE_PTR
;
213 {register} invalue
: JSAMPLE
;
216 h_expand
, v_expand
: int
;
219 outcount
: int
; { Nomssi: avoid pointer arithmetic }
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
];
229 while (outrow
< cinfo
^.max_v_samp_factor
) do
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 }
237 invalue
:= inptr
^; { don't need GETJSAMPLE() here }
239 for h
:= pred(h_expand
) downto 0 do
242 inc(outptr
); { <-- fix: this was left out in PasJpeg 1.0 }
243 Dec(outcount
); { thanks to Jannie Gerber for the report }
247 { Generate any additional output rows by duplicating the first one }
248 if (v_expand
> 1) then
250 jcopy_sample_rows(output_data
, outrow
, output_data
, outrow
+1,
251 v_expand
-1, cinfo
^.output_width
);
254 Inc(outrow
, v_expand
);
259 { Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
260 It's still a box filter. }
263 procedure h2v1_upsample (cinfo
: j_decompress_ptr
;
264 compptr
: jpeg_component_info_ptr
;
265 input_data
: JSAMPARRAY
;
266 var output_data_ptr
: JSAMPARRAY
);
268 output_data
: JSAMPARRAY
;
269 {register} inptr
, outptr
: JSAMPLE_PTR
;
270 {register} invalue
: JSAMPLE
;
275 output_data
:= output_data_ptr
;
277 for inrow
:= 0 to pred(cinfo
^.max_v_samp_factor
) do
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
285 invalue
:= inptr
^; { don't need GETJSAMPLE() here }
291 Dec(outcount
, 2); { Nomssi: to avoid pointer arithmetic }
297 { Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
298 It's still a box filter. }
301 procedure h2v2_upsample (cinfo
: j_decompress_ptr
;
302 compptr
: jpeg_component_info_ptr
;
303 input_data
: JSAMPARRAY
;
304 var output_data_ptr
: JSAMPARRAY
);
306 output_data
: JSAMPARRAY
;
307 {register} inptr
, outptr
: JSAMPLE_PTR
;
308 {register} invalue
: JSAMPLE
;
313 output_data
:= output_data_ptr
;
317 while (outrow
< cinfo
^.max_v_samp_factor
) do
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
325 invalue
:= inptr
^; { don't need GETJSAMPLE() here }
333 jcopy_sample_rows(output_data
, outrow
, output_data
, outrow
+1,
334 1, cinfo
^.output_width
);
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). }
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
);
360 output_data
: JSAMPARRAY
;
361 {register} pre_inptr
, inptr
, outptr
: JSAMPLE_PTR
;
362 {register} invalue
: int
;
363 {register} colctr
: JDIMENSION
;
366 output_data
:= output_data_ptr
;
368 for inrow
:= 0 to pred(cinfo
^.max_v_samp_factor
) do
370 inptr
:= JSAMPLE_PTR(input_data
^[inrow
]);
371 outptr
:= JSAMPLE_PTR(output_data
^[inrow
]);
372 { Special case for first column }
374 invalue
:= GETJSAMPLE(inptr
^);
376 outptr
^ := JSAMPLE (invalue
);
378 outptr
^ := JSAMPLE ((invalue
* 3 + GETJSAMPLE(inptr
^) + 2) shr 2);
381 for colctr
:= pred(compptr
^.downsampled_width
- 2) downto 0 do
383 { General case: 3/4 * nearer pixel + 1/4 * further pixel }
384 invalue
:= GETJSAMPLE(inptr
^) * 3;
386 outptr
^ := JSAMPLE ((invalue
+ GETJSAMPLE(pre_inptr
^) + 1) shr 2);
389 outptr
^ := JSAMPLE ((invalue
+ GETJSAMPLE(inptr
^) + 2) shr 2);
393 { Special case for last column }
394 invalue
:= GETJSAMPLE(inptr
^);
395 outptr
^ := JSAMPLE ((invalue
* 3 + GETJSAMPLE(pre_inptr
^) + 1) shr 2);
397 outptr
^ := JSAMPLE (invalue
);
398 {Inc(outptr); - value never used }
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). }
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
);
415 output_data
: JSAMPARRAY
;
416 {register} inptr0
, inptr1
, outptr
: JSAMPLE_PTR
;
417 {$ifdef BITS_IN_JSAMPLE_IS_8}
418 {register} thiscolsum
, lastcolsum
, nextcolsum
: int
;
420 {register} thiscolsum
, lastcolsum
, nextcolsum
: INT32
;
422 {register} colctr
: JDIMENSION
;
423 inrow
, outrow
, v
: int
;
425 prev_input_data
: JSAMPARRAY
; { Nomssi work around }
427 output_data
:= output_data_ptr
;
431 while (outrow
< cinfo
^.max_v_samp_factor
) do
433 for v
:= 0 to pred(2) do
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 }
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
]);
444 else { next nearest is row below }
445 inptr1
:= JSAMPLE_PTR(input_data
^[inrow
+1]);
446 outptr
:= JSAMPLE_PTR(output_data
^[outrow
]);
449 { Special case for first column }
450 thiscolsum
:= GETJSAMPLE(inptr0
^) * 3 + GETJSAMPLE(inptr1
^);
453 nextcolsum
:= GETJSAMPLE(inptr0
^) * 3 + GETJSAMPLE(inptr1
^);
457 outptr
^ := JSAMPLE ((thiscolsum
* 4 + 8) shr 4);
459 outptr
^ := JSAMPLE ((thiscolsum
* 3 + nextcolsum
+ 7) shr 4);
461 lastcolsum
:= thiscolsum
; thiscolsum
:= nextcolsum
;
463 for colctr
:= pred(compptr
^.downsampled_width
- 2) downto 0 do
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
^);
470 outptr
^ := JSAMPLE ((thiscolsum
* 3 + lastcolsum
+ 8) shr 4);
472 outptr
^ := JSAMPLE ((thiscolsum
* 3 + nextcolsum
+ 7) shr 4);
474 lastcolsum
:= thiscolsum
;
475 thiscolsum
:= nextcolsum
;
478 { Special case for last column }
479 outptr
^ := JSAMPLE ((thiscolsum
* 3 + lastcolsum
+ 8) shr 4);
481 outptr
^ := JSAMPLE ((thiscolsum
* 4 + 7) shr 4);
482 {Inc(outptr); - value never used }
489 { Module initialization routine for upsampling. }
492 procedure jinit_upsampler (cinfo
: j_decompress_ptr
);
494 upsample
: my_upsample_ptr
;
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
;
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
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 }
533 if (not compptr
^.component_needed
) then
535 { Don't bother to upsample an uninteresting component. }
536 upsample
^.methods
[ci
] := noop_upsample
;
537 need_buffer
:= FALSE;
540 if (h_in_group
= h_out_group
) and (v_in_group
= v_out_group
) then
542 { Fullsize components can be processed without any work. }
543 upsample
^.methods
[ci
] := fullsize_upsample
;
544 need_buffer
:= FALSE;
547 if (h_in_group
* 2 = h_out_group
) and
548 (v_in_group
= v_out_group
) then
550 { Special cases for 2h1v upsampling }
551 if (do_fancy
) and (compptr
^.downsampled_width
> 2) then
552 upsample
^.methods
[ci
] := h2v1_fancy_upsample
554 upsample
^.methods
[ci
] := h2v1_upsample
;
557 if (h_in_group
* 2 = h_out_group
) and
558 (v_in_group
* 2 = v_out_group
) then
560 { Special cases for 2h2v upsampling }
561 if (do_fancy
) and (compptr
^.downsampled_width
> 2) then
563 upsample
^.methods
[ci
] := h2v2_fancy_upsample
;
564 upsample
^.pub
.need_context_rows
:= TRUE;
567 upsample
^.methods
[ci
] := h2v2_upsample
;
570 if ((h_out_group
mod h_in_group
) = 0) and
571 ((v_out_group
mod v_in_group
) = 0) then
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
);
579 ERREXIT(j_common_ptr(cinfo
), JERR_FRACT_SAMPLE_NOTIMPL
);
580 if (need_buffer
) then
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
));