为什么 CopyRect 在 delphi 10.3 中翻转了第二张图片?
Why did CopyRect Flipped the second image in delphi 10.3?
我想对我的页面进行截图并将结果放入位图中,因为页面上有一个滚动条,我必须多次截图,我想合并这些位图。
如果使用此代码截屏并保存:
我使用代码从这个页面合并它们 http://www.delphigroups.info/2/8/309463.html
如果我直接复制它,将导致使用第一个图像,而我使用白色矩形作为第二个。所以我试着稍微改变一下,现在我将两张图片放在一个文件中。
这是我用来连接位图的代码:
function ConcatenateBitmaps(const MainBitmap: TBitmap; const BitmapToAdd:
TBitmap): TBitmap;
begin
Result := MainBitmap;
If BitmapToAdd.Width > MainBitmap.Width then
Result.Width := BitmapToAdd.Width;
Result.Height := MainBitmap.Height + MainBitmap.Height;
Result.Canvas.CopyRect(
Rect(0,MainBitmap.Height,BitmapToAdd.Width,BitmapToAdd.Height),
BitmapToAdd.Canvas,
Rect(0,0,BitmapToAdd.Width,BitmapToAdd.Height)
);
end;
问题是第二张图片被垂直和水平翻转了;
我做错了什么?
编辑:
结果的一个例子,第一张图不错,第二张图翻转了:
现在看来,我的描述是错误的,水平镜像,垂直翻转
原因和快速修复:
问题出在这部分:
Rect(0,MainBitmap.Height,BitmapToAdd.Width,BitmapToAdd.Height)
您制作了一个矩形,其中 top
是生成图像的总高度,底部是要添加的位图的高度。所以这个矩形基本上是倒置的(底部在顶部上方)。
它也可能变形了,因为这个矩形的高度不是要添加的位图的高度。
快速修复是:
Rect(0,Result.Height- BitmapToAdd.Height,BitmapToAdd.Width,Result.Height)
其他问题和困惑:
但我认为造成您混淆的原因是您认为 Result 和 MainBitmap 是两个不同的位图,而实际上它们都是对同一位图的引用。您在开始时所做的分配只是复制引用,而不是实际的 TBitmap 对象。
此外,您混淆了 'height' 和 'bottom'。 TRect 希望您设置顶部和底部坐标,而不是顶部和高度。这一点,连同上一个问题,不仅导致位图倒置,而且会被拉伸,部分覆盖之前的图像。添加的图片越多,效果越明显。
我个人认为在这种情况下修改现有位图的效率更高,主要是因为否则您将不得不一直清理旧位图,而且您有一个神奇地创建位图的函数。您会遇到位图对象的所有权问题,随之而来的是内存泄漏的风险,这并不好,尤其是在处理大型位图时。
我建议的版本:
因此,我只想将其作为一个过程,其中通过向其中添加第二个位图来修改第一个位图。
在下面的版本中,我还使用了Canvas.ClipRect
,这是针对位图的,本质上是位图的外接矩形。然后我使用 OffsetRect
到 'move' 这个矩形(增加它的顶部 Y 和底部 Y)。
通过在单独的变量中执行此操作,与我上面提供的快速修复相比,您可以获得一个相对干净的版本,因为您可以在实际修改 MainBitmap 之前使用它的尺寸。
procedure AppendBitmap(const MainBitmap: TBitmap; const BitmapToAdd:
TBitmap);
var
TargetRect: TRect;
begin
// Widen the main bitmap if needed
if BitmapToAdd.Width > MainBitmap.Width then
MainBitmap.Width := BitmapToAdd.Width;
// Set TargetRect to the right size
TargetRect := BitmapToAdd.Canvas.ClipRect;
// And then to the right position
OffsetRect(TargetRect, 0, MainBitmap.Height);
// Make room for the bitmap to add
MainBitmap.Height := MainBitmap.Height + BitmapToAdd.Height;
// Draw it in the created space
MainBitmap.Canvas.CopyRect(
TargetRect,
BitmapToAdd.Canvas,
BitmapToAdd.Canvas.ClipRect
);
end;
如果愿意,您可以使用原始签名创建一个包装函数,创建主图像和 returns 的副本。不过请注意,MainBitmap 和此函数的结果不再是同一个位图,您必须确保在完成后正确释放它们。
function ConcatenateBitmaps(const MainBitmap: TBitmap; const BitmapToAdd:
TBitmap): TBitmap;
begin
Result := TBitmap.Create;
Result.Assign(MainBitmap);
AppendBitmap(Result, BitmapToAdd);
end;
PS:我喜欢这样的问题,我从中学到了一些东西。我从未意识到您可以通过翻转传递给 CopyRect 的矩形来翻转图像。 :D
我想对我的页面进行截图并将结果放入位图中,因为页面上有一个滚动条,我必须多次截图,我想合并这些位图。
如果使用此代码截屏并保存:
我使用代码从这个页面合并它们 http://www.delphigroups.info/2/8/309463.html
如果我直接复制它,将导致使用第一个图像,而我使用白色矩形作为第二个。所以我试着稍微改变一下,现在我将两张图片放在一个文件中。
这是我用来连接位图的代码:
function ConcatenateBitmaps(const MainBitmap: TBitmap; const BitmapToAdd:
TBitmap): TBitmap;
begin
Result := MainBitmap;
If BitmapToAdd.Width > MainBitmap.Width then
Result.Width := BitmapToAdd.Width;
Result.Height := MainBitmap.Height + MainBitmap.Height;
Result.Canvas.CopyRect(
Rect(0,MainBitmap.Height,BitmapToAdd.Width,BitmapToAdd.Height),
BitmapToAdd.Canvas,
Rect(0,0,BitmapToAdd.Width,BitmapToAdd.Height)
);
end;
问题是第二张图片被垂直和水平翻转了;
我做错了什么?
编辑:
结果的一个例子,第一张图不错,第二张图翻转了:
现在看来,我的描述是错误的,水平镜像,垂直翻转
原因和快速修复:
问题出在这部分:
Rect(0,MainBitmap.Height,BitmapToAdd.Width,BitmapToAdd.Height)
您制作了一个矩形,其中 top
是生成图像的总高度,底部是要添加的位图的高度。所以这个矩形基本上是倒置的(底部在顶部上方)。
它也可能变形了,因为这个矩形的高度不是要添加的位图的高度。
快速修复是:
Rect(0,Result.Height- BitmapToAdd.Height,BitmapToAdd.Width,Result.Height)
其他问题和困惑:
但我认为造成您混淆的原因是您认为 Result 和 MainBitmap 是两个不同的位图,而实际上它们都是对同一位图的引用。您在开始时所做的分配只是复制引用,而不是实际的 TBitmap 对象。
此外,您混淆了 'height' 和 'bottom'。 TRect 希望您设置顶部和底部坐标,而不是顶部和高度。这一点,连同上一个问题,不仅导致位图倒置,而且会被拉伸,部分覆盖之前的图像。添加的图片越多,效果越明显。
我个人认为在这种情况下修改现有位图的效率更高,主要是因为否则您将不得不一直清理旧位图,而且您有一个神奇地创建位图的函数。您会遇到位图对象的所有权问题,随之而来的是内存泄漏的风险,这并不好,尤其是在处理大型位图时。
我建议的版本:
因此,我只想将其作为一个过程,其中通过向其中添加第二个位图来修改第一个位图。
在下面的版本中,我还使用了Canvas.ClipRect
,这是针对位图的,本质上是位图的外接矩形。然后我使用 OffsetRect
到 'move' 这个矩形(增加它的顶部 Y 和底部 Y)。
通过在单独的变量中执行此操作,与我上面提供的快速修复相比,您可以获得一个相对干净的版本,因为您可以在实际修改 MainBitmap 之前使用它的尺寸。
procedure AppendBitmap(const MainBitmap: TBitmap; const BitmapToAdd:
TBitmap);
var
TargetRect: TRect;
begin
// Widen the main bitmap if needed
if BitmapToAdd.Width > MainBitmap.Width then
MainBitmap.Width := BitmapToAdd.Width;
// Set TargetRect to the right size
TargetRect := BitmapToAdd.Canvas.ClipRect;
// And then to the right position
OffsetRect(TargetRect, 0, MainBitmap.Height);
// Make room for the bitmap to add
MainBitmap.Height := MainBitmap.Height + BitmapToAdd.Height;
// Draw it in the created space
MainBitmap.Canvas.CopyRect(
TargetRect,
BitmapToAdd.Canvas,
BitmapToAdd.Canvas.ClipRect
);
end;
如果愿意,您可以使用原始签名创建一个包装函数,创建主图像和 returns 的副本。不过请注意,MainBitmap 和此函数的结果不再是同一个位图,您必须确保在完成后正确释放它们。
function ConcatenateBitmaps(const MainBitmap: TBitmap; const BitmapToAdd:
TBitmap): TBitmap;
begin
Result := TBitmap.Create;
Result.Assign(MainBitmap);
AppendBitmap(Result, BitmapToAdd);
end;
PS:我喜欢这样的问题,我从中学到了一些东西。我从未意识到您可以通过翻转传递给 CopyRect 的矩形来翻转图像。 :D