如何使用firemonkey在选定区域裁剪位图?
Posted
技术标签:
【中文标题】如何使用firemonkey在选定区域裁剪位图?【英文标题】:How crop bitmap in selected area using firemonkey? 【发布时间】:2017-10-22 23:59:08 【问题描述】:我需要为我的应用创建裁剪效果。我在 TImage 上有一个 TRectangle,当用户按下保存按钮时,我需要只复制 TRectangle 使用的区域。有什么方法可以只从 Image1.Bitmap 中剪切一个特定区域?我打印了一张图片以更好地说明我需要什么:
【问题讨论】:
你最好使用可以控制比例的画布。不要只使用任何随机的图像控件。如果是我,我会为此编写一个自定义控件。但这不会是一件非常微不足道的事情。 您使用的WrapMode
是什么?如果它是Tile
并且您的选择器覆盖了显示图像的多个图块怎么办?
裁剪过程如下: 1) 计算图像的缩放比例并将矩形边界转换为图像比例。 2) 创建一个 TBitmap 并将 CopyFromBitmap 与计算出的矩形一起使用。这会将 TImage 位图中的一个部分复制到新位图中。 3)将位图分配给您的 TImage 位图(如果这是您想要的)。
你能给我一个关于如何执行第 2 步的代码示例吗?
这个概念非常简单:在受控画布上绘制图像(您可以 100% 控制),然后进行简单的数学运算来确定比例。当然有很多资源如何在 Firemonkey 中提取图像的一部分。我用它们编写了我自己的矢量签名控件。对你来说更简单。但请不要指望我们会为您编写。
【参考方案1】:
这是一个适合我的示例:
procedure TForm1.Button1Click(Sender: TObject);
var
Bmp: TBitmap;
xScale, yScale: extended;
iRect: TRect;
begin
Bmp := TBitmap.Create;
xScale := Image1.Bitmap.Width / Image1.Width;
yScale := Image1.Bitmap.Height / Image1.Height;
try
Bmp.Width := round(Rectangle1.Width * xScale);
Bmp.Height := round(Rectangle1.Height * yScale);
iRect.Left := round(Rectangle1.Position.X * xScale);
iRect.Top := round(Rectangle1.Position.Y * yScale);
iRect.Width := round(Rectangle1.Width * xScale);
iRect.Height := round(Rectangle1.Height * yScale);
Bmp.CopyFromBitmap(Image1.Bitmap, iRect, 0, 0);
Image2.Bitmap := Bmp
finally
Bmp.Free;
end;
end;
我在这里假设Rectangle1
有Image1
作为它的Parent
:
否则您将需要考虑Position.X
和Position.Y
属性的偏移量。
这是程序运行的结果:
【讨论】:
非常感谢,正是我需要的! 我在手机上试过你的解决方案,但在一些分辨率和比例不同的智能手机中......从选择中复制的图像不正确。为什么? 这个方法准确率很差,scale是Single,rect的X、Y、Heigh和Width都是Single,但是TRect要求的是Integer,这么多“轮”要转换代码更改裁剪区域的尺寸。我正在尝试使用 TCanvas 方法将 TImage 的画布绘制到 retangle 的 TCanvas,然后使用 makenapshot 从矩形中获取 TBitmap。但仍在尝试。 @Joao xScale 和 yScale 是扩展的,而不是单一的。坦率地说,我怀疑单曲的 mashine epsilon 5.96e-08 - 1.19e-07 在当前情况下真的很重要。当分辨率约为 10000000 - 100000000 像素时,可能会出现 1 px 错误。否则我想知道您是否可以为更高精度的处理指定确切的实际任务。 @asd-tm 不是关于类型精度,而是关于转换。扩展的四舍五入到整数会导致结果发生重大变化。我正在使用您的代码从 timage 中获取一个矩形,结果与裁剪区域不同,矩形区域的变化大于比例。【参考方案2】:另一种方法:
var
Tmp: TBitmap;
Bmp: TBitmap;
iRect: TRect;
begin
Tmp := TBitmap.Create;
Tmp := Image1.MakeScreenshot; //ignore the scale, so will F*ck the resolution, but resolve the scale issues
Bmp := TBitmap.Create;
try
Bmp.Width := round(Rectangle1.Width);
Bmp.Height := round(Rectangle1.Height);
iRect.Left := round(Rectangle1.Position.X);
iRect.Top := round(Rectangle1.Position.Y);
iRect.Width := round(Rectangle1.Width);
iRect.Height := round(Rectangle1.Height);
Bmp.CopyFromBitmap(tmp, iRect, 0, 0);
Image2.Bitmap := Bmp
finally
Tmp.Free;
Bmp.Free;
end;
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于如何使用firemonkey在选定区域裁剪位图?的主要内容,如果未能解决你的问题,请参考以下文章