如何解决TPaintBox使用SetWorldTransform旋转图像
我正在将图像加载到${myObject.render}
中,然后尝试按照SetWorldTransform中的建议使用this answer旋转图像:
图片可以通过TPaintBox
很好地加载。
但是,当我单击测试按钮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,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;
我忘记了什么?
解决方法
我写了一个完整的例子。在此示例中,我展示了如何旋转,平移,缩放图像并结合这些转换。
为此,我编写了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,FWICImage);
finally
SetWorldTransform(ACanvas.Handle,XFormOld);
end;
end;
finally
SetGraphicsMode(ACanvas.Handle,GMode);
end;
end;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。