• FlipReverseRotate Lab Report


    http://www.efg2.com/Lab/ImageProcessing/FlipReverseRotate.htm

    The purpose of this program, FlipReverseRotate.EXE, is to demonstrate how to

    flip (top-to-bottom) and/or
    reverse (left-to-right)

    a bitmap in memory and display the results on the screen.
    Three methods to flip/reverse are compared:

    Scanline, CopyRect, StretchBlt.

    In addition, a bitmap can be rotated any multiple of 90 degrees,
    namely 0, 90, 180, or 270 degrees counterclockwise, but only with the Scanline method.

    View Code
    // The FlipReverseRotate Library provides three functions to flip and/or
    // reverse a bitmap.  You can choose which approach you'd like to use from the
    // three methods to flip or reverse a bitmap:  ScanLine, CopyRect, StretchBlt.
    //
    // A "Flip" operation takes the top of an image to the bottom and the bottom of
    // the image to the top.  It is a reflection along a horizontal line in the
    // middle of an image.
    //
    // A "Reverse" operation takes the left of an image to the right and the right
    // of the image to the left.  It is a reflection along a vertical line in the
    // middle of an image.
    //
    // Any Flip/Reverse operation is commutative, i.e., the flip and reverse can
    // be performed in any order to get the same result.  A flip followed by a
    // reverse is the same as a reverse followed by a flip.
    //
    // A "rotate" operation spins an image 0, 90, 180 or 270 degrees around an
    // axis in the center of the image.
    //
    // A flip/reverse operation along with a rotation is not commutative in general.
    // A flip followed by a rotation will not always result in the same image as a
    // rotation followed by a flip.  The rotation here ALWAYS follows any flip and/or
    // reversal.
    //
    // The examples here are intended for use with bitmaps that have 24 bits/pixel.
    // Palettes may be lost on 256-color bitmaps.
    //
    // Copyright (C) 1998, Earl F. Glynn.  All Rights Reserved.
    // May be used freely for non-comercial use.
    
    unit FlipReverseRotateLibrary;
    
    interface
    
    uses
      Dialogs,
      Windows, // TRGBTriple (put here to avoid TBitmap conflict in Implementation)
      Graphics; // TBitmap
    
    // Flip/Reverse functions by Method
    function FlipReverseScanLine( const Flip, Reverse : BOOLEAN;
      const Bitmap : TBitmap ) : TBitmap;
    
    function FlipReverseCopyRect( const Flip, Reverse : BOOLEAN;
      const Bitmap : TBitmap ) : TBitmap;
    
    function FlipReverseStretchBlt( const Flip, Reverse : BOOLEAN;
      const Bitmap : TBitmap ) : TBitmap;
    
    // The Rotation function is only for the Scanline Method.
    // Note:  Windows NT supports a "plgblt" API call that can be used to rotate
    // images.
    function RotateScanline90( const angle : INTEGER; const Bitmap : TBitmap )
      : TBitmap;
    
    implementation
    
    uses
      Classes, // Rect
      SysUtils; // Exception
    
    const
      MaxPixelCount = 65536; // or some other arbitrarily large value
    
    type
      EBitmapError = class( Exception );
      TRGBArray = array [ 0 .. MaxPixelCount - 1 ] of TRGBTriple;
      pRGBArray = ^TRGBArray;
    
      /// ///////////////////////////////////////////////////////////////////////////
    
    function FlipReverseScanLine( const Flip, Reverse : BOOLEAN;
      const Bitmap : TBitmap ) : TBitmap;
    var
      i : INTEGER;
      j : INTEGER;
      RowIn : pRGBArray;
      RowOut : pRGBArray;
    begin
      if Bitmap.PixelFormat <> pf24bit then
        raise EBitmapError.Create( 'Can Flip/Reverse only 24-bit bitmap' );
    
      RESULT := TBitmap.Create;
      RESULT.Width := Bitmap.Width;
      RESULT.Height := Bitmap.Height;
      RESULT.PixelFormat := Bitmap.PixelFormat;
    
      for j := 0 to Bitmap.Height - 1 do
      begin
        RowIn := Bitmap.Scanline[ j ];
        if Flip then
          RowOut := RESULT.Scanline[ Bitmap.Height - 1 - j ]
        else
          RowOut := RESULT.Scanline[ j ];
    
        // Optimization technique:  Use two FOR loops so IF is outside of inner loop
        if Reverse then
        begin
          for i := 0 to Bitmap.Width - 1 do
            RowOut[ i ] := RowIn[ Bitmap.Width - 1 - i ]
        end
        else
        begin
          for i := 0 to Bitmap.Width - 1 do
            RowOut[ i ] := RowIn[ i ]
        end
    
      end
    end { FlipReverseScanLine };
    
    /// ///////////////////////////////////////////////////////////////////////////
    
    // This function implements a suggestion by David Ullrich in a July 25, 1997
    // post to comp.lang.pascal.delphi.misc.
    //
    // The Graphics.PAS unit shows that CopyRect calls the Windows StretchBlt API
    // function.
    function FlipReverseCopyRect( const Flip, Reverse : BOOLEAN;
      const Bitmap : TBitmap ) : TBitmap;
    var
      Bottom : INTEGER;
      Left : INTEGER;
      Right : INTEGER;
      Top : INTEGER;
    begin
      RESULT := TBitmap.Create;
      RESULT.Width := Bitmap.Width;
      RESULT.Height := Bitmap.Height;
      RESULT.PixelFormat := Bitmap.PixelFormat;
    
      // Flip Top to Bottom
      if Flip then
      begin
        // Unclear why extra "-1" is needed here.
        Top := Bitmap.Height - 1;
        Bottom := -1
      end
      else
      begin
        Top := 0;
        Bottom := Bitmap.Height
      end;
    
      // Reverse Left to Right
      if Reverse then
      begin
        // Unclear why extra "-1" is needed here.
        Left := Bitmap.Width - 1;
        Right := -1;
      end
      else
      begin
        Left := 0;
        Right := Bitmap.Width;
      end;
    
      RESULT.Canvas.CopyRect( Rect( Left, Top, Right, Bottom ), Bitmap.Canvas,
        Rect( 0, 0, Bitmap.Width, Bitmap.Height ) );
    end { FlipReverseCopyRect };
    
    /// ///////////////////////////////////////////////////////////////////////////
    
    function FlipReverseStretchBlt( const Flip, Reverse : BOOLEAN;
      const Bitmap : TBitmap ) : TBitmap;
    var
      Bottom : INTEGER;
      Left : INTEGER;
      Right : INTEGER;
      Top : INTEGER;
    begin
      RESULT := TBitmap.Create;
      RESULT.Width := Bitmap.Width;
      RESULT.Height := Bitmap.Height;
      RESULT.PixelFormat := Bitmap.PixelFormat;
    
      // Flip Top to Bottom
      if Flip then
      begin
        // Unclear why extra "-1" is needed here.
        Top := Bitmap.Height - 1;
        Bottom := -1
      end
      else
      begin
        Top := 0;
        Bottom := Bitmap.Height
      end;
    
      // Reverse Left to Right
      if Reverse then
      begin
        // Unclear why extra "-1" is needed here.
        Left := Bitmap.Width - 1;
        Right := -1;
      end
      else
      begin
        Left := 0;
        Right := Bitmap.Width;
      end;
    
      StretchBlt( RESULT.Canvas.Handle, Left, Top, Right - Left, Bottom - Top,
        Bitmap.Canvas.Handle, 0, 0, Bitmap.Width, Bitmap.Height, cmSrcCopy );
    end { FlipReverseStretchBlt };
    
    /// ///////////////////////////////////////////////////////////////////////////
    
    // Rotate 24-bits/pixel Bitmap any multiple of 90 degrees.
    function RotateScanline90( const angle : INTEGER; const Bitmap : TBitmap )
      : TBitmap;
    
    // These four internal functions parallel the four cases in rotating a
    // bitmap using the Pixels property.  See the RotatePixels example on
    // the Image Processing page of efg's Computer Lab for an example of the
    // use of the Pixels property (which is very slow).
    
    // A Bitmap.Assign could be used for a simple copy.  A complete example
    // using ScanLine is included here to help explain the other three cases.
      function SimpleCopy : TBitmap;
      var
        i : INTEGER;
        j : INTEGER;
        RowIn : pRGBArray;
        RowOut : pRGBArray;
      begin
        RESULT := TBitmap.Create;
        RESULT.Width := Bitmap.Width;
        RESULT.Height := Bitmap.Height;
        RESULT.PixelFormat := Bitmap.PixelFormat; // only pf24bit for now
    
        // Out[i, j] = In[i, j]
    
        for j := 0 to Bitmap.Height - 1 do
        begin
          RowIn := Bitmap.Scanline[ j ];
          RowOut := RESULT.Scanline[ j ];
    
          // Could optimize the following by using a function like CopyMemory
          // from the Windows unit.
          for i := 0 to Bitmap.Width - 1 do
          begin
            // Why does this crash with RowOut[i] := RowIn[i]?  Alignment?
            // Use this longer form as workaround.
            with RowOut[ i ] do
            begin
              rgbtRed := RowIn[ i ].rgbtRed;
              rgbtGreen := RowIn[ i ].rgbtGreen;
              rgbtBlue := RowIn[ i ].rgbtBlue;
            end
          end
        end
      end { SimpleCopy };
    
      function Rotate90DegreesCounterClockwise : TBitmap;
      var
        i : INTEGER;
        j : INTEGER;
        RowIn : pRGBArray;
      begin
        RESULT := TBitmap.Create;
        RESULT.Width := Bitmap.Height;
        RESULT.Height := Bitmap.Width;
        RESULT.PixelFormat := Bitmap.PixelFormat; // only pf24bit for now
    
        // Out[j, Right - i - 1] = In[i, j]
        for j := 0 to Bitmap.Height - 1 do
        begin
          RowIn := Bitmap.Scanline[ j ];
          for i := 0 to Bitmap.Width - 1 do
            pRGBArray( RESULT.Scanline[ Bitmap.Width - i - 1 ] )[ j ] := RowIn[ i ]
        end
      end { Rotate90DegreesCounterClockwise };
    
    // Could use Rotate90DegreesCounterClockwise twice to get a
    // Rotate180DegreesCounterClockwise.  Rotating 180 degrees is the same
    // as a Flip and Reverse
      function Rotate180DegreesCounterClockwise : TBitmap;
      var
        i : INTEGER;
        j : INTEGER;
        RowIn : pRGBArray;
        RowOut : pRGBArray;
      begin
        RESULT := TBitmap.Create;
        RESULT.Width := Bitmap.Width;
        RESULT.Height := Bitmap.Height;
        RESULT.PixelFormat := Bitmap.PixelFormat; // only pf24bit for now
    
        // Out[Right - i - 1, Bottom - j - 1] = In[i, j]
        for j := 0 to Bitmap.Height - 1 do
        begin
          RowIn := Bitmap.Scanline[ j ];
          RowOut := RESULT.Scanline[ Bitmap.Height - j - 1 ];
          for i := 0 to Bitmap.Width - 1 do
            RowOut[ Bitmap.Width - i - 1 ] := RowIn[ i ]
        end
    
      end { Rotate180DegreesCounterClockwise };
    
    // Could use Rotate90DegreesCounterClockwise three times to get a
    // Rotate270DegreesCounterClockwise
      function Rotate270DegreesCounterClockwise : TBitmap;
      var
        i : INTEGER;
        j : INTEGER;
        RowIn : pRGBArray;
      begin
        RESULT := TBitmap.Create;
        RESULT.Width := Bitmap.Height;
        RESULT.Height := Bitmap.Width;
        RESULT.PixelFormat := Bitmap.PixelFormat; // only pf24bit for now
    
        // Out[Bottom - j - 1, i] = In[i, j]
        for j := 0 to Bitmap.Height - 1 do
        begin
          RowIn := Bitmap.Scanline[ j ];
          for i := 0 to Bitmap.Width - 1 do
            pRGBArray( RESULT.Scanline[ i ] )[ Bitmap.Height - j - 1 ] := RowIn[ i ]
        end
      end { Rotate270DegreesCounterClockwise };
    
    begin
      if Bitmap.PixelFormat <> pf24bit then
        raise EBitmapError.Create( 'Can Rotate90 only 24-bit bitmap' );
    
      if ( angle >= 0 ) and ( angle mod 90 <> 0 ) then
        raise EBitmapError.Create
          ( 'Rotate90:  Angle not positive multiple of 90 degrees' );
    
      case ( angle div 90 ) mod 4 of
        0 :
          RESULT := SimpleCopy;
        1 :
          RESULT := Rotate90DegreesCounterClockwise;
        // Anticlockwise for the Brits
        2 :
          RESULT := Rotate180DegreesCounterClockwise;
        3 :
          RESULT := Rotate270DegreesCounterClockwise
      else
        RESULT := nil // avoid compiler warning
      end;
    
    end { RotateScanline90 };
    
    end.

  • 相关阅读:
    LeetCode 382. Linked List Random Node
    LeetCode 398. Random Pick Index
    LeetCode 1002. Find Common Characters
    LeetCode 498. Diagonal Traverse
    LeetCode 825. Friends Of Appropriate Ages
    LeetCode 824. Goat Latin
    LeetCode 896. Monotonic Array
    LeetCode 987. Vertical Order Traversal of a Binary Tree
    LeetCode 689. Maximum Sum of 3 Non-Overlapping Subarrays
    LeetCode 636. Exclusive Time of Functions
  • 原文地址:https://www.cnblogs.com/shangdawei/p/3061584.html
Copyright © 2020-2023  润新知