TPaintBox使用SetWorldTransform旋转图像

简·多根(Jan Doggen)

我正在将图像加载到中TPaintBox,然后尝试按照此答案中的建议使用SetWorldTransform旋转它

图片通过加载良好TPaintBox.Invalidate -> TPaintBox.OnPaint
但是,当我单击“测试”按钮时BtnRotateWorldTransform,我看到图像闪烁但没有旋转。

procedure TFrmRotateImage.FormCreate(Sender: TObject);
begin
  FWICImage := TWICImage.Create; 
end;

procedure TFrmRotateImage.BtnLoadPaintBoxClick(Sender: TObject);
begin
   if DlgOpen.Execute then  // PNG or JPG file
   begin
      try
         FWICImage.LoadFromFile(DlgOpen.FileName);
         FBoxLoaded := true;
         PaintBox.Invalidate;
      finally
      end;
   end;
end;

procedure TFrmRotateImage.PaintBoxPaint(Sender: TObject);  // OnPaint handler
begin
   if not FBoxLoaded then Exit;
   PaintBox.Canvas.Draw(0,0,FWICImage);
end;

procedure TFrmRotateImage.BtnRotateWorldTransformClick(Sender: TObject);  // Test button
var
   lRect: TRect;
begin
   lRect.Top    := PaintBox.Top;
   lRect.Left   := PaintBox.Left;
   lRect.Width  := PaintBox.Width;
   lRect.Height := PaintBox.Height;
   StretchDrawRotated(PaintBox.Canvas,lRect,90,lRect.CenterPoint,FWICImage);
   PaintBox.Invalidate;
end;

procedure XForm_SetRotation(out AXForm: TXForm; AAngle: Extended; ACenter: TPoint);
var
  SinA, CosA: Extended;
begin
  SinCos(AAngle, SinA, CosA);
  AXForm.eM11 := CosA;
  AXForm.eM12 := SinA;
  AXForm.eM21 := -SinA;
  AXForm.eM22 := CosA;
  AXForm.eDx := (ACenter.X - (CosA * ACenter.X)) + ((SinA * ACenter.Y));
  AXForm.eDy := (ACenter.Y - (SinA * ACenter.X)) - ((CosA * ACenter.Y));
end;

procedure StretchDrawRotated(ACanvas: TCanvas; const ARect: TRect; AAngle: Extended; ACenter: TPoint; AGraphic: TGraphic);
var
  XForm, XFormOld: TXForm;
  GMode: Integer;
begin
  GMode := SetGraphicsMode(ACanvas.Handle, GM_ADVANCED);
  try
    if GetWorldTransform(ACanvas.Handle, XFormOld) then
      try
        XForm_SetRotation(XForm, AAngle, ACenter);
        SetWorldTransform(ACanvas.Handle, XForm);
        ACanvas.StretchDraw(ARect, AGraphic);
      finally
        SetWorldTransform(ACanvas.Handle, XFormOld);
      end;
  finally
    SetGraphicsMode(ACanvas.Handle, GMode);
  end;
end;

我忘了什么?

fpiette

我写了一个完整的例子。在此示例中,我展示了如何旋转,平移,缩放图像并结合这些转换。

为此,我编写了3个函数来轻松准备旋转,缩放和平移。

在PaintBox1Paint事件处理程序中,我为旋转,缩放和平移取了固定值。当然,在正常的应用程序中,它来自其他地方(例如UI)。转换计算应在PaintBox1Paint过程之外,并在每次参数变化时进行。然后应调用Invalidate,以便使用新的计算转换对它进行重绘。

procedure TForm4.FormCreate(Sender: TObject);
begin
    FWICImage := TWICImage.Create;
end;

procedure TForm4.FormDestroy(Sender: TObject);
begin
    FreeAndNil(FWICImage);
end;

procedure TForm4.LoadImageButtonClick(Sender: TObject);
begin
    FWICImage.LoadFromFile('C:\Users\fpiette\Pictures\Delphi25 ICS.jpg');
    FBoxLoaded := TRUE;
    PaintBox1.Invalidate;
end;

function XForm_SetRotation(
    AAngle     : Single;
    ACenter    : TPoint) : TXForm;
var
    SinA, CosA: Extended;
