我在处理图像旋转和镜像问题的时候,用Pixel的赋值进行操作,发现效率很差,因此改用其它的方法,例如:ScanLine、BitBlt等也不是很好。不过再用StretchDraw的时候速度挺快,但是不管坐标如何定义,总是有一白边,代码如下:
//MirHorizontal:
var
bit,bitCurrent:TBitmap;
rctDraw:TRect;
begin
bitCurrent.Width:=bit.Width ;
bitCurrent.Height:= bit.Height ;
rctDraw.Top:=0;
rctDraw.Left:=bit.Width;//改成bit.Width-1也不行
rctDraw.Bottom :=bit.Height;//改成bit.Height-1也不行
rctDraw.Right :=0;
bitCurrent.Canvas.StretchDraw(rctDraw,bit);
end;希望各位图像旋转和镜像问题给于好的建议和方法,上面的代码能指出错误的原因。

解决方案 »

  1.   

    rctDraw.Left:=bit.Width + 1;试试
    这种例子很多的到处找找一大堆
      

  2.   

    //镜像(水平翻转)
    Procedure Mirror(JPg:TJpegImage);
    Var
       X,Y                 : Integer;
       SrcRect,DstRect     : TRect;
       Bitmap1,Bitmap2:Tbitmap;
    Begin
    //  Try
        Try
          Bitmap1:=Tbitmap.create;
          Bitmap1.PixelFormat:=pf24bit;
          Bitmap1.Width:=Jpg.Width;
          Bitmap1.Height:=Jpg.Height;
          Bitmap1.Assign(JPg);
          X := Bitmap1.Width;
          Y := Bitmap1.Height;
          SrcRect := Rect(0,0,X,Y);
          DstRect := Rect(X,0,0,Y);
          Bitmap2 := TBitmap.Create;
          Bitmap2.PixelFormat:=pf24bit;
          Bitmap2.Width := x;
          Bitmap2.Height := y;
          Bitmap2.Canvas.CopyRect(DstRect,Bitmap1.Canvas,SrcRect);
          Jpg.Assign(Bitmap2);
        Finally;
          bitmap1.Free;
          Bitmap2.Free;
        End;
    End;
      

  3.   

    谢谢各位,
    镜像问题我已解决,不过没用Canvas.StretchDraw,用的StretchBlt后一切正常。余下就是旋转的效率的问题,我的旋转只有90,180,270,可以不用考虑复杂的情况,希望给些建议和好的方法。
      

  4.   

    To DWGZ() :
            你的方法我也试过,效果没有解决,不过,直接调用Api就没出现上面的问题的。
      

  5.   

    FUNCTION RotateScanLine90(CONST Angle:  INTEGER;
                              CONST Bitmap:  TBitmap):TBitmap;
       FUNCTION SimpleCopy:  TBitmap;   //0
       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;    //
          FOR J := 0 TO Bitmap.Height - 1 DO BEGIN
             RowIn  := Bitmap.ScanLine[J];
             RowOut := RESULT.ScanLine[J];
             FOR i := 0 TO Bitmap.Width - 1 DO BEGIN
                WITH rowOut[i] DO BEGIN
                   rgbtRed   := rowIn[i].rgbtRed;
                   rgbtGreen := rowIn[i].rgbtGreen;
                   rgbtBlue  := rowIn[i].rgbtBlue;
                END;
             END;
          END;
       END {简单拷贝};   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;
          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;
        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
           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};
        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
           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('仅支持24位图像');
        IF (angle >= 0) AND (angle MOD 90 <> 0)
        THEN RAISE EBitmapError.Create('参数错误!');}
        Try
          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;
        Except
          On EOutOfResources Do
            Messagebox(Application.handle,'系统资源不足!','Error',mb_ok+mb_iconError);
          On EOutOfMemory Do
            Messagebox(Application.handle,'内存溢出!','Error',mb_ok+mb_iconError);
        Else
          Messagebox(Application.handle,'出现异常错误!','Error',mb_ok+mb_iconError);
        End;
      

  6.   

    不知道为什么,我一用ScanLine,效率更低,还没有直接通过Pixel操作快。还有一个问题,就是在移动的时候,图片的抖动问题(即闪的特别厉害)。
      

  7.   

    根据我使用的情况,scanline是效率最高的,如果你认为不行的话,试试下面两个//利用块拷贝方法将源图片进行翻转或颠倒
    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;
       IF Flip THEN BEGIN
          Top    := Bitmap.Height-1;
          Bottom := -1
          END
       ELSE BEGIN
          Top    := 0;
          Bottom := Bitmap.Height
       END;
       IF Reverse THEN BEGIN
          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;
       IF Flip THEN BEGIN
          Top    := Bitmap.Height-1;
          Bottom := -1
          END
       ELSE BEGIN
          Top    := 0;
          Bottom := Bitmap.Height
       END;
       IF Reverse THEN BEGIN
          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};