2012-02-07 9 views
8

Se si dispone di una TBitmap e si desidera ottenere un'immagine ritagliata da questa bitmap, è possibile eseguire l'operazione di ritaglio "in posizione"? per esempio. se ho una bitmap che è 800x600, come posso ridurla (ritagliarla) in modo che contenga l'immagine 600x400 al centro, cioè la TBitmap risultante è 600x400 e consiste nel rettangolo delimitato da (100, 100) e (700 , 500) nell'immagine originale?Delphi: come ritagliare una bitmap "in posizione"?

Devo passare tramite un'altra bitmap o questa operazione può essere eseguita all'interno della bitmap originale?

risposta

20

È possibile utilizzare la funzione

BitBlt provare questo codice.

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; 

ed è possibile utilizzare in questo modo

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; 

Se si desidera utilizzare la stessa bitmap, provare questa versione della funzione

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; 

e utilizzare in questo modo

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

Grazie per quello. C'è un modo semplice per realizzare questo senza aver bisogno di una seconda bitmap? Nello stesso modo in cui la routine 'Move' in Delphi gestisce sorgenti e destinazioni sovrapposte, esiste un equivalente bidimensionale? – rossmcm

+0

È possibile utilizzare Sposta con la proprietà ScanLine di TBitmap, ma è necessario calcolare la dimensione in byte dei pixel in base a BitsPerPixel –

+0

, selezionare la seconda opzione che utilizza solo una bitmap. – RRUZ

4

so che hai il tuo risposta accettata già, ma da quando ho scritto la mia versione (che usa wrapper VCL al posto della chiamata GDI), la posterò qui invece di buttarla via.

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; 
Problemi correlati