2012-02-07 38 views
8

Nếu tôi có một TBitmap và tôi muốn có được một hình ảnh được cắt từ bitmap này, tôi có thể thực hiện thao tác cắt xén "tại chỗ" không? ví dụ. nếu tôi có bitmap là 800x600, làm cách nào tôi có thể giảm (cắt) nó sao cho nó chứa hình ảnh 600x400 ở giữa, tức là kết quả TBitmap là 600x400 và bao gồm hình chữ nhật được bao quanh bởi (100, 100) và (700) , 500) trong hình ảnh gốc?Delphi - làm thế nào để cắt một bitmap "tại chỗ"?

Tôi có cần phải đi qua một bitmap khác hoặc thao tác này có thể được thực hiện trong bitmap gốc không?

Trả lời

20

Bạn có thể sử dụng chức năng BitBlt

thử mã này.

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; 

và bạn có thể sử dụng theo cách này

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; 

Nếu bạn muốn sử dụng bitmap tương tự, hãy thử phiên bản này của hàm

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; 

Và sử dụng theo cách này

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

Cảm ơn điều đó. Có cách nào đơn giản để hoàn thành việc này mà không cần bitmap thứ hai không? Trong cùng một cách như thường lệ 'Move' trong Delphi xử lý nguồn chồng chéo và đích, có tương đương hai chiều không? – rossmcm

+0

Bạn có thể sử dụng Di chuyển với thuộc tính ScanLine của TBitmap nhưng bạn sẽ phải tính toán kích thước byte của pixel tùy thuộc vào BitsPerPixel –

+0

kiểm tra tùy chọn thứ hai chỉ sử dụng một bitmap. – RRUZ

4

Tôi biết bạn có chấp nhận câu trả lời đã có, nhưng kể từ khi tôi đã viết phiên bản của tôi (trong đó sử dụng wrapper VCL thay vì cuộc gọi GDI), tôi sẽ đăng nó ở đây thay vì chỉ ném nó đi.

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; 
Các vấn đề liên quan