为啥我尝试裁剪位图时出现空白 TImage?

Posted

技术标签:

【中文标题】为啥我尝试裁剪位图时出现空白 TImage?【英文标题】:Why there is blank TImage when I try to crop the bitmap?为什么我尝试裁剪位图时出现空白 TImage? 【发布时间】:2018-11-25 17:53:24 【问题描述】:

我已按照此答案裁剪图像: how do I crop a bitmap “in place”?

在 delphi 7 中,我有一个 TImage Image_center。

Image := TPngObject.Create;
try
  Image.LoadFromStream(Stream);
  Image_center.Picture.Graphic := Image;
  Image_center.width := Image.width;
  Image_center.height := Image.height;
  Image_center.Left := ( form1.clientWidth div 2 ) - (Image_center.width div 2);
  CropBitmap(Image_center.Picture.Bitmap, 1, 45,   Image.width, Image.height-45);
finally
  Image.Free;
end;

但结果是 TImage 包含白色位图。如果我跳过/注释掉 CropBitmap 函数,那么我可以看到图像。所以加载没有问题。为什么我看到的是白色区域而不是图像?

procedure CropBitmap(InBitmap : TBitmap; X, Y, W, H :Integer);
begin
  BitBlt(InBitmap.Canvas.Handle, 0, 0, W, H, InBitmap.Canvas.Handle, X, Y, SRCCOPY);
  InBitmap.Width :=W;
  InBitmap.Height:=H;
end;

Delphi 7 位图方法:

In TBitmap

~TBitmap
            Assign
            Create
            Destroy
            Dormant
            FreeImage
            HandleAllocated

LoadFromClipboardFormat
            LoadFromResourceID
            LoadFromResourceName
            LoadFromStream
            Mask
            ReleaseHandle

ReleaseMaskHandle
            ReleasePalette
            SaveToClipboardFormat
            SaveToStream
            TBitmap

Derived from TGraphic

LoadFromFile
            SaveToFile

Derived from TInterfacedPersistent

AfterConstruction
            QueryInterface

Derived from TPersistent

GetNamePath

Derived from TObject

BeforeDestruction
            ClassInfo
            ClassName
            ClassNameIs
            ClassParent
            ClassType
            CleanupInstance

DefaultHandler
            Dispatch
            FieldAddress
            Free
            FreeInstance
            GetInterface
            GetInterfaceEntry

GetInterfaceTable
            InheritsFrom
            InitInstance
            InstanceSize
            MethodAddress
            MethodName
            NewInstance

SafeCallException

【问题讨论】:

因为Image_centerBitmap属性一直是空的!您将其分配为TPngObject,它不会神奇地转换为位图。当您引用Image_center.Bitmap 时,您无意中也删除了.png 图像。正如我在对您上一个问题的评论中所说,首先将图像加载到TBitmap(可以是Image_center.Bitmap,然后(overpaint 或)BitBlt 直接加载到Image_center.Bitmap 我不清楚如何将 PNG 图像加载到 TImage 位图。我认为 Vcl.Graphics.TPicture.LoadFromStream 无法理解 png 类型,因为我使用的是 D7 Image.AssignTo(Image_center.Picture.Bitmap) 谢谢,但我在 Delphi 7 中没有 AssignTo 这个功能。 Image_center.Picture.Bitmap.Canvas.Brush.Color := ???; Image_center.Picture.Bitmap.SetSize(Image.Width, Image.Height); Image.Draw(Image_center.Picture.Bitmap.Canvas, Rect(0, 0, Image.Width, Image.Height)); 【参考方案1】:

您(错误地)假设Image_center.Picture.Bitmap 会将图片作为位图提供给您。仅当它是位图时才如此,否则它将用空位图覆盖您的图形。

相反,您可以在位图上绘制您的 PNG 图像,例如:

with Image_center.Picture.Bitmap do
begin
  Width := Image.Width;
  Height := Image.Height;
  Canvas.Draw(0,0, Image);
end;

之后,您可以使用Image_center.Picture.GraphicImage_center.Picture.Bitmap 中的位图来做任何您想做的事情。

但请记住,这样一来,您将失去在 PNG 图像中的任何透明度,并且恢复它并非易事,尽管如果您阅读 How to get bitmap transparancy without the need to paint first? 可能会这样做。

【讨论】:

以上是关于为啥我尝试裁剪位图时出现空白 TImage?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用firemonkey在选定区域裁剪位图?

尝试通过 WCF 传递位图时出现“System.ServiceModel.CommunicationException”

BitmapRegionDecode.decodeRegion,尝试从位图创建图块时出现skia错误

从 C++ 中的屏幕选择创建位图时出现黑色图像

调整位图的大小,保持宽高比,不会出现失真和裁剪

在 AsyncTack 中加载位图时出现问题