⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transupp.pas

📁 DELPHI版的JPEG文件解码源程序
💻 PAS
📖 第 1 页 / 共 4 页
字号:
Unit transupp;

{* transupp.c
 * transupp.h

 Copyright (C) 1997, 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 image transformation routines and other utility code
 used by the jpegtran sample application.  These are NOT part of the core
 JPEG library.  But we keep these routines separate from jpegtran.c to
 ease the task of maintaining jpegtran-like programs that have other user
 interfaces.

 NOTE: all the routines declared here have very specific requirements
 about when they are to be executed during the reading and writing of the
 source and destination files.  See the comments in transupp.c, or see
 jpegtran.c for an example of correct usage. }

interface


{$I jconfig.inc}

uses
  jmorecfg,
  jinclude,
  jpeglib;


{ Short forms of external names for systems with brain-damaged linkers. }

{$ifdef NEED_SHORT_EXTERNAL_NAMES}
  jtransform_request_workspace		jTrRequest
  jtransform_adjust_parameters		jTrAdjust
  jtransform_execute_transformation	jTrExec
  jcopy_markers_setup			jCMrkSetup
  jcopy_markers_execute			jCMrkExec
{$endif} { NEED_SHORT_EXTERNAL_NAMES }


{ Codes for supported types of image transformations. }

type
  JXFORM_CODE = (
	JXFORM_NONE,		{ no transformation }
{$ifdef CROP_SUPPORTED}
        JXFORM_CUT,             { cut out part of the image }
{$endif}
	JXFORM_FLIP_H,		{ horizontal flip }
	JXFORM_FLIP_V,		{ vertical flip }
	JXFORM_TRANSPOSE,	{ transpose across UL-to-LR axis }
	JXFORM_TRANSVERSE,	{ transpose across UR-to-LL axis }
	JXFORM_ROT_90,		{ 90-degree clockwise rotation }
	JXFORM_ROT_180,		{ 180-degree rotation }
	JXFORM_ROT_270		{ 270-degree clockwise (or 90 ccw) }
                );

{
  Although rotating and flipping data expressed as DCT coefficients is not
  hard, there is an asymmetry in the JPEG format specification for images
  whose dimensions aren't multiples of the iMCU size.  The right and bottom
  image edges are padded out to the next iMCU boundary with junk data; but
  no padding is possible at the top and left edges.  If we were to flip
  the whole image including the pad data, then pad garbage would become
  visible at the top and/or left, and real pixels would disappear into the
  pad margins --- perhaps permanently, since encoders & decoders may not
  bother to preserve DCT blocks that appear to be completely outside the
  nominal image area.  So, we have to exclude any partial iMCUs from the
  basic transformation.

  Transpose is the only transformation that can handle partial iMCUs at the
  right and bottom edges completely cleanly.  flip_h can flip partial iMCUs
  at the bottom, but leaves any partial iMCUs at the right edge untouched.
  Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
  The other transforms are defined as combinations of these basic transforms
  and process edge blocks in a way that preserves the equivalence.

  The "trim" option causes untransformable partial iMCUs to be dropped;
  this is not strictly lossless, but it usually gives the best-looking
  result for odd-size images.  Note that when this option is active,
  the expected mathematical equivalences between the transforms may not hold.
  (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
  followed by -rot 180 -trim trims both edges.)

  We also offer a "force to grayscale" option, which simply discards the
  chrominance channels of a YCbCr image.  This is lossless in the sense that
  the luminance channel is preserved exactly.  It's not the same kind of
  thing as the rotate/flip transformations, but it's convenient to handle it
  as part of this package, mainly because the transformation routines have to
  be aware of the option to know how many components to work on.
 }

type
 jpeg_transform_info = record
   { Options: set by caller }
   transform : JXFORM_CODE;	{ image transform operator }
   trim : boolean;		{ if TRUE, trim partial MCUs as needed }
   force_grayscale : boolean;	{ if TRUE, convert color image to grayscale }
{$ifdef CROP_SUPPORTED}
   xoffs, yoffs, newwidth, newheight : JDIMENSION;
{$endif}
   { Internal workspace: caller should not touch these }
   num_components : int;	{ # of components in workspace }
   workspace_coef_arrays : jvirt_barray_tbl_ptr; { workspace for transformations }
 end;


{$ifdef TRANSFORMS_SUPPORTED}

{ Request any required workspace }
procedure jtransform_request_workspace(srcinfo : j_decompress_ptr;
                                       var info : jpeg_transform_info);
{ Adjust output image parameters }
function jtransform_adjust_parameters(
             srcinfo : j_decompress_ptr;
             dstinfo : j_compress_ptr;
	     src_coef_arrays : jvirt_barray_tbl_ptr;
	     var info : jpeg_transform_info) : jvirt_barray_tbl_ptr;

{ Execute the actual transformation, if any }
procedure jtransform_execute_transformation(
	     srcinfo : j_decompress_ptr;
             dstinfo : j_compress_ptr;
	     src_coef_arrays : jvirt_barray_tbl_ptr;
	     var info : jpeg_transform_info);

{$endif} { TRANSFORMS_SUPPORTED }

{ Support for copying optional markers from source to destination file. }

type
 JCOPY_OPTION = (
	JCOPYOPT_NONE,		{ copy no optional markers }
	JCOPYOPT_COMMENTS,	{ copy only comment (COM) markers }
	JCOPYOPT_ALL		{ copy all optional markers }
                );

const
  JCOPYOPT_DEFAULT = JCOPYOPT_COMMENTS;	{ recommended default }

{ Setup decompression object to save desired markers in memory }
procedure jcopy_markers_setup(srcinfo : j_decompress_ptr;
                              option : JCOPY_OPTION);
{ Copy markers saved in the given source object to the destination object }
procedure jcopy_markers_execute(srcinfo : j_decompress_ptr;
                                dstinfo : j_compress_ptr;
	                        option : JCOPY_OPTION);

implementation

{ Although this file really shouldn't have access to the library internals,
  it's helpful to let it call jround_up() and jcopy_block_row(). }
uses
  jutils,
  jdeferr,
  jerror,
  {$ifdef SAVE_MARKERS_SUPPORTED}
  jdmarker,
  {$endif}
  jcapimin,
  jcparam;  { set color space }

{$ifdef TRANSFORMS_SUPPORTED}

{ Lossless image transformation routines.  These routines work on DCT
  coefficient arrays and thus do not require any lossy decompression
  or recompression of the image.
  Thanks to Guido Vollbeding for the initial design and code of this feature.

  Horizontal flipping is done in-place, using a single top-to-bottom
  pass through the virtual source array.  It will thus be much the
  fastest option for images larger than main memory.

  The other routines require a set of destination virtual arrays, so they
  need twice as much memory as jpegtran normally does.  The destination
  arrays are always written in normal scan order (top to bottom) because
  the virtual array manager expects this.  The source arrays will be scanned
  in the corresponding order, which means multiple passes through the source
  arrays for most of the transforms.  That could result in much thrashing
  if the image is larger than main memory.

  Some notes about the operating environment of the individual transform
  routines:
  1. Both the source and destination virtual arrays are allocated from the
     source JPEG object, and therefore should be manipulated by calling the
     source's memory manager.
  2. The destination's component count should be used.  It may be smaller
     than the source's when forcing to grayscale.
  3. Likewise the destination's sampling factors should be used.  When
     forcing to grayscale the destination's sampling factors will be all 1,
     and we may as well take that as the effective iMCU size.
  4. When "trim" is in effect, the destination's dimensions will be the
     trimmed values but the source's will be untrimmed.
  5. All the routines assume that the source and destination buffers are
     padded out to a full iMCU boundary.  This is true, although for the
     source buffer it is an undocumented property of jdcoefct.c.
  Notes 2,3,4 boil down to this: generally we should use the destination's
  dimensions and ignore the source's. }

{LOCAL}
procedure do_flip_h (srcinfo : j_decompress_ptr;
                     dstinfo : j_compress_ptr;
	             src_coef_arrays : jvirt_barray_tbl_ptr);
{ Horizontal flip; done in-place, so no separate dest array is required }
var
  MCU_cols, comp_width, blk_x, blk_y : JDIMENSION;
  ci, k, offset_y : int;
  buffer : JBLOCKARRAY;
  ptr1, ptr2 : JCOEF_PTR;
  temp1, temp2 : JCOEF;
  compptr : jpeg_component_info_ptr;
begin
  { Horizontal mirroring of DCT blocks is accomplished by swapping
    pairs of blocks in-place.  Within a DCT block, we perform horizontal
    mirroring by changing the signs of odd-numbered columns.
    Partial iMCUs at the right edge are left untouched. }

  MCU_cols := dstinfo^.image_width div (dstinfo^.max_h_samp_factor * DCTSIZE);

  for ci := 0 to dstinfo^.num_components-1 do
  begin
    compptr := jpeg_component_info_ptr(dstinfo^.comp_info);
    Inc(compptr, ci);
    comp_width := MCU_cols * compptr^.h_samp_factor;
    blk_y := 0;
    while (blk_y < compptr^.height_in_blocks) do
    begin
      buffer := srcinfo^.mem^.access_virt_barray
	(j_common_ptr(srcinfo), src_coef_arrays^[ci], blk_y,
	 JDIMENSION (compptr^.v_samp_factor), TRUE);
      for offset_y := 0 to compptr^.v_samp_factor-1 do
      begin
        blk_x := 0;
	while (blk_x * 2 < comp_width) do
        begin
	  ptr1 := JCOEF_PTR(@(buffer^[offset_y]^[blk_x]));
	  ptr2 := JCOEF_PTR(@(buffer^[offset_y]^[comp_width - blk_x - 1]));
	  { this unrolled loop doesn't need to know which row it's on... }
          k := 0;
	  while (k < DCTSIZE2) do
          begin
	    temp1 := ptr1^;	{ swap even column }
	    temp2 := ptr2^;
	    ptr1^ := temp2;
            Inc(ptr1);
	    ptr2^ := temp1;
            Inc(ptr2);
	    temp1 := ptr1^;	{ swap odd column with sign change }
	    temp2 := ptr2^;
	    ptr1^ := -temp2;
            Inc(ptr1);
	    ptr2^ := -temp1;
            Inc(ptr2);
            Inc(k, 2);
	  end;
          Inc(blk_x);
	end;
      end;
      Inc(blk_y, compptr^.v_samp_factor);
    end; { while }
  end; { for ci }
end; { do_flip_h }


{LOCAL}
procedure do_flip_v (srcinfo : j_decompress_ptr;
                     dstinfo : j_compress_ptr;
	             src_coef_arrays : jvirt_barray_tbl_ptr;
	             dst_coef_arrays : jvirt_barray_tbl_ptr);
{ Vertical flip }
var
  MCU_rows, comp_height, dst_blk_x, dst_blk_y : JDIMENSION;
  ci, i, j, offset_y : int;
  src_buffer, dst_buffer : JBLOCKARRAY;
  src_row_ptr, dst_row_ptr : JBLOCKROW;
  src_ptr, dst_ptr : JCOEF_PTR;
  compptr : jpeg_component_info_ptr;
begin
  { We output into a separate array because we can't touch different
    rows of the source virtual array simultaneously.  Otherwise, this
    is a pretty straightforward analog of horizontal flip.
    Within a DCT block, vertical mirroring is done by changing the signs
    of odd-numbered rows.
    Partial iMCUs at the bottom edge are copied verbatim. }

  MCU_rows := dstinfo^.image_height div (dstinfo^.max_v_samp_factor * DCTSIZE);

  for ci := 0 to dstinfo^.num_components-1 do
  begin
    compptr := jpeg_component_info_ptr(dstinfo^.comp_info);
    Inc(compptr, ci);
    comp_height := MCU_rows * compptr^.v_samp_factor;
    dst_blk_y := 0;
    while (dst_blk_y < compptr^.height_in_blocks) do
    begin
      dst_buffer := srcinfo^.mem^.access_virt_barray
           (j_common_ptr(srcinfo), dst_coef_arrays^[ci], dst_blk_y,
            JDIMENSION(compptr^.v_samp_factor), TRUE);
      if (dst_blk_y < comp_height) then
      begin
        { Row is within the mirrorable area. }
        src_buffer := srcinfo^.mem^.access_virt_barray
           (j_common_ptr(srcinfo), src_coef_arrays^[ci],
           comp_height - dst_blk_y - JDIMENSION(compptr^.v_samp_factor),
           JDIMENSION (compptr^.v_samp_factor), FALSE);
      end
      else
      begin
        { Bottom-edge blocks will be copied verbatim. }
        src_buffer := srcinfo^.mem^.access_virt_barray
           (j_common_ptr(srcinfo), src_coef_arrays^[ci], dst_blk_y,
            JDIMENSION (compptr^.v_samp_factor), FALSE);
      end;
      for offset_y := 0 to compptr^.v_samp_factor-1 do
      begin
        if (dst_blk_y < comp_height) then
        begin
          { Row is within the mirrorable area. }
          dst_row_ptr := dst_buffer^[offset_y];
          src_row_ptr := src_buffer^[compptr^.v_samp_factor - offset_y - 1];
          for dst_blk_x := 0 to compptr^.width_in_blocks-1 do
          begin
            dst_ptr := JCOEF_PTR(@(dst_row_ptr^[dst_blk_x]));
            src_ptr := JCOEF_PTR(@(src_row_ptr^[dst_blk_x]));
            i := 0;
            while (i < DCTSIZE) do
            begin
              { copy even row }
              for j := 0 to DCTSIZE-1 do
              begin
                dst_ptr^ := src_ptr^;
                Inc(dst_ptr);
                Inc(src_ptr);
              end;
              { copy odd row with sign change }
              for j := 0 to DCTSIZE-1 do
              begin
                dst_ptr^ := - (src_ptr^);
                Inc(dst_ptr);
                Inc(src_ptr);
              end;
              Inc(i, 2);
            end;
          end;
        end
        else
        begin
          { Just copy row verbatim. }
          jcopy_block_row(src_buffer^[offset_y], dst_buffer^[offset_y],
                          compptr^.width_in_blocks);
        end;
      end;
      Inc(dst_blk_y, compptr^.v_samp_factor);
    end; { while }
  end; { for ci }

⌨️ 快捷键说明

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