begin
    SinCos(AAngle, SinA, CosA);
    Result.eM11 := CosA;
    Result.eM12 := SinA;
    Result.eM21 := -SinA;
    Result.eM22 := CosA;
    Result.eDx := (ACenter.X - (CosA * ACenter.X)) + ((SinA * ACenter.Y));
    Result.eDy := (ACenter.Y - (SinA * ACenter.X)) - ((CosA * ACenter.Y));
end;

function XForm_SetScale(
    const AZoomX : Single;
    const AZoomY : Single;
    const center: TPoint) : TXForm;
begin
    Result.eM11 := AZoomX;
    Result.eM12 := 0.0;
    Result.eM21 := 0.0;
    Result.eM22 := AZoomY;
    Result.eDx  := center.x - AZoomX * center.x;
    Result.eDy  := center.y - AZoomY * center.y;
end;

function XForm_SetTranslate(
    const ADistX : Integer;
    const ADistY : Integer) : TXForm;
begin
    Result.eM11 := 1.0;
    Result.eM12 := 0.0;
    Result.eM21 := 0.0;
    Result.eM22 := 1.0;
    Result.eDx  := ADistX;
    Result.eDy  := ADistY;
end;

procedure TForm4.PaintBox1Paint(Sender: TObject);
var
    XFormScale  : TXForm;
    XFormRot    : TXForm;
    XFormXLat   : TXForm;
    XForm       : TXForm;
    XFormOld    : TXForm;
    GMode       : Integer;
    AZoomFactor : Single;
    AAngle      : Single;
    ADistX      : Integer;
    ADistY      : Integer;
    ACanvas     : TCanvas;
begin
    if not FBoxLoaded then
        Exit;

    AZoomFactor := 0.25;
    AAngle      := 30.0;
    ADistX      := 100;
    ADistY      := 200;
    ACanvas     := PaintBox1.Canvas;

    GMode := SetGraphicsMode(ACanvas.Handle, GM_ADVANCED);
    try
        if GetWorldTransform(ACanvas.Handle, XFormOld) then begin
            try
                XFormRot   := XForm_SetRotation(
                                  AAngle,
                                  Point(FWICImage.Width div 2,
                                        FWICImage.Height div 2));
                XFormScale := XForm_SetScale(
                                  AZoomFactor, AZoomFactor, Point(0, 0));
                XFormXLat  := XForm_SetTranslate(ADistX, ADistY);
                CombineTransform(XForm, XFormRot, XFormScale);
                CombineTransform(XForm, XForm,    XFormXLat);
                SetWorldTransform(ACanvas.Handle, XForm);
                ACanvas.Draw(0, 0, FWICImage);
            finally
                SetWorldTransform(ACanvas.Handle, XFormOld);
            end;
        end;
    finally
        SetGraphicsMode(ACanvas.Handle, GMode);
    end;
end;

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用UIGraphicsImageRenderer旋转图像?

来自分类Dev

使用pygame旋转图像

来自分类Dev

Matlab旋转图像而不使用旋转

来自分类Dev

Matlab旋转图像而不使用旋转

来自分类Dev

尝试使用jQuery旋转图像

来自分类Dev

使用C旋转BMP图像

来自分类Dev

使用VBA旋转保存的图像

来自分类Dev

旋转图像并使用xml翻译

来自分类Dev

使用AngularJS自旋转图像

来自分类Dev

错误使用php旋转图像

来自分类Dev

尝试使用jQuery旋转图像

来自分类Dev

使用javascript比较旋转的图像

来自分类Dev

使用Janmuller库旋转图像偏心图像

来自分类Dev

使用Janmuller库旋转图像偏心图像

来自分类Dev

使用javascript旋转和取消旋转图像onClick

来自分类Dev

旋转自动旋转旋转的图像

来自分类Dev

使用ImageMagick检测EXIF方向并旋转图像

来自分类Dev

使用CGImageSourceRef加载图像时旋转错误

来自分类Dev

使用skimage旋转图像而不进行裁剪

来自分类Dev

使用鼠标旋转画布中的图像

来自分类Dev

如果需要使用javascript旋转图像

来自分类Dev

使用leptonica旋转时图像像素丢失

来自分类Dev

使用旋转的矩形提取图像ROI

来自分类Dev

使用CIFilter后图像自动旋转

来自分类Dev

Android:如何使用壁画旋转图像

来自分类Dev

如何使用jQuery保存旋转图像?

来自分类Dev

使用精灵在Pygame中旋转图像

来自分类Dev

单击后使用JavaScript旋转图像

来自分类Dev

使用numpy旋转图像(面试问题)