Danke für Eure Antworten!
... Soweit ich mich erinnere, kann man aber auch ein Bild von Grau in Schwarz-Weiß umwandeln, indem man die Helligkeitsstufe festlegt, ab welcher das jeweilige Pixel weiß sein soll. Da würde ich mal ansetzen.
Dieser letzte Satz hat mich auf die - aus meiner Sicht - richtige Fährte geschickt. Für mich habe ich das Problem gelöst.
Zunächst habe ich das Bild nach schwarz/weiß umgewandelt. Mein nächster Ansatz war es dann, die schwarzen Pixel zu zählen. Anschließend habe ich diese mit den weißen ins Verhältnis gesetzt und ab einem Wert von 3 ‰ (Promille) das Bild als Bild mit Inhalt deklariert. Allerdings war das sehr fehlerbehaftet. Denn es gibt nicht nur Staub, Falten etc., sondern dann auch schwarze Ränder und - überholter Beitrag - schwarze Löscher.
Also schneide ich jetzt die Ränder innerhalb bestimmter Grenzen ab. Anschließend zähle ich die Anzahl der schwarzen Pixel. Wenn diese einen absoluten Wert überschreiten, ist es kein leeres Bild mehr. Das beschleunigt sogar die Suche, weil ich dann die Procedure verlassen kann.
Hier mein Code fürs Protokoll:
Delphi-Quellcode:
// Leeres Bild erkennen --------------------------------------------------------
// MaxBlack ist die Anzahl maximal zulässiger schwarzer Pixel.
// Beim Scannen können schwarze Ränder, Staubkörner etc. auftreten. Um ein
// möglichst genaues Ergebnis zu erzielen werden zuerst die Ränder abge-
// schnitten und dann die Anzahl der dunkeln/schwarzen Pixel ermittelt.
// Der Wert selbst dürfte hardwareabhängig sein und kann deshalb als Variable
// übergeben werden.
Function TScanForm.PictureIsEmpty(Const BitMap: TBitmap;
Const MaxBlack: Integer = 75): Boolean;
Const
lMargin = 12; // linker Rand
rMargin = 8; // rechter Rand
bMargin = 4; // unterer Rand
tMargin = 8; // oberer Rand
Tolerance = 118; // guter Schwarz-Wert
Var
lWidth : Integer;
lHeight : Integer;
lBlack : Int64;
I, J : Integer;
lLine :^TRGBTriple;
Begin
Result:=True; // ausgehen von leerem Bild
lWidth:= BitMap.Width - lMargin - rMargin; // maximale Breite
lHeight:=BitMap.Height - tMargin - bMargin; // maximale Höhe
BitBlt(Bitmap.Canvas.Handle, 0, 0, lWidth, lHeight,
Bitmap.Canvas.Handle, lMargin, tMargin, SRCCOPY);
BitMap.Width :=lWidth;
BitMap.Height:=lHeight;
If (Bitmap.PixelFormat <> pf24bit) Then
Bitmap.PixelFormat := pf24bit; // wegen Scanline
lBlack:=0; // schwarze Pixel
For I:=0 To Pred(Bitmap.Height) Do // alle Zeilen durchgehen
Begin
lLine:=Bitmap.Scanline[I]; // Zeile zuweisen
For J:=0 To Pred(Bitmap.Width) Do // Zeile abarbeiten
Begin
If (lLine^.rgbtred + lLine^.rgbtBlue +
lLine^.rgbtgreen) Div 3 < Tolerance Then
Inc(lBlack); // = dunkler Wert -> schwarz
If (lBlack >= MaxBlack) Then // viele schwarze Pixel
Begin
Result:=False; // = Bild mit Inhalt
// Exit; // Zeit sparen!!!
End;
Inc(lLine); // nächste Zeile durchsuchen
End;
End;
// TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TE
fList.Append(IntToStr(fCount) + ';' + IntToStr(BitMap.Height * BitMap.Width) +
';' + IntToStr(lBlack));
// TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TE
End;