123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- Unit JcDCTmgr;
- { Original : jcdctmgr.c ; Copyright (C) 1994-1996, Thomas G. Lane. }
- { This file is part of the Independent JPEG Group's software.
- For conditions of distribution and use, see the accompanying README file.
- This file contains the forward-DCT management logic.
- This code selects a particular DCT implementation to be used,
- and it performs related housekeeping chores including coefficient
- quantization. }
- interface
- {$N+}
- {$I jconfig.inc}
- uses
- jmorecfg,
- jinclude,
- jdeferr,
- jerror,
- jpeglib,
- jdct, { Private declarations for DCT subsystem }
- jfdctint, jfdctfst, jfdctflt;
- { Initialize FDCT manager. }
- {GLOBAL}
- procedure jinit_forward_dct (cinfo : j_compress_ptr);
- implementation
- { Private subobject for this module }
- type
- my_fdct_ptr = ^my_fdct_controller;
- my_fdct_controller = record
- pub : jpeg_forward_dct; { public fields }
- { Pointer to the DCT routine actually in use }
- do_dct : forward_DCT_method_ptr;
- { The actual post-DCT divisors --- not identical to the quant table
- entries, because of scaling (especially for an unnormalized DCT).
- Each table is given in normal array order. }
- divisors : array[0..NUM_QUANT_TBLS-1] of DCTELEM_FIELD_PTR;
- {$ifdef DCT_FLOAT_SUPPORTED}
- { Same as above for the floating-point case. }
- do_float_dct : float_DCT_method_ptr;
- float_divisors : array[0..NUM_QUANT_TBLS-1] of FAST_FLOAT_FIELD_PTR;
- {$endif}
- end;
- { Initialize for a processing pass.
- Verify that all referenced Q-tables are present, and set up
- the divisor table for each one.
- In the current implementation, DCT of all components is done during
- the first pass, even if only some components will be output in the
- first scan. Hence all components should be examined here. }
- {METHODDEF}
- procedure start_pass_fdctmgr (cinfo : j_compress_ptr); far;
- var
- fdct : my_fdct_ptr;
- ci, qtblno, i : int;
- compptr : jpeg_component_info_ptr;
- qtbl : JQUANT_TBL_PTR;
- dtbl : DCTELEM_FIELD_PTR;
- {$ifdef DCT_IFAST_SUPPORTED}
- const
- CONST_BITS = 14;
- aanscales : array[0..DCTSIZE2-1] of INT16 =
- ({ precomputed values scaled up by 14 bits }
- 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
- 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
- 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
- 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
- 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
- 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
- 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
- 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247);
- {SHIFT_TEMPS}
- { Descale and correctly round an INT32 value that's scaled by N bits.
- We assume RIGHT_SHIFT rounds towards minus infinity, so adding
- the fudge factor is correct for either sign of X. }
- function DESCALE(x : INT32; n : int) : INT32;
- var
- shift_temp : INT32;
- begin
- shift_temp := x + (INT32(1) shl (n-1));
- {$ifdef RIGHT_SHIFT_IS_UNSIGNED}
- if shift_temp < 0 then
- Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n))
- else
- {$endif}
- Descale := (shift_temp shr n);
- end;
- {$endif}
- {$ifdef DCT_FLOAT_SUPPORTED}
- var
- fdtbl : FAST_FLOAT_FIELD_PTR;
- row, col : int;
- const
- aanscalefactor : array[0..DCTSIZE-1] of double =
- (1.0, 1.387039845, 1.306562965, 1.175875602,
- 1.0, 0.785694958, 0.541196100, 0.275899379);
- {$endif}
- begin
- fdct := my_fdct_ptr (cinfo^.fdct);
- compptr := jpeg_component_info_ptr(cinfo^.comp_info);
- for ci := 0 to pred(cinfo^.num_components) do
- begin
- qtblno := compptr^.quant_tbl_no;
- { Make sure specified quantization table is present }
- if (qtblno < 0) or (qtblno >= NUM_QUANT_TBLS) or
- (cinfo^.quant_tbl_ptrs[qtblno] = NIL) then
- ERREXIT1(j_common_ptr(cinfo), JERR_NO_QUANT_TABLE, qtblno);
- qtbl := cinfo^.quant_tbl_ptrs[qtblno];
- { Compute divisors for this quant table }
- { We may do this more than once for same table, but it's not a big deal }
- case (cinfo^.dct_method) of
- {$ifdef DCT_ISLOW_SUPPORTED}
- JDCT_ISLOW:
- begin
- { For LL&M IDCT method, divisors are equal to raw quantization
- coefficients multiplied by 8 (to counteract scaling). }
- if (fdct^.divisors[qtblno] = NIL) then
- begin
- fdct^.divisors[qtblno] := DCTELEM_FIELD_PTR(
- cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
- DCTSIZE2 * SIZEOF(DCTELEM)) );
- end;
- dtbl := fdct^.divisors[qtblno];
- for i := 0 to pred(DCTSIZE2) do
- begin
- dtbl^[i] := (DCTELEM(qtbl^.quantval[i])) shl 3;
- end;
- end;
- {$endif}
- {$ifdef DCT_IFAST_SUPPORTED}
- JDCT_IFAST:
- begin
- { For AA&N IDCT method, divisors are equal to quantization
- coefficients scaled by scalefactor[row]*scalefactor[col], where
- scalefactor[0] := 1
- scalefactor[k] := cos(k*PI/16) * sqrt(2) for k=1..7
- We apply a further scale factor of 8. }
- if (fdct^.divisors[qtblno] = NIL) then
- begin
- fdct^.divisors[qtblno] := DCTELEM_FIELD_PTR(
- cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
- DCTSIZE2 * SIZEOF(DCTELEM)) );
- end;
- dtbl := fdct^.divisors[qtblno];
- for i := 0 to pred(DCTSIZE2) do
- begin
- dtbl^[i] := DCTELEM(
- {MULTIPLY16V16}
- DESCALE( INT32(qtbl^.quantval[i]) * INT32 (aanscales[i]),
- CONST_BITS-3) );
- end;
- end;
- {$endif}
- {$ifdef DCT_FLOAT_SUPPORTED}
- JDCT_FLOAT:
- begin
- { For float AA&N IDCT method, divisors are equal to quantization
- coefficients scaled by scalefactor[row]*scalefactor[col], where
- scalefactor[0] := 1
- scalefactor[k] := cos(k*PI/16) * sqrt(2) for k=1..7
- We apply a further scale factor of 8.
- What's actually stored is 1/divisor so that the inner loop can
- use a multiplication rather than a division. }
- if (fdct^.float_divisors[qtblno] = NIL) then
- begin
- fdct^.float_divisors[qtblno] := FAST_FLOAT_FIELD_PTR(
- cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
- DCTSIZE2 * SIZEOF(FAST_FLOAT)) );
- end;
- fdtbl := fdct^.float_divisors[qtblno];
- i := 0;
- for row := 0 to pred(DCTSIZE) do
- begin
- for col := 0 to pred(DCTSIZE) do
- begin
- fdtbl^[i] := {FAST_FLOAT}
- (1.0 / (( {double}(qtbl^.quantval[i]) *
- aanscalefactor[row] * aanscalefactor[col] * 8.0)));
- Inc(i);
- end;
- end;
- end;
- {$endif}
- else
- ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
- end;
- Inc(compptr);
- end;
- end;
- { Perform forward DCT on one or more blocks of a component.
- The input samples are taken from the sample_data[] array starting at
- position start_row/start_col, and moving to the right for any additional
- blocks. The quantized coefficients are returned in coef_blocks[]. }
- {METHODDEF}
- procedure forward_DCT (cinfo : j_compress_ptr;
- compptr : jpeg_component_info_ptr;
- sample_data : JSAMPARRAY;
- coef_blocks : JBLOCKROW;
- start_row : JDIMENSION;
- start_col : JDIMENSION;
- num_blocks : JDIMENSION); far;
- { This version is used for integer DCT implementations. }
- var
- { This routine is heavily used, so it's worth coding it tightly. }
- fdct : my_fdct_ptr;
- do_dct : forward_DCT_method_ptr;
- divisors : DCTELEM_FIELD_PTR;
- workspace : array[0..DCTSIZE2-1] of DCTELEM; { work area for FDCT subroutine }
- bi : JDIMENSION;
- var
- {register} workspaceptr : DCTELEMPTR;
- {register} elemptr : JSAMPLE_PTR;
- {register} elemr : int;
- {$ifndef DCTSIZE_IS_8}
- var
- {register} elemc : int;
- {$endif}
- var
- {register} temp, qval : DCTELEM;
- {register} i : int;
- {register} output_ptr : JCOEFPTR;
- begin
- fdct := my_fdct_ptr (cinfo^.fdct);
- do_dct := fdct^.do_dct;
- divisors := fdct^.divisors[compptr^.quant_tbl_no];
- Inc(JSAMPROW_PTR(sample_data), start_row); { fold in the vertical offset once }
- for bi := 0 to pred(num_blocks) do
- begin
- { Load data into workspace, applying unsigned->signed conversion }
- workspaceptr := @workspace[0];
- for elemr := 0 to pred(DCTSIZE) do
- begin
- elemptr := @sample_data^[elemr]^[start_col];
- {$ifdef DCTSIZE_IS_8} { unroll the inner loop }
- workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE;
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE;
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE;
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE;
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE;
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE;
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE;
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE;
- Inc(workspaceptr);
- {Inc(elemptr); - Value never used }
- {$else}
- for elemc := pred(DCTSIZE) downto 0 do
- begin
- workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE;
- Inc(workspaceptr);
- Inc(elemptr);
- end;
- {$endif}
- end;
- { Perform the DCT }
- do_dct (workspace);
- { Quantize/descale the coefficients, and store into coef_blocks[] }
- output_ptr := JCOEFPTR(@coef_blocks^[bi]);
- for i := 0 to pred(DCTSIZE2) do
- begin
- qval := divisors^[i];
- temp := workspace[i];
- { Divide the coefficient value by qval, ensuring proper rounding.
- Since C does not specify the direction of rounding for negative
- quotients, we have to force the dividend positive for portability.
- In most files, at least half of the output values will be zero
- (at default quantization settings, more like three-quarters...)
- so we should ensure that this case is fast. On many machines,
- a comparison is enough cheaper than a divide to make a special test
- a win. Since both inputs will be nonnegative, we need only test
- for a < b to discover whether a/b is 0.
- If your machine's division is fast enough, define FAST_DIVIDE. }
- if (temp < 0) then
- begin
- temp := -temp;
- Inc(temp, qval shr 1); { for rounding }
- {DIVIDE_BY(temp, qval);}
- {$ifdef FAST_DIVIDE}
- temp := temp div qval;
- {$else}
- if (temp >= qval) then
- temp := temp div qval
- else
- temp := 0;
- {$endif}
- temp := -temp;
- end
- else
- begin
- Inc(temp, qval shr 1); { for rounding }
- {DIVIDE_BY(temp, qval);}
- {$ifdef FAST_DIVIDE}
- temp := temp div qval;
- {$else}
- if (temp >= qval) then
- temp := temp div qval
- else
- temp := 0;
- {$endif}
- end;
- output_ptr^[i] := JCOEF (temp);
- end;
- Inc(start_col, DCTSIZE);
- end;
- end;
- {$ifdef DCT_FLOAT_SUPPORTED}
- {METHODDEF}
- procedure forward_DCT_float (cinfo : j_compress_ptr;
- compptr : jpeg_component_info_ptr;
- sample_data : JSAMPARRAY;
- coef_blocks : JBLOCKROW;
- start_row : JDIMENSION;
- start_col : JDIMENSION;
- num_blocks : JDIMENSION); far;
- { This version is used for floating-point DCT implementations. }
- var
- { This routine is heavily used, so it's worth coding it tightly. }
- fdct : my_fdct_ptr;
- do_dct : float_DCT_method_ptr;
- divisors : FAST_FLOAT_FIELD_PTR;
- workspace : array[0..DCTSIZE2-1] of FAST_FLOAT; { work area for FDCT subroutine }
- bi : JDIMENSION;
- var
- {register} workspaceptr : FAST_FLOAT_PTR;
- {register} elemptr : JSAMPLE_PTR;
- {register} elemr : int;
- {$ifndef DCTSIZE_IS_8}
- var
- {register} elemc : int;
- {$endif}
- var
- {register} temp : FAST_FLOAT;
- {register} i : int;
- {register} output_ptr : JCOEFPTR;
- begin
- fdct := my_fdct_ptr (cinfo^.fdct);
- do_dct := fdct^.do_float_dct;
- divisors := fdct^.float_divisors[compptr^.quant_tbl_no];
- Inc(JSAMPROW_PTR(sample_data), start_row); { fold in the vertical offset once }
- for bi := 0 to pred(num_blocks) do
- begin
- { Load data into workspace, applying unsigned->signed conversion }
- workspaceptr := @workspace[0];
- for elemr := 0 to pred(DCTSIZE) do
- begin
- elemptr := @(sample_data^[elemr]^[start_col]);
- {$ifdef DCTSIZE_IS_8} { unroll the inner loop }
- workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE);
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE);
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE);
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE);
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE);
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE);
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE);
- Inc(workspaceptr);
- Inc(elemptr);
- workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE);
- Inc(workspaceptr);
- {Inc(elemptr); - value never used }
- {$else}
- for elemc := pred(DCTSIZE) downto 0 do
- begin
- workspaceptr^ := {FAST_FLOAT}(
- (GETJSAMPLE(elemptr^) - CENTERJSAMPLE) );
- Inc(workspaceptr);
- Inc(elemptr);
- end;
- {$endif}
- end;
- { Perform the DCT }
- do_dct (workspace);
- { Quantize/descale the coefficients, and store into coef_blocks[] }
- output_ptr := JCOEFPTR(@(coef_blocks^[bi]));
- for i := 0 to pred(DCTSIZE2) do
- begin
- { Apply the quantization and scaling factor }
- temp := workspace[i] * divisors^[i];
- { Round to nearest integer.
- Since C does not specify the direction of rounding for negative
- quotients, we have to force the dividend positive for portability.
- The maximum coefficient size is +-16K (for 12-bit data), so this
- code should work for either 16-bit or 32-bit ints. }
- output_ptr^[i] := JCOEF ( int(Trunc (temp + {FAST_FLOAT}(16384.5))) - 16384);
- end;
- Inc(start_col, DCTSIZE);
- end;
- end;
- {$endif} { DCT_FLOAT_SUPPORTED }
- { Initialize FDCT manager. }
- {GLOBAL}
- procedure jinit_forward_dct (cinfo : j_compress_ptr);
- var
- fdct : my_fdct_ptr;
- i : int;
- begin
- fdct := my_fdct_ptr(
- cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE,
- SIZEOF(my_fdct_controller)) );
- cinfo^.fdct := jpeg_forward_dct_ptr (fdct);
- fdct^.pub.start_pass := start_pass_fdctmgr;
- case (cinfo^.dct_method) of
- {$ifdef DCT_ISLOW_SUPPORTED}
- JDCT_ISLOW:
- begin
- fdct^.pub.forward_DCT := forward_DCT;
- fdct^.do_dct := jpeg_fdct_islow;
- end;
- {$endif}
- {$ifdef DCT_IFAST_SUPPORTED}
- JDCT_IFAST:
- begin
- fdct^.pub.forward_DCT := forward_DCT;
- fdct^.do_dct := jpeg_fdct_ifast;
- end;
- {$endif}
- {$ifdef DCT_FLOAT_SUPPORTED}
- JDCT_FLOAT:
- begin
- fdct^.pub.forward_DCT := forward_DCT_float;
- fdct^.do_float_dct := jpeg_fdct_float;
- end;
- {$endif}
- else
- ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED);
- end;
- { Mark divisor tables unallocated }
- for i := 0 to pred(NUM_QUANT_TBLS) do
- begin
- fdct^.divisors[i] := NIL;
- {$ifdef DCT_FLOAT_SUPPORTED}
- fdct^.float_divisors[i] := NIL;
- {$endif}
- end;
- end;
- end.
|