DEADSOFTWARE

hopefully no more windows
[d2df-editor.git] / src / lib / vampimg / JpegLib / imjdmerge.pas
1 unit imjdmerge;
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
12 R := Y + K1 * Cr
13 G := Y + K2 * Cb + K3 * Cr
14 B := Y + K4 * Cb
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. }
31 interface
33 {$I imjconfig.inc}
35 uses
36 imjmorecfg,
37 imjinclude,
38 imjpeglib,
39 imjutils;
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. }
47 {GLOBAL}
48 procedure jinit_merged_upsampler (cinfo : j_decompress_ptr);
50 implementation
53 { Private subobject }
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;
61 type
62 my_upsample_ptr = ^my_upsampler;
63 my_upsampler = record
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. }
83 spare_row : JSAMPROW;
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 }
88 end; {my_upsampler;}
91 const
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. }
99 {LOCAL}
100 procedure build_ycc_rgb_table (cinfo : j_decompress_ptr);
101 const
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)) );
106 var
107 upsample : my_upsample_ptr;
108 i : int;
109 x : INT32;
110 var
111 shift_temp : INT32;
112 begin
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)) );
128 x := -CENTERJSAMPLE;
129 for i := 0 to pred(MAXJSAMPLE) do
130 begin
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)))
140 else
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)))
151 else
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;
159 Inc(x);
160 end;
161 end;
164 { Initialize for an upsampling pass. }
166 {METHODDEF}
167 procedure start_pass_merged_upsample (cinfo : j_decompress_ptr);
168 var
169 upsample : my_upsample_ptr;
170 begin
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;
177 end;
180 { Control routine to do upsampling (and color conversion).
182 The control routine just handles the row buffering considerations. }
184 {METHODDEF}
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. }
193 var
194 upsample : my_upsample_ptr;
195 work_ptrs : array[0..2-1] of JSAMPROW;
196 num_rows : JDIMENSION; { number of rows returned to caller }
197 begin
198 upsample := my_upsample_ptr (cinfo^.upsample);
200 if (upsample^.spare_full) then
201 begin
202 { If we have a spare row saved from a previous cycle, just return it. }
203 jcopy_sample_rows(JSAMPARRAY(@upsample^.spare_row),
204 0,
205 JSAMPARRAY(@ output_buf^[out_row_ctr]),
206 0, 1, upsample^.out_row_width);
207 num_rows := 1;
208 upsample^.spare_full := FALSE;
209 end
210 else
211 begin
212 { Figure number of rows to return to caller. }
213 num_rows := 2;
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
224 begin
225 work_ptrs[1] := output_buf^[out_row_ctr + 1];
226 end
227 else
228 begin
229 work_ptrs[1] := upsample^.spare_row;
230 upsample^.spare_full := TRUE;
231 end;
232 { Now do the upsampling. }
233 upsample^.upmethod (cinfo, input_buf, {var}in_row_group_ctr,
234 JSAMPARRAY(@work_ptrs));
235 end;
237 { Adjust counts }
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);
243 end;
246 {METHODDEF}
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. }
255 var
256 upsample : my_upsample_ptr;
257 begin
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]));
263 { Adjust counts }
264 Inc(out_row_ctr);
265 Inc(in_row_group_ctr);
266 end;
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. }
279 {METHODDEF}
280 procedure h2v1_merged_upsample (cinfo : j_decompress_ptr;
281 input_buf : JSAMPIMAGE;
282 in_row_group_ctr : JDIMENSION;
283 output_buf : JSAMPARRAY);
284 var
285 upsample : my_upsample_ptr;
286 {register} y, cred, cgreen, cblue : int;
287 cb, cr : int;
288 {register} outptr : JSAMPROW;
289 inptr0, inptr1, inptr2 : JSAMPLE_PTR;
290 col : JDIMENSION;
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;
297 var
298 shift_temp : INT32;
299 begin
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
313 begin
314 { Do the chroma part of the calculation }
315 cb := GETJSAMPLE(inptr1^);
316 Inc(inptr1);
317 cr := GETJSAMPLE(inptr2^);
318 Inc(inptr2);
319 cred := Crrtab^[cr];
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)))
325 else
326 cgreen := int(shift_temp shr SCALEBITS);
328 cblue := Cbbtab^[cb];
329 { Fetch 2 Y values and emit 2 pixels }
330 y := GETJSAMPLE(inptr0^);
331 Inc(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^);
337 Inc(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);
342 end;
343 { If image width is odd, do the last output column separately }
344 if Odd(cinfo^.output_width) then
345 begin
346 cb := GETJSAMPLE(inptr1^);
347 cr := GETJSAMPLE(inptr2^);
348 cred := Crrtab^[cr];
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)))
354 else
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];
362 end;
363 end;
366 { Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. }
368 {METHODDEF}
369 procedure h2v2_merged_upsample (cinfo : j_decompress_ptr;
370 input_buf : JSAMPIMAGE;
371 in_row_group_ctr : JDIMENSION;
372 output_buf : JSAMPARRAY);
373 var
374 upsample : my_upsample_ptr;
375 {register} y, cred, cgreen, cblue : int;
376 cb, cr : int;
377 {register} outptr0, outptr1 : JSAMPROW;
378 inptr00, inptr01, inptr1, inptr2 : JSAMPLE_PTR;
379 col : JDIMENSION;
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;
386 var
387 shift_temp : INT32;
388 begin
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
404 begin
405 { Do the chroma part of the calculation }
406 cb := GETJSAMPLE(inptr1^);
407 Inc(inptr1);
408 cr := GETJSAMPLE(inptr2^);
409 Inc(inptr2);
410 cred := Crrtab^[cr];
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)))
416 else
417 cgreen := int(shift_temp shr SCALEBITS);
419 cblue := Cbbtab^[cb];
420 { Fetch 4 Y values and emit 4 pixels }
421 y := GETJSAMPLE(inptr00^);
422 Inc(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^);
428 Inc(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^);
434 Inc(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^);
440 Inc(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);
445 end;
446 { If image width is odd, do the last output column separately }
447 if Odd(cinfo^.output_width) then
448 begin
449 cb := GETJSAMPLE(inptr1^);
450 cr := GETJSAMPLE(inptr2^);
451 cred := Crrtab^[cr];
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)))
457 else
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];
469 end;
470 end;
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. }
480 {GLOBAL}
481 procedure jinit_merged_upsampler (cinfo : j_decompress_ptr);
482 var
483 upsample : my_upsample_ptr;
484 begin
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
495 begin
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))) );
502 end
503 else
504 begin
505 upsample^.pub.upsample := merged_1v_upsample;
506 upsample^.upmethod := h2v1_merged_upsample;
507 { No spare row needed }
508 upsample^.spare_row := NIL;
509 end;
511 build_ycc_rgb_table(cinfo);
512 end;
514 end.