gpt4 book ai didi

delphi - 使用 GDI+ 居中旋转图像

转载 作者:行者123 更新时间:2023-12-03 19:25:13 25 4
gpt4 key购买 nike

如何使用 GDI+ 居中旋转图像?

我在这里创建了一个小例子来说明我的问题。

界面

带有 OpenPictureDialog 和 PaintBox 的空白表单,与客户端对齐。向 PaintBox 添加一个 DoubleClick 事件和一个 OnPaintEvent。

后面的代码

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Vcl.ExtCtrls, Vcl.ExtDlgs, GDIPAPI, GDIPOBJ, GDIPUTIL;

type
TForm1 = class(TForm)
PaintBox1: TPaintBox;
OpenPictureDialog1: TOpenPictureDialog;
procedure PaintBox1Paint(Sender: TObject);
procedure PaintBox1DblClick(Sender: TObject);
private
{ Private declarations }
FImage: TGPImage;
procedure DrawImage(aMaxWidth, aMaxHeight: Cardinal); overload;
procedure DrawImage; overload;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation


{$R *.dfm}

procedure TForm1.DrawImage(aMaxWidth, aMaxHeight: Cardinal);
var
Ratio: Double;
Height, Width, HeightOffset, WidthOffset: Cardinal;
begin
PaintBox1.Canvas.Brush.Color := clWhite;
FillRect(PaintBox1.Canvas.Handle, Rect(0, 0, aMaxWidth, aMaxHeight), PaintBox1.Canvas.Brush.Handle);

if FImage = nil then
exit;

Ratio := FImage.GetWidth / FImage.GetHeight;

Height := FImage.GetHeight;
Width := FImage.GetWidth;

if (FImage.GetHeight <= aMaxHeight) and (FImage.GetWidth <= aMaxWidth) then
{ do nothing }; // Width and height allready set

if (FImage.GetHeight <= aMaxHeight) and (FImage.GetWidth > aMaxWidth) then
Width := Round(FImage.GetHeight * Ratio);

if (FImage.GetHeight > aMaxHeight) and (FImage.GetWidth > aMaxWidth) then
if Ratio > 1 then
begin
Height := Round(aMaxWidth / Ratio);
Width := aMaxWidth;
end
else
begin
Width := Round(aMaxHeight * Ratio);
Height := aMaxHeight;
end;

HeightOffset := (aMaxHeight - Height) div 2;
WidthOffset := (aMaxWidth - Width) div 2;

with TGPGraphics.Create(PaintBox1.Canvas.Handle) do
try
// RotateTransform(30);
DrawImage(FImage, WidthOffset, HeightOffset, Width, Height);
finally
Free;
end;
end;

procedure TForm1.DrawImage;
begin
DrawImage(PaintBox1.Width, PaintBox1.Height);
end;

procedure TForm1.PaintBox1DblClick(Sender: TObject);
begin
if not OpenPictureDialog1.Execute then
exit;
FImage.Free;
FImage := TGPImage.Create(OpenPictureDialog1.FileName);
DrawImage;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
DrawImage;
end;

end.

如果我不旋转图像,一切正常,但是当我调用 RotateTransform(30); 时图像偏离中心。

我试图移动原点:
  with TGPGraphics.Create(PaintBox1.Canvas.Handle) do
try
TranslateTransform(WidthOffset + (Width div 2), HeightOffset + (Height div 2));
RotateTransform(30);
DrawImage(FImage, WidthOffset, HeightOffset, Width, Height);
finally
Free;
end;

但随后图像不可见。

结果

使用下面 MBo 的答案,我最终得到了这个:
procedure TForm1.DrawImage(aMaxWidth, aMaxHeight: Cardinal; aRotationAngle: Double);
var
radAngle, Ratio: Double;
Height, Width: Cardinal;
Wanted_CX, Wanted_CY: Integer;
WCX_InRotated, WCY_InRotated, xr, yr: Single;
begin
PaintBox1.Canvas.Brush.Color := clWhite;
FillRect(PaintBox1.Canvas.Handle, Rect(0, 0, aMaxWidth, aMaxHeight), PaintBox1.Canvas.Brush.Handle);

if FImage = nil then
exit;

Ratio := FImage.GetWidth / FImage.GetHeight;

Height := FImage.GetHeight;
Width := FImage.GetWidth;

if (FImage.GetHeight <= aMaxHeight) and (FImage.GetWidth <= aMaxWidth) then
{ do nothing }; // Width and height allready set

if (FImage.GetHeight <= aMaxHeight) and (FImage.GetWidth > aMaxWidth) then
Width := Round(FImage.GetHeight * Ratio);

if (FImage.GetHeight > aMaxHeight) and (FImage.GetWidth > aMaxWidth) then
if Ratio > 1 then
begin
Height := Round(aMaxWidth / Ratio);
Width := aMaxWidth;
end
else
begin
Width := Round(aMaxHeight * Ratio);
Height := aMaxHeight;
end;

radAngle := DegToRad(aRotationAngle);
Wanted_CX := PaintBox1.Width div 2;
Wanted_CY := PaintBox1.Height div 2;
xr := 0.5 * (Width * Cos(radAngle) - Height * Sin(radAngle)); // shift of rotated center
yr := 0.5 * (Width * Sin(radAngle) + Height * Cos(radAngle)); // relative to left top corner

with TGPGraphics.Create(PaintBox1.Canvas.Handle) do
try
RotateTransform(aRotationAngle);
WCX_InRotated := Cos(radAngle) * (Wanted_CX - xr) + Sin(radAngle) * (Wanted_CY - yr);
WCY_InRotated := -Sin(radAngle) * (Wanted_CX - xr) + Cos(radAngle) * (Wanted_CY - yr);
DrawImage(FImage, WCX_InRotated, WCY_InRotated);
finally
Free;
end;
end;

最佳答案

问题根源: DrawImage 在新的(旋转的)坐标系下工作,在想要的地方画图不是那么简单。

简单示例旋转图片并以给定点为中心输出它(由黄色圆圈显示)。

var
FImage: TGPImage;
w, h, Wanted_CX, Wanted_CY: Integer;
WCX_InRotated, WCY_InRotated, xr, yr: Single;
Fi, FiRad: Double;
begin
FImage := TGPImage.Create('d:\distr\pics\test.bmp'); //220x250
Fi := 30;
FiRad := DegToRad(Fi);
w := FImage.GetWidth;
h := FImage.GetHeight;
Wanted_CX := 200; //position of rotated image center
Wanted_CY := 200;
xr := 0.5 * (w * Cos(FiRad) - h * Sin(FiRad)); //shift of rotated center
yr := 0.5 * (w * Sin(FiRad) + h * Cos(FiRad)); //relative to left top corner
with TGPGraphics.Create(Canvas.Handle) do
try
RotateTransform(Fi); //rotates about left top corner
//transform windows coordinates into rotated system
WCX_InRotated := Cos(FiRad) * (Wanted_CX - xr) + Sin(FiRad) * (Wanted_CY - yr);
WCY_InRotated := -Sin(FiRad) * (Wanted_CX - xr) + Cos(FiRad) * (Wanted_CY - yr);
DrawImage(FImage, WCX_InRotated, WCY_InRotated);
finally
Free;
end;

Canvas.Brush.Color := clYellow;
Canvas.Ellipse(200 - 4, 200 - 4, 200 + 5, 200 + 5);
end;

enter image description here

关于delphi - 使用 GDI+ 居中旋转图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40826187/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com