jcdctmgr.pas

来自「DELPHI版的JPEG文件解码源程序」· PAS 代码 · 共 514 行 · 第 1/2 页

PAS
514
字号

    { 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.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?