2012-05-10 21 views
10

Ich muss ein Close-Crop-Rechteck für eine Bitmap von einem bestimmten Hintergrundfarbschlüssel berechnen. Auf den folgenden Bildern können Sie sehen, was als Nahkultur gedacht ist. Auf der linken Seite befindet sich auf der rechten Seite Ausgang der Nähe Ernte der Quelle:Wie berechne ich das Nahfeld einer Bitmap?

enter image description here

enter image description here

Wie Sie sehen können, muss ich die oberste, ganz links, untersten und äußersten rechten Pixel finden die sich farblich vom Hintergrund unterscheiden, um das Close-Crop-Rechteck zu erstellen. Also, wie finde ich diese unterschiedlichen äußeren Pixel, um das Nahausschnittrechteck zu erhalten? Oder, mit anderen Worten, wie berechnet man das Close-Crop-Rechteck einer Bitmap?

+0

ich versucht habe, eine Mischung aus Code von einigen Antworten David mir vor kurzem geholfen: http: // Stackoverflow. com/questions/10503428/resize-the-canvas-around-a-bitmap und http://stackoverflow.com/questions/10499069/moving-bitmap-pixels Ich dachte, ich könnte es verstehen, aber nicht wirklich. Ich sollte in der Lage sein, die ResizeBitmapCanvas-Prozedur anzupassen, um dies zu tun, aber ich konnte nicht, ich werde leicht verwirrt. –

+0

@Blobby Eine Möglichkeit, dies zu tun ist, von jeder Seite der Bitmap aus zu beginnen und die Loop-Variable zu dekrementieren, bis Sie ein Pixel finden, das sich von der Hintergrundfarbe unterscheidet. Wiederholen Sie den Vorgang für jede Seite und voila, Sie haben ein Auto-Cropping-Werkzeug – ComputerSaysNo

+0

@Dorin, du kannst es in einem 'ScanLine' Durchlauf tun, du musst dich nur an die Grenzen erinnern ;-) – TLama

Antwort

11

Sie können diesen Code verwenden (Sie können den commented version dieses Beitrags als auch folgen):

procedure CalcCloseCrop(ABitmap: TBitmap; const ABackColor: TColor; 
    out ACropRect: TRect); 
var 
    X: Integer; 
    Y: Integer; 
    Color: TColor; 
    Pixel: PRGBTriple; 
    RowClean: Boolean; 
    LastClean: Boolean; 
begin 
    if ABitmap.PixelFormat <> pf24bit then 
    raise Exception.Create('Incorrect bit depth, bitmap must be 24-bit!'); 

    LastClean := False; 
    ACropRect := Rect(ABitmap.Width, ABitmap.Height, 0, 0); 

    for Y := 0 to ABitmap.Height-1 do 
    begin 
    RowClean := True; 
    Pixel := ABitmap.ScanLine[Y]; 
    for X := 0 to ABitmap.Width - 1 do 
    begin 
     Color := RGB(Pixel.rgbtRed, Pixel.rgbtGreen, Pixel.rgbtBlue); 
     if Color <> ABackColor then 
     begin 
     RowClean := False; 
     if X < ACropRect.Left then 
      ACropRect.Left := X; 
     if X + 1 > ACropRect.Right then 
      ACropRect.Right := X + 1; 
     end; 
     Inc(Pixel); 
    end; 

    if not RowClean then 
    begin 
     if not LastClean then 
     begin 
     LastClean := True; 
     ACropRect.Top := Y; 
     end; 
     if Y + 1 > ACropRect.Bottom then 
     ACropRect.Bottom := Y + 1; 
    end; 
    end; 

    if ACropRect.IsEmpty then 
    begin 
    if ACropRect.Left = ABitmap.Width then 
     ACropRect.Left := 0; 
    if ACropRect.Top = ABitmap.Height then 
     ACropRect.Top := 0; 
    if ACropRect.Right = 0 then 
     ACropRect.Right := ABitmap.Width; 
    if ACropRect.Bottom = 0 then 
     ACropRect.Bottom := ABitmap.Height; 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    R: TRect; 
    Bitmap: TBitmap; 
begin 
    CalcCloseCrop(Image1.Picture.Bitmap, $00FFA749, R); 
    Bitmap := TBitmap.Create; 
    try 
    Bitmap.SetSize(R.Width, R.Height); 
    Bitmap.Canvas.CopyRect(Rect(0, 0, R.Width, R.Height), Image1.Canvas, R); 
    Image1.Picture.Bitmap.Assign(Bitmap); 
    finally 
    Bitmap.Free; 
    end; 
end; 
+3

+1 gute Arbeit Mann! – ComputerSaysNo

+0

Excellent stuff TLama, keine Anerkennung weg von diesem;) Ich wünschte nur, ich könnte nicht nur Ihre Antwort verstehen, aber viele andere. EDIT: die Pixel auf einer Bitmap, sind sie von einer unsichtbaren Box (Bounding Box) umgeben, wie ich ursprünglich dachte? Wenn ja, wird dies mit Rect gefunden? –

+0

Ich werde versuchen, dies zu kommentieren, aber nach einer Überprüfung. Über die unsichtbare Box meinst du irgendeinen leeren Raum um das beschnittene Bild, richtig? Ich füge etwas hinzu, aber was ist, wenn das erste (Nicht-Hintergrund-) Pixel auf der Position [0; 0] ist, möchten Sie es hinter der Bildgröße erweitern und diesen äußeren Raum mit ABackColor füllen? – TLama

Verwandte Themen