3 { This file contains code for merged upsampling/color conversion.
5 This file combines functions from jdsample.c and jdcolor.c;
6 read those files first to understand what's going on.
8 When the chroma components are to be upsampled by simple replication
9 (ie, box filtering), we can save some work in color conversion by
10 calculating all the output pixels corresponding to a pair of chroma
11 samples at one time. In the conversion equations
13 G := Y + K2 * Cb + K3 * Cr
15 only the Y term varies among the group of pixels corresponding to a pair
16 of chroma samples, so the rest of the terms can be calculated just once.
17 At typical sampling ratios, this eliminates half or three-quarters of the
18 multiplications needed for color conversion.
20 This file currently provides implementations for the following cases:
21 YCbCr => RGB color conversion only.
22 Sampling ratios of 2h1v or 2h2v.
23 No scaling needed at upsample time.
24 Corner-aligned (non-CCIR601) sampling alignment.
25 Other special cases could be added, but in most applications these are
26 the only common cases. (For uncommon cases we fall back on the more
27 general code in jdsample.c and jdcolor.c.) }
29 { Original: jdmerge.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
41 { Module initialization routine for merged upsampling/color conversion.
43 NB: this is called under the conditions determined by use_merged_upsample()
44 in jdmaster.c. That routine MUST correspond to the actual capabilities
45 of this module; no safety checks are made here. }
48 procedure jinit_merged_upsampler (cinfo
: j_decompress_ptr
);
55 type { the same definition as in JdColor }
56 int_Color_Table
= array[0..MAXJSAMPLE
+1-1] of int
;
57 int_CConvertPtr
= ^int_Color_Table
;
58 INT32_Color_Table
= array[0..MAXJSAMPLE
+1-1] of INT32
;
59 INT32_CConvertPtr
= ^INT32_Color_Table
;
62 my_upsample_ptr
= ^my_upsampler
;
64 pub
: jpeg_upsampler
; { public fields }
66 { Pointer to routine to do actual upsampling/conversion of one row group }
67 upmethod
: procedure (cinfo
: j_decompress_ptr
;
68 input_buf
: JSAMPIMAGE
;
69 in_row_group_ctr
: JDIMENSION
;
70 output_buf
: JSAMPARRAY
);
72 { Private state for YCC->RGB conversion }
73 Cr_r_tab
: int_CConvertPtr
; { => table for Cr to R conversion }
74 Cb_b_tab
: int_CConvertPtr
; { => table for Cb to B conversion }
75 Cr_g_tab
: INT32_CConvertPtr
; { => table for Cr to G conversion }
76 Cb_g_tab
: INT32_CConvertPtr
; { => table for Cb to G conversion }
78 { For 2:1 vertical sampling, we produce two output rows at a time.
79 We need a "spare" row buffer to hold the second output row if the
80 application provides just a one-row buffer; we also use the spare
81 to discard the dummy last row if the image height is odd. }
84 spare_full
: boolean; { TRUE if spare buffer is occupied }
86 out_row_width
: JDIMENSION
; { samples per output row }
87 rows_to_go
: JDIMENSION
; { counts rows remaining in image }
92 SCALEBITS
= 16; { speediest right-shift on some machines }
93 ONE_HALF
= (INT32(1) shl (SCALEBITS
-1));
96 { Initialize tables for YCC->RGB colorspace conversion.
97 This is taken directly from jdcolor.c; see that file for more info. }
100 procedure build_ycc_rgb_table (cinfo
: j_decompress_ptr
);
102 FIX_1_40200
= INT32( Round(1.40200 * (INT32(1) shl SCALEBITS
)) );
103 FIX_1_77200
= INT32( Round(1.77200 * (INT32(1) shl SCALEBITS
)) );
104 FIX_0_71414
= INT32( Round(0.71414 * (INT32(1) shl SCALEBITS
)) );
105 FIX_0_34414
= INT32( Round(0.34414 * (INT32(1) shl SCALEBITS
)) );
107 upsample
: my_upsample_ptr
;
113 upsample
:= my_upsample_ptr (cinfo
^.upsample
);
115 upsample
^.Cr_r_tab
:= int_CConvertPtr (
116 cinfo
^.mem
^.alloc_small (j_common_ptr (cinfo
), JPOOL_IMAGE
,
117 (MAXJSAMPLE
+1) * SIZEOF(int
)) );
118 upsample
^.Cb_b_tab
:= int_CConvertPtr (
119 cinfo
^.mem
^.alloc_small (j_common_ptr (cinfo
), JPOOL_IMAGE
,
120 (MAXJSAMPLE
+1) * SIZEOF(int
)) );
121 upsample
^.Cr_g_tab
:= INT32_CConvertPtr (
122 cinfo
^.mem
^.alloc_small (j_common_ptr (cinfo
), JPOOL_IMAGE
,
123 (MAXJSAMPLE
+1) * SIZEOF(INT32
)) );
124 upsample
^.Cb_g_tab
:= INT32_CConvertPtr (
125 cinfo
^.mem
^.alloc_small (j_common_ptr (cinfo
), JPOOL_IMAGE
,
126 (MAXJSAMPLE
+1) * SIZEOF(INT32
)) );
129 for i
:= 0 to pred(MAXJSAMPLE
) do
131 { i is the actual input pixel value, in the range 0..MAXJSAMPLE }
132 { The Cb or Cr value we are thinking of is x := i - CENTERJSAMPLE }
133 { Cr=>R value is nearest int to 1.40200 * x }
134 {upsample^.Cr_r_tab^[i] := int(
135 RIGHT_SHIFT(FIX_1_40200 * x + ONE_HALF, SCALEBITS) );}
136 shift_temp
:= FIX_1_40200
* x
+ ONE_HALF
;
137 if shift_temp
< 0 then { SHIFT arithmetic RIGHT }
138 upsample
^.Cr_r_tab
^[i
] := int((shift_temp
shr SCALEBITS
)
139 or ( (not INT32(0)) shl (32-SCALEBITS
)))
141 upsample
^.Cr_r_tab
^[i
] := int(shift_temp
shr SCALEBITS
);
144 { Cb=>B value is nearest int to 1.77200 * x }
145 {upsample^.Cb_b_tab^[i] := int(
146 RIGHT_SHIFT(FIX_1_77200 * x + ONE_HALF, SCALEBITS) );}
147 shift_temp
:= FIX_1_77200
* x
+ ONE_HALF
;
148 if shift_temp
< 0 then { SHIFT arithmetic RIGHT }
149 upsample
^.Cb_b_tab
^[i
] := int((shift_temp
shr SCALEBITS
)
150 or ( (not INT32(0)) shl (32-SCALEBITS
)))
152 upsample
^.Cb_b_tab
^[i
] := int(shift_temp
shr SCALEBITS
);
154 { Cr=>G value is scaled-up -0.71414 * x }
155 upsample
^.Cr_g_tab
^[i
] := (- FIX_0_71414
) * x
;
156 { Cb=>G value is scaled-up -0.34414 * x }
157 { We also add in ONE_HALF so that need not do it in inner loop }
158 upsample
^.Cb_g_tab
^[i
] := (- FIX_0_34414
) * x
+ ONE_HALF
;
164 { Initialize for an upsampling pass. }
167 procedure start_pass_merged_upsample (cinfo
: j_decompress_ptr
);
169 upsample
: my_upsample_ptr
;
171 upsample
:= my_upsample_ptr (cinfo
^.upsample
);
173 { Mark the spare buffer empty }
174 upsample
^.spare_full
:= FALSE;
175 { Initialize total-height counter for detecting bottom of image }
176 upsample
^.rows_to_go
:= cinfo
^.output_height
;
180 { Control routine to do upsampling (and color conversion).
182 The control routine just handles the row buffering considerations. }
185 procedure merged_2v_upsample (cinfo
: j_decompress_ptr
;
186 input_buf
: JSAMPIMAGE
;
187 var in_row_group_ctr
: JDIMENSION
;
188 in_row_groups_avail
: JDIMENSION
;
189 output_buf
: JSAMPARRAY
;
190 var out_row_ctr
: JDIMENSION
;
191 out_rows_avail
: JDIMENSION
);
192 { 2:1 vertical sampling case: may need a spare row. }
194 upsample
: my_upsample_ptr
;
195 work_ptrs
: array[0..2-1] of JSAMPROW
;
196 num_rows
: JDIMENSION
; { number of rows returned to caller }
198 upsample
:= my_upsample_ptr (cinfo
^.upsample
);
200 if (upsample
^.spare_full
) then
202 { If we have a spare row saved from a previous cycle, just return it. }
203 jcopy_sample_rows(JSAMPARRAY(@upsample
^.spare_row
),
205 JSAMPARRAY(@ output_buf
^[out_row_ctr
]),
206 0, 1, upsample
^.out_row_width
);
208 upsample
^.spare_full
:= FALSE;
212 { Figure number of rows to return to caller. }
214 { Not more than the distance to the end of the image. }
215 if (num_rows
> upsample
^.rows_to_go
) then
216 num_rows
:= upsample
^.rows_to_go
;
217 { And not more than what the client can accept: }
218 Dec(out_rows_avail
, {var} out_row_ctr
);
219 if (num_rows
> out_rows_avail
) then
220 num_rows
:= out_rows_avail
;
221 { Create output pointer array for upsampler. }
222 work_ptrs
[0] := output_buf
^[out_row_ctr
];
223 if (num_rows
> 1) then
225 work_ptrs
[1] := output_buf
^[out_row_ctr
+ 1];
229 work_ptrs
[1] := upsample
^.spare_row
;
230 upsample
^.spare_full
:= TRUE;
232 { Now do the upsampling. }
233 upsample
^.upmethod (cinfo
, input_buf
, {var}in_row_group_ctr
,
234 JSAMPARRAY(@work_ptrs
));
238 Inc(out_row_ctr
, num_rows
);
239 Dec(upsample
^.rows_to_go
, num_rows
);
240 { When the buffer is emptied, declare this input row group consumed }
241 if (not upsample
^.spare_full
) then
242 Inc(in_row_group_ctr
);
247 procedure merged_1v_upsample (cinfo
: j_decompress_ptr
;
248 input_buf
: JSAMPIMAGE
;
249 var in_row_group_ctr
: JDIMENSION
;
250 in_row_groups_avail
: JDIMENSION
;
251 output_buf
: JSAMPARRAY
;
252 var out_row_ctr
: JDIMENSION
;
253 out_rows_avail
: JDIMENSION
);
254 { 1:1 vertical sampling case: much easier, never need a spare row. }
256 upsample
: my_upsample_ptr
;
258 upsample
:= my_upsample_ptr (cinfo
^.upsample
);
260 { Just do the upsampling. }
261 upsample
^.upmethod (cinfo
, input_buf
, in_row_group_ctr
,
262 JSAMPARRAY(@ output_buf
^[out_row_ctr
]));
265 Inc(in_row_group_ctr
);
269 { These are the routines invoked by the control routines to do
270 the actual upsampling/conversion. One row group is processed per call.
272 Note: since we may be writing directly into application-supplied buffers,
273 we have to be honest about the output width; we can't assume the buffer
274 has been rounded up to an even width. }
277 { Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. }
280 procedure h2v1_merged_upsample (cinfo
: j_decompress_ptr
;
281 input_buf
: JSAMPIMAGE
;
282 in_row_group_ctr
: JDIMENSION
;
283 output_buf
: JSAMPARRAY
);
285 upsample
: my_upsample_ptr
;
286 {register} y
, cred
, cgreen
, cblue
: int
;
288 {register} outptr
: JSAMPROW
;
289 inptr0
, inptr1
, inptr2
: JSAMPLE_PTR
;
291 { copy these pointers into registers if possible }
292 {register} range_limit
: range_limit_table_ptr
;
293 Crrtab
: int_CConvertPtr
;
294 Cbbtab
: int_CConvertPtr
;
295 Crgtab
: INT32_CConvertPtr
;
296 Cbgtab
: INT32_CConvertPtr
;
300 upsample
:= my_upsample_ptr (cinfo
^.upsample
);
301 range_limit
:= cinfo
^.sample_range_limit
;
302 Crrtab
:= upsample
^.Cr_r_tab
;
303 Cbbtab
:= upsample
^.Cb_b_tab
;
304 Crgtab
:= upsample
^.Cr_g_tab
;
305 Cbgtab
:= upsample
^.Cb_g_tab
;
307 inptr0
:= JSAMPLE_PTR(input_buf
^[0]^[in_row_group_ctr
]);
308 inptr1
:= JSAMPLE_PTR(input_buf
^[1]^[in_row_group_ctr
]);
309 inptr2
:= JSAMPLE_PTR(input_buf
^[2]^[in_row_group_ctr
]);
310 outptr
:= output_buf
^[0];
311 { Loop for each pair of output pixels }
312 for col
:= pred(cinfo
^.output_width
shr 1) downto 0 do
314 { Do the chroma part of the calculation }
315 cb
:= GETJSAMPLE(inptr1
^);
317 cr
:= GETJSAMPLE(inptr2
^);
320 {cgreen := int( RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS) );}
321 shift_temp
:= Cbgtab
^[cb
] + Crgtab
^[cr
];
322 if shift_temp
< 0 then { SHIFT arithmetic RIGHT }
323 cgreen
:= int((shift_temp
shr SCALEBITS
)
324 or ( (not INT32(0)) shl (32-SCALEBITS
)))
326 cgreen
:= int(shift_temp
shr SCALEBITS
);
328 cblue
:= Cbbtab
^[cb
];
329 { Fetch 2 Y values and emit 2 pixels }
330 y
:= GETJSAMPLE(inptr0
^);
332 outptr
^[RGB_RED
] := range_limit
^[y
+ cred
];
333 outptr
^[RGB_GREEN
] := range_limit
^[y
+ cgreen
];
334 outptr
^[RGB_BLUE
] := range_limit
^[y
+ cblue
];
335 Inc(JSAMPLE_PTR(outptr
), RGB_PIXELSIZE
);
336 y
:= GETJSAMPLE(inptr0
^);
338 outptr
^[RGB_RED
] := range_limit
^[y
+ cred
];
339 outptr
^[RGB_GREEN
] := range_limit
^[y
+ cgreen
];
340 outptr
^[RGB_BLUE
] := range_limit
^[y
+ cblue
];
341 Inc(JSAMPLE_PTR(outptr
), RGB_PIXELSIZE
);
343 { If image width is odd, do the last output column separately }
344 if Odd(cinfo
^.output_width
) then
346 cb
:= GETJSAMPLE(inptr1
^);
347 cr
:= GETJSAMPLE(inptr2
^);
349 {cgreen := int ( RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS) );}
350 shift_temp
:= Cbgtab
^[cb
] + Crgtab
^[cr
];
351 if shift_temp
< 0 then { SHIFT arithmetic RIGHT }
352 cgreen
:= int((shift_temp
shr SCALEBITS
)
353 or ( (not INT32(0)) shl (32-SCALEBITS
)))
355 cgreen
:= int(shift_temp
shr SCALEBITS
);
357 cblue
:= Cbbtab
^[cb
];
358 y
:= GETJSAMPLE(inptr0
^);
359 outptr
^[RGB_RED
] := range_limit
^[y
+ cred
];
360 outptr
^[RGB_GREEN
] := range_limit
^[y
+ cgreen
];
361 outptr
^[RGB_BLUE
] := range_limit
^[y
+ cblue
];
366 { Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. }
369 procedure h2v2_merged_upsample (cinfo
: j_decompress_ptr
;
370 input_buf
: JSAMPIMAGE
;
371 in_row_group_ctr
: JDIMENSION
;
372 output_buf
: JSAMPARRAY
);
374 upsample
: my_upsample_ptr
;
375 {register} y
, cred
, cgreen
, cblue
: int
;
377 {register} outptr0
, outptr1
: JSAMPROW
;
378 inptr00
, inptr01
, inptr1
, inptr2
: JSAMPLE_PTR
;
380 { copy these pointers into registers if possible }
381 {register} range_limit
: range_limit_table_ptr
;
382 Crrtab
: int_CConvertPtr
;
383 Cbbtab
: int_CConvertPtr
;
384 Crgtab
: INT32_CConvertPtr
;
385 Cbgtab
: INT32_CConvertPtr
;
389 upsample
:= my_upsample_ptr (cinfo
^.upsample
);
390 range_limit
:= cinfo
^.sample_range_limit
;
391 Crrtab
:= upsample
^.Cr_r_tab
;
392 Cbbtab
:= upsample
^.Cb_b_tab
;
393 Crgtab
:= upsample
^.Cr_g_tab
;
394 Cbgtab
:= upsample
^.Cb_g_tab
;
396 inptr00
:= JSAMPLE_PTR(input_buf
^[0]^[in_row_group_ctr
*2]);
397 inptr01
:= JSAMPLE_PTR(input_buf
^[0]^[in_row_group_ctr
*2 + 1]);
398 inptr1
:= JSAMPLE_PTR(input_buf
^[1]^[in_row_group_ctr
]);
399 inptr2
:= JSAMPLE_PTR(input_buf
^[2]^[in_row_group_ctr
]);
400 outptr0
:= output_buf
^[0];
401 outptr1
:= output_buf
^[1];
402 { Loop for each group of output pixels }
403 for col
:= pred(cinfo
^.output_width
shr 1) downto 0 do
405 { Do the chroma part of the calculation }
406 cb
:= GETJSAMPLE(inptr1
^);
408 cr
:= GETJSAMPLE(inptr2
^);
411 {cgreen := int( RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS) );}
412 shift_temp
:= Cbgtab
^[cb
] + Crgtab
^[cr
];
413 if shift_temp
< 0 then { SHIFT arithmetic RIGHT }
414 cgreen
:= int((shift_temp
shr SCALEBITS
)
415 or ( (not INT32(0)) shl (32-SCALEBITS
)))
417 cgreen
:= int(shift_temp
shr SCALEBITS
);
419 cblue
:= Cbbtab
^[cb
];
420 { Fetch 4 Y values and emit 4 pixels }
421 y
:= GETJSAMPLE(inptr00
^);
423 outptr0
^[RGB_RED
] := range_limit
^[y
+ cred
];
424 outptr0
^[RGB_GREEN
] := range_limit
^[y
+ cgreen
];
425 outptr0
^[RGB_BLUE
] := range_limit
^[y
+ cblue
];
426 Inc(JSAMPLE_PTR(outptr0
), RGB_PIXELSIZE
);
427 y
:= GETJSAMPLE(inptr00
^);
429 outptr0
^[RGB_RED
] := range_limit
^[y
+ cred
];
430 outptr0
^[RGB_GREEN
] := range_limit
^[y
+ cgreen
];
431 outptr0
^[RGB_BLUE
] := range_limit
^[y
+ cblue
];
432 Inc(JSAMPLE_PTR(outptr0
), RGB_PIXELSIZE
);
433 y
:= GETJSAMPLE(inptr01
^);
435 outptr1
^[RGB_RED
] := range_limit
^[y
+ cred
];
436 outptr1
^[RGB_GREEN
] := range_limit
^[y
+ cgreen
];
437 outptr1
^[RGB_BLUE
] := range_limit
^[y
+ cblue
];
438 Inc(JSAMPLE_PTR(outptr1
), RGB_PIXELSIZE
);
439 y
:= GETJSAMPLE(inptr01
^);
441 outptr1
^[RGB_RED
] := range_limit
^[y
+ cred
];
442 outptr1
^[RGB_GREEN
] := range_limit
^[y
+ cgreen
];
443 outptr1
^[RGB_BLUE
] := range_limit
^[y
+ cblue
];
444 Inc(JSAMPLE_PTR(outptr1
), RGB_PIXELSIZE
);
446 { If image width is odd, do the last output column separately }
447 if Odd(cinfo
^.output_width
) then
449 cb
:= GETJSAMPLE(inptr1
^);
450 cr
:= GETJSAMPLE(inptr2
^);
452 {cgreen := int (RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS));}
453 shift_temp
:= Cbgtab
^[cb
] + Crgtab
^[cr
];
454 if shift_temp
< 0 then { SHIFT arithmetic RIGHT }
455 cgreen
:= int((shift_temp
shr SCALEBITS
)
456 or ( (not INT32(0)) shl (32-SCALEBITS
)))
458 cgreen
:= int(shift_temp
shr SCALEBITS
);
460 cblue
:= Cbbtab
^[cb
];
461 y
:= GETJSAMPLE(inptr00
^);
462 outptr0
^[RGB_RED
] := range_limit
^[y
+ cred
];
463 outptr0
^[RGB_GREEN
] := range_limit
^[y
+ cgreen
];
464 outptr0
^[RGB_BLUE
] := range_limit
^[y
+ cblue
];
465 y
:= GETJSAMPLE(inptr01
^);
466 outptr1
^[RGB_RED
] := range_limit
^[y
+ cred
];
467 outptr1
^[RGB_GREEN
] := range_limit
^[y
+ cgreen
];
468 outptr1
^[RGB_BLUE
] := range_limit
^[y
+ cblue
];
473 { Module initialization routine for merged upsampling/color conversion.
475 NB: this is called under the conditions determined by use_merged_upsample()
476 in jdmaster.c. That routine MUST correspond to the actual capabilities
477 of this module; no safety checks are made here. }
481 procedure jinit_merged_upsampler (cinfo
: j_decompress_ptr
);
483 upsample
: my_upsample_ptr
;
485 upsample
:= my_upsample_ptr (
486 cinfo
^.mem
^.alloc_small (j_common_ptr(cinfo
), JPOOL_IMAGE
,
487 SIZEOF(my_upsampler
)) );
488 cinfo
^.upsample
:= jpeg_upsampler_ptr (upsample
);
489 upsample
^.pub
.start_pass
:= start_pass_merged_upsample
;
490 upsample
^.pub
.need_context_rows
:= FALSE;
492 upsample
^.out_row_width
:= cinfo
^.output_width
* JDIMENSION(cinfo
^.out_color_components
);
494 if (cinfo
^.max_v_samp_factor
= 2) then
496 upsample
^.pub
.upsample
:= merged_2v_upsample
;
497 upsample
^.upmethod
:= h2v2_merged_upsample
;
498 { Allocate a spare row buffer }
499 upsample
^.spare_row
:= JSAMPROW(
500 cinfo
^.mem
^.alloc_large ( j_common_ptr(cinfo
), JPOOL_IMAGE
,
501 size_t (upsample
^.out_row_width
* SIZEOF(JSAMPLE
))) );
505 upsample
^.pub
.upsample
:= merged_1v_upsample
;
506 upsample
^.upmethod
:= h2v1_merged_upsample
;
507 { No spare row needed }
508 upsample
^.spare_row
:= NIL;
511 build_ycc_rgb_table(cinfo
);