【问题标题】:Delphi - how do I crop a bitmap "in place"?Delphi - 如何“就地”裁剪位图?
【发布时间】:2012-02-29 07:26:20
【问题描述】:

如果我有一个 TBitmap 并且我想从这个位图中获得一个裁剪的图像,我可以“就地”执行裁剪操作吗?例如如果我有一个 800x600 的位图,我如何缩小(裁剪)它以使其在中心包含 600x400 图像,即生成的 TBitmap 为 600x400,并由 (100, 100) 和 (700) 包围的矩形组成, 500) 在原始图像中?

我需要通过另一个位图还是可以在原始位图中完成此操作?

【问题讨论】:

    标签: delphi bitmap crop tbitmap


    【解决方案1】:

    你可以使用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 例程处理重叠源和目标的方式相同,是否存在二维等价物?
    • 您可以将 Move 与 TBitmap 的 ScanLine 属性一起使用,但您必须根据 BitsPerPixel 计算像素的字节大小
    • 勾选第二个选项,它只使用一个位图。
    • 第一个变体与 OP 想要的无关(而且只是浪费内存,因为 BitBlt 在操作期间会保留光栅数据)
    • 第一个版本是在 OP 编辑​​他的问题之前编写的。
    【解决方案2】:

    我知道您已经接受了答案,但是由于我编写了我的版本(它使用 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;
    

    【讨论】:

      猜你喜欢
      • 2015-05-05
      • 2019-05-10
      • 2013-08-16
      • 2015-12-11
      • 2013-03-25
      • 2017-10-19
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多