Delphi - 如何在原位裁剪位图?

9
如果我有一个TBitmap,想要从这个位图中获取裁剪后的图像,能否在原位进行裁剪操作?例如,如果我有一个800x600的位图,如何缩小(裁剪)它,使其包含中心的600x400图像,即生成的TBitmap是600x400,并由原始图像中(100,100)和(700,500)所限定的矩形组成?
需要通过另一个位图吗,还是可以在原始位图内完成这个操作?
2个回答

24
你可以使用BitBlt函数。
尝试这段代码。
procedure CropBitmap(InBitmap, OutBitMap : TBitmap; X, Y, W, H :Integer);
begin
  OutBitMap.PixelFormat := InBitmap.PixelFormat;
  OutBitMap.Width  := W;
  OutBitMap.Height := H;
  BitBlt(OutBitMap.Canvas.Handle, 0, 0, W, H, InBitmap.Canvas.Handle, X, Y, SRCCOPY);
end;

你可以这样使用

Var
  Bmp : TBitmap;
begin
  Bmp:=TBitmap.Create;
  try
    CropBitmap(Image1.Picture.Bitmap, Bmp, 10,0, 150, 150);
    //do something with the cropped image
    //Bmp.SaveToFile('Foo.bmp');
  finally
   Bmp.Free;
  end;
end;

如果您想使用相同的位图,请尝试此函数的版本。
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;

以这种方式使用

Var
 Bmp : TBitmap;
begin
    Bmp:=Image1.Picture.Bitmap;
    CropBitmap(Bmp, 10,0, 150, 150);
    //do somehting with the Bmp
    Image1.Picture.Assign(Bmp);
end;

谢谢。有没有简单的方法可以在不需要第二个位图的情况下完成这个任务?就像Delphi中的“Move”例程处理重叠源和目标一样,是否有一个二维等效的例程呢? - rossmcm
你可以使用TBitmap的ScanLine属性和Move方法,但是你需要根据BitsPerPixel计算像素的字节大小。 - Stijn Sanders
检查第二个选项,它仅使用一个位图。 - RRUZ
第一个变量与OP想要的无关(并且只是浪费内存,因为BitBlt在操作期间保留光栅数据)。 - OnTheFly
1
第一个版本是在提问者编辑问题之前编写的。 - RRUZ
@RRUZ,“原地”子句一直存在。 - OnTheFly

4

我知道你已经有了接受的答案,但是因为我写了我的版本(使用VCL包装器而不是GDI调用),所以我会在这里发布它,而不是把它扔掉。

procedure TForm1.FormClick(Sender: TObject);
var
  Source, Dest: TRect;
begin
  Source := Image1.Picture.Bitmap.Canvas.ClipRect;
  { desired rectangle obtained by collapsing the original one by 2*2 times }
  InflateRect(Source, -(Image1.Picture.Bitmap.Width div 4), -(Image1.Picture.Bitmap.Height div 4));
  Dest := Source;
  OffsetRect(Dest, -Dest.Left, -Dest.Top);
  { NB: raster data is preserved during the operation, so there is not need to have 2 bitmaps }
  Image1.Picture.Bitmap.Canvas.CopyRect(Dest, Image1.Picture.Bitmap.Canvas, Source);
  { and finally "truncate" the canvas }
  Image1.Picture.Bitmap.Width := Dest.Right;
  Image1.Picture.Bitmap.Height := Dest.Bottom;
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接