600*600圆形
使用的RotateImage旋转锯齿比较明显
寻找无锯齿的图片中心旋转 方法(要可形成连续旋转)

解决方案 »

  1.   

    //将 FSrcBmp 按 Frotate角度和FDstRect画至FDstBmp上,并以 FDstBmp 的位深度进行相应的插值处理
    procedure DrawRotateAtBmp(FSrcBmp ,FDstBmp: TBitmap; FDstRect : TGpRectF; FRotate : Single ; bCreateMask : Boolean = True);
      var aGpSrcBmp,aGpAASrcBmp : TGpBitmap;
          Gd,aAAGd : TGpGraphics;
          aMatrix : TGpMatrix;
          FCenter : TGpPointF;
          aAASrcBmp ,aAADstBmp,Bmp : TBitmap;
          aAADstRect : TGpRectF;
          i, j : Integer;
          aMask  : TBitmap;
          pData,pMask : pByteArray;
    begin
      Bmp := TBitmap.Create;
      Bmp.Assign(FDstBmp);  aGpSrcBmp := TGpBitmap.Create(FSrcBmp.Handle,FSrcBmp.Palette); //转换为tgpbitmap
      aAASrcBmp := TBitmap.Create;
      aAASrcBmp.Width := FSrcBmp.Width * 4;
      aAASrcBmp.Height := FSrcBmp.Height * 4;
      aAASrcBmp.Canvas.CopyRect(aAASrcBmp.Canvas.ClipRect,FSrcBmp.Canvas,FSrcBmp.Canvas.ClipRect);
      //将放大四倍后的原始图像转换为tgpbitmap对象
      aGpAASrcBmp := TGpBitmap.Create(aAASrcBmp.Handle,aAASrcBmp.Palette);
      //将目标图像放大四倍
      aAADstBmp :=TBitmap.Create;
      aAADstBmp.PixelFormat := FDstBmp.PixelFormat;
      aAADstBmp.Width := FDstBmp.Width * 4 ;
      aAADstBmp.Height := FDstBmp.Height * 4;
      aAADstBmp.Canvas.CopyRect(aAADstBmp.Canvas.ClipRect,FDstBmp.Canvas,FDstBmp.Canvas.ClipRect);  FCenter.X := Round(FDstRect.X  + FDstRect.Width / 2);   //旋转中心点    + FDispRect.X
      FCenter.Y := Round(FDstRect.Y  + FDstRect.Height / 2);
      //按原始尺寸将fsrcbmp绘制到fdstbmp
      try
        Gd := TGpGraphics.Create(FDstBmp.Canvas.Handle);
        aMatrix := TGpMatrix.Create;
        aMatrix.RotateAt(FRotate,FCenter);
        Gd.SetTransform(aMatrix);                          // aGpSrcBmp
        Gd.DrawImage(aGpSrcBmp,FDstRect,0,0, aGpSrcBmp.Width,aGpSrcBmp.Height,utPixel);
      finally
        aMatrix.Free;
        Gd.Free;
      end;
      if bCreateMask then
      begin
        //单独将原始图像ALPHA通道插值处理 ,保存旋转后的通道,如原始图像为24位,则不需要该操作
        aMask := TBitmap.Create;
        aMask.PixelFormat := pf32bit;
        aMask.Width := FDstBmp.Width;
        aMask.Height := FDstBmp.Height;
        CreateAlpha(FSrcBmp,FDstBmp,FDstRect,FRotate,False);
        aMask.Assign(FDstBmp);
      end;  FCenter.X := Round(FDstRect.X * 4 +  FDstRect.Width * 4/ 2); 
      FDispRect.X * 4 +  FDispRect.Y * 4 +
      FCenter.Y := Round(FDstRect.Y * 4 +  FDstRect.Height * 4/ 2);
      with aAADstRect do
      begin
       x:=FDstRect.X * 4 ; Y := FDstRect.Y * 4; Width := FDstRect.Width * 4;
       Height := FDstRect.Height * 4;
      end;
      //绘制全部放大四倍后的图像
      try
        aAAGd := TGpGraphics.Create(aAADstBmp.Canvas.Handle);
        aMatrix := TGpMatrix.Create;
        aMatrix.RotateAt(FRotate,FCenter);
        aAAGd.SetTransform(aMatrix);
        aAAGd.DrawImage(aGpAASrcBmp,aAADstRect,
                        0,0,aGpAASrcBmp.Width,aGpAASrcBmp.Height ,utPixel);
      finally
        aMatrix.Free;
        aAAGd.Free;
      end;
      //按4倍插值进行位图反走样,注意必须是24位
      //参数:1:按原始尺寸绘制后的图像;2:按放大四倍后绘制图像;3,4:原始目标图像大小
      CreateAAImage(FDstBmp.Canvas.Handle,aAADstBmp.Canvas.Handle,4,FDstBmp.Width,FDstBmp.Height,FDstBmp.PixelFormat);
      //将插值处理后的通道赋给目标图像,如fsrcbmp为24位,则无需要处理
      if bCreateMask and (Assigned(aMask)) then
      begin
        for i := 0 to FDstBmp.Height - 1 do
        begin
          pData := FDstBmp.ScanLine[i];
          pMask := aMask.ScanLine[i];
          for j := 0 to FDstBmp.Width - 1 do
          begin
            pData[j * 4 + 3] := pMask[j * 4 + 3];
          end;  
        end;
        aMask.Free;
      end;
      FreeAndNil(aGpSrcBmp);
      FreeAndNil(aGpAASrcBmp);
      FreeAndNil(aAADstBmp);
      FreeAndNil(aAASrcBmp);
      FreeAndNil(Bmp);
    end;procedure CreateAAImage(hAADC : HDC; hSrcDc : HDC; scale : Integer;aWidth ,aHeight : Integer ; pf : Graphics.TPixelFormat = pf24bit);
      var  hSrcBitmap,hAABitmap : HBITMAP;
           srcWidth ,srcHeight ,srcPitch,srcSize : Integer;
           dstWidth, dstHeight ,dstPitch,dstSize : Integer;
           lpSrcBits ,lpDstBits: array of Byte;
           gridSize : Integer;
           resultRed, resultGreen, resultBlue,resultAlpha : Integer;
           dstX, dstY, dstOffset : Integer;
           srcX, srcY, srcOffset : Integer;
           tmpX, tmpY, tmpOffset : Integer;
           X,Y,i,j ,nType:Integer;
    begin
      case pf of
        pf24bit : nType := 3;
        pf32bit : nType := 4;
      end;
      srcWidth := scale * awidth;
      srcHeight := scale * aHeight;
      srcPitch := srcWidth * nType;
      srcSize :=  srcHeight * srcPitch;
      SetLength(lpSrcBits,srcSize);
      hSrcBitmap := HBITMAP(GetCurrentObject(hSrcDc,OBJ_BITMAP));
      GetBitmapBits(hSrcBitmap, srcSize, lpSrcBits);
      dstWidth := aWidth;
      dstHeight := aHeight;
      dstPitch := dstWidth * nType;
      dstSize := dstHeight * dstPitch;
      SetLength(lpDstBits,dstSize);
      hAABitmap  := HBITMAP(GetCurrentObject(hAADC, OBJ_BITMAP));
      GetBitmapBits(hAABitmap, dstSize, lpDstBits);  gridSize := scale * scale;
      dstX := 0; dstY := 0;
      for y := 1 to dstHeight - 2 do
      begin
        dstX := 0; srcX := 0;
        srcY := (y * scale) * srcPitch;
        for X := 1 to dstWidth - 2 do
        begin
          srcX := (x * scale) * nType;
          srcOffset := srcY + srcX;
          resultRed := 0; resultGreen := 0;
          resultBlue := 0; resultAlpha := 0;
          tmpY := -srcPitch;
          for i := 0 to scale - 1 do
          begin
            tmpX := -nType;
            for j := 0 to scale - 1 do
            begin
              tmpOffset := tmpY + tmpX;
              if nType = 4 then
                resultAlpha := resultAlpha + lpSrcBits[srcOffset + tmpOffset + 3];
              resultRed := resultRed + lpSrcBits[srcOffset + tmpOffset + 2];
              resultGreen := resultGreen + lpSrcBits[srcOffset + tmpOffset + 1];
              resultBlue := resultBlue + lpSrcBits[srcOffset + tmpOffset];
              tmpX := tmpX + nType;
            end;
            tmpY := tmpY + srcPitch;
          end;
          dstOffset := dstY + dstX;
          if nType = 4 then
            lpDstBits[dstOffset + 3] := BYTE(Round(resultAlpha / gridSize));
          lpDstBits[dstOffset + 2] := BYTE(Round(resultRed / gridSize));
          lpDstBits[dstOffset + 1] := BYTE(Round(resultGreen / gridSize));
          lpDstBits[dstOffset] := BYTE(Round(resultBlue / gridSize));
          dstX := dstX +  nType;
        end;
        dstY := dstY + dstPitch;
      end;
      SetBitmapBits(hAABitmap, dstSize, lpDstBits);
      lpSrcBits := nil;
      lpDstBits := nil;
    end;procedure CreateAlpha(FSrcbmp,FDstBmp : TBitmap;FDstRect : TGpRectF;FRotate : Single;bCreateMask : Boolean = True);
      var pDst,pSrc : pByteArray;
          aMask,aDstMask  : TBitmap;
          i , j : Integer;
    begin
      aDstMask := TBitmap.Create;
      aDstMask.PixelFormat := pf24bit;
      aDstMask.Width := FDstBmp.Width;
      aDstMask.Height := FDstBmp.Height;
      aDstMask.Canvas.Brush.Color := clBlack;
      aDstMask.Canvas.FillRect(aDstMask.Canvas.ClipRect);
      aMask := TBitmap.Create;
      aMask.PixelFormat := pf24bit;
      aMask.Width := FSrcBmp.Width;
      aMask.Height := FSrcBmp.Height;
      for i := 0 to FSrcBmp.Height - 1 do
      begin
        pDst := aMask.ScanLine[i];
        pSrc := FSrcBmp.ScanLine[i];
        for j := 0 to FSrcBmp.Width - 1 do
        begin
          pDst[j * 3 ] := pSrc[j * 4 + 3];
          pDst[j * 3 + 1] := pSrc[j * 4 + 3];
          pDst[j * 3 + 2] := pSrc[j * 4 + 3];
        end;
      end;
      DrawRotateAtBmp(aMask,aDstMask,FDstRect,FRotate,False);
      for i := 0 to FDstBmp.Height - 1 do
      begin
        pDst := FDstBmp.ScanLine[i];
        pSrc := aDstMask.ScanLine[i];
        for j := 0 to FDstBmp.Width - 1 do
        begin
          pDst[j * 4 + 3] := pSrc[j * 3];
        end;  
      end;
      aDstMask.Free;
      aMask.Free;
    end;
      

  2.   

    //将 FSrcBmp 按 Frotate角度和FDstRect画至FDstBmp上,并以 FDstBmp 的位深度进行相应的插值处理
    procedure DrawRotateAtBmp(FSrcBmp ,FDstBmp: TBitmap; FDstRect : TGpRectF; FRotate : Single ; bCreateMask : Boolean = True);
      var aGpSrcBmp,aGpAASrcBmp : TGpBitmap;
          Gd,aAAGd : TGpGraphics;
          aMatrix : TGpMatrix;
          FCenter : TGpPointF;
          aAASrcBmp ,aAADstBmp,Bmp : TBitmap;
          aAADstRect : TGpRectF;
          i, j : Integer;
          aMask  : TBitmap;
          pData,pMask : pByteArray;
    begin
      Bmp := TBitmap.Create;
      Bmp.Assign(FDstBmp);  aGpSrcBmp := TGpBitmap.Create(FSrcBmp.Handle,FSrcBmp.Palette); //转换为tgpbitmap
      aAASrcBmp := TBitmap.Create;
      aAASrcBmp.Width := FSrcBmp.Width * 4;
      aAASrcBmp.Height := FSrcBmp.Height * 4;
      aAASrcBmp.Canvas.CopyRect(aAASrcBmp.Canvas.ClipRect,FSrcBmp.Canvas,FSrcBmp.Canvas.ClipRect);
      //将放大四倍后的原始图像转换为tgpbitmap对象
      aGpAASrcBmp := TGpBitmap.Create(aAASrcBmp.Handle,aAASrcBmp.Palette);
      //将目标图像放大四倍
      aAADstBmp :=TBitmap.Create;
      aAADstBmp.PixelFormat := FDstBmp.PixelFormat;
      aAADstBmp.Width := FDstBmp.Width * 4 ;
      aAADstBmp.Height := FDstBmp.Height * 4;
      aAADstBmp.Canvas.CopyRect(aAADstBmp.Canvas.ClipRect,FDstBmp.Canvas,FDstBmp.Canvas.ClipRect);  FCenter.X := Round(FDstRect.X  + FDstRect.Width / 2);   //旋转中心点    + FDispRect.X
      FCenter.Y := Round(FDstRect.Y  + FDstRect.Height / 2);
      //按原始尺寸将fsrcbmp绘制到fdstbmp
      try
        Gd := TGpGraphics.Create(FDstBmp.Canvas.Handle);
        aMatrix := TGpMatrix.Create;
        aMatrix.RotateAt(FRotate,FCenter);
        Gd.SetTransform(aMatrix);                          // aGpSrcBmp
        Gd.DrawImage(aGpSrcBmp,FDstRect,0,0, aGpSrcBmp.Width,aGpSrcBmp.Height,utPixel);
      finally
        aMatrix.Free;
        Gd.Free;
      end;
      if bCreateMask then
      begin
        //单独将原始图像ALPHA通道插值处理 ,保存旋转后的通道,如原始图像为24位,则不需要该操作
        aMask := TBitmap.Create;
        aMask.PixelFormat := pf32bit;
        aMask.Width := FDstBmp.Width;
        aMask.Height := FDstBmp.Height;
        CreateAlpha(FSrcBmp,FDstBmp,FDstRect,FRotate,False);
        aMask.Assign(FDstBmp);
      end;  FCenter.X := Round(FDstRect.X * 4 +  FDstRect.Width * 4/ 2); 
      FDispRect.X * 4 +  FDispRect.Y * 4 +
      FCenter.Y := Round(FDstRect.Y * 4 +  FDstRect.Height * 4/ 2);
      with aAADstRect do
      begin
       x:=FDstRect.X * 4 ; Y := FDstRect.Y * 4; Width := FDstRect.Width * 4;
       Height := FDstRect.Height * 4;
      end;
      //绘制全部放大四倍后的图像
      try
        aAAGd := TGpGraphics.Create(aAADstBmp.Canvas.Handle);
        aMatrix := TGpMatrix.Create;
        aMatrix.RotateAt(FRotate,FCenter);
        aAAGd.SetTransform(aMatrix);
        aAAGd.DrawImage(aGpAASrcBmp,aAADstRect,
                        0,0,aGpAASrcBmp.Width,aGpAASrcBmp.Height ,utPixel);
      finally
        aMatrix.Free;
        aAAGd.Free;
      end;
      //按4倍插值进行位图反走样,注意必须是24位
      //参数:1:按原始尺寸绘制后的图像;2:按放大四倍后绘制图像;3,4:原始目标图像大小
      CreateAAImage(FDstBmp.Canvas.Handle,aAADstBmp.Canvas.Handle,4,FDstBmp.Width,FDstBmp.Height,FDstBmp.PixelFormat);
      //将插值处理后的通道赋给目标图像,如fsrcbmp为24位,则无需要处理
      if bCreateMask and (Assigned(aMask)) then
      begin
        for i := 0 to FDstBmp.Height - 1 do
        begin
          pData := FDstBmp.ScanLine[i];
          pMask := aMask.ScanLine[i];
          for j := 0 to FDstBmp.Width - 1 do
          begin
            pData[j * 4 + 3] := pMask[j * 4 + 3];
          end;  
        end;
        aMask.Free;
      end;
      FreeAndNil(aGpSrcBmp);
      FreeAndNil(aGpAASrcBmp);
      FreeAndNil(aAADstBmp);
      FreeAndNil(aAASrcBmp);
      FreeAndNil(Bmp);
    end;procedure CreateAAImage(hAADC : HDC; hSrcDc : HDC; scale : Integer;aWidth ,aHeight : Integer ; pf : Graphics.TPixelFormat = pf24bit);
      var  hSrcBitmap,hAABitmap : HBITMAP;
           srcWidth ,srcHeight ,srcPitch,srcSize : Integer;
           dstWidth, dstHeight ,dstPitch,dstSize : Integer;
           lpSrcBits ,lpDstBits: array of Byte;
           gridSize : Integer;
           resultRed, resultGreen, resultBlue,resultAlpha : Integer;
           dstX, dstY, dstOffset : Integer;
           srcX, srcY, srcOffset : Integer;
           tmpX, tmpY, tmpOffset : Integer;
           X,Y,i,j ,nType:Integer;
    begin
      case pf of
        pf24bit : nType := 3;
        pf32bit : nType := 4;
      end;
      srcWidth := scale * awidth;
      srcHeight := scale * aHeight;
      srcPitch := srcWidth * nType;
      srcSize :=  srcHeight * srcPitch;
      SetLength(lpSrcBits,srcSize);
      hSrcBitmap := HBITMAP(GetCurrentObject(hSrcDc,OBJ_BITMAP));
      GetBitmapBits(hSrcBitmap, srcSize, lpSrcBits);
      dstWidth := aWidth;
      dstHeight := aHeight;
      dstPitch := dstWidth * nType;
      dstSize := dstHeight * dstPitch;
      SetLength(lpDstBits,dstSize);
      hAABitmap  := HBITMAP(GetCurrentObject(hAADC, OBJ_BITMAP));
      GetBitmapBits(hAABitmap, dstSize, lpDstBits);  gridSize := scale * scale;
      dstX := 0; dstY := 0;
      for y := 1 to dstHeight - 2 do
      begin
        dstX := 0; srcX := 0;
        srcY := (y * scale) * srcPitch;
        for X := 1 to dstWidth - 2 do
        begin
          srcX := (x * scale) * nType;
          srcOffset := srcY + srcX;
          resultRed := 0; resultGreen := 0;
          resultBlue := 0; resultAlpha := 0;
          tmpY := -srcPitch;
          for i := 0 to scale - 1 do
          begin
            tmpX := -nType;
            for j := 0 to scale - 1 do
            begin
              tmpOffset := tmpY + tmpX;
              if nType = 4 then
                resultAlpha := resultAlpha + lpSrcBits[srcOffset + tmpOffset + 3];
              resultRed := resultRed + lpSrcBits[srcOffset + tmpOffset + 2];
              resultGreen := resultGreen + lpSrcBits[srcOffset + tmpOffset + 1];
              resultBlue := resultBlue + lpSrcBits[srcOffset + tmpOffset];
              tmpX := tmpX + nType;
            end;
            tmpY := tmpY + srcPitch;
          end;
          dstOffset := dstY + dstX;
          if nType = 4 then
            lpDstBits[dstOffset + 3] := BYTE(Round(resultAlpha / gridSize));
          lpDstBits[dstOffset + 2] := BYTE(Round(resultRed / gridSize));
          lpDstBits[dstOffset + 1] := BYTE(Round(resultGreen / gridSize));
          lpDstBits[dstOffset] := BYTE(Round(resultBlue / gridSize));
          dstX := dstX +  nType;
        end;
        dstY := dstY + dstPitch;
      end;
      SetBitmapBits(hAABitmap, dstSize, lpDstBits);
      lpSrcBits := nil;
      lpDstBits := nil;
    end;procedure CreateAlpha(FSrcbmp,FDstBmp : TBitmap;FDstRect : TGpRectF;FRotate : Single;bCreateMask : Boolean = True);
      var pDst,pSrc : pByteArray;
          aMask,aDstMask  : TBitmap;
          i , j : Integer;
    begin
      aDstMask := TBitmap.Create;
      aDstMask.PixelFormat := pf24bit;
      aDstMask.Width := FDstBmp.Width;
      aDstMask.Height := FDstBmp.Height;
      aDstMask.Canvas.Brush.Color := clBlack;
      aDstMask.Canvas.FillRect(aDstMask.Canvas.ClipRect);
      aMask := TBitmap.Create;
      aMask.PixelFormat := pf24bit;
      aMask.Width := FSrcBmp.Width;
      aMask.Height := FSrcBmp.Height;
      for i := 0 to FSrcBmp.Height - 1 do
      begin
        pDst := aMask.ScanLine[i];
        pSrc := FSrcBmp.ScanLine[i];
        for j := 0 to FSrcBmp.Width - 1 do
        begin
          pDst[j * 3 ] := pSrc[j * 4 + 3];
          pDst[j * 3 + 1] := pSrc[j * 4 + 3];
          pDst[j * 3 + 2] := pSrc[j * 4 + 3];
        end;
      end;
      DrawRotateAtBmp(aMask,aDstMask,FDstRect,FRotate,False);
      for i := 0 to FDstBmp.Height - 1 do
      begin
        pDst := FDstBmp.ScanLine[i];
        pSrc := aDstMask.ScanLine[i];
        for j := 0 to FDstBmp.Width - 1 do
        begin
          pDst[j * 4 + 3] := pSrc[j * 3];
        end;  
      end;
      aDstMask.Free;
      aMask.Free;
    end;
      

  3.   

    主要是在旋转的时候边缘有 
    GDI
    我不会把四周搞透明