Scanline: Ist das auch wirklich ein 32-Bit-Bitmap?
Scanline kannst Du auch mit einem 24-Bit-Bitmap verwenden, Du musst halt nur berücksichtigen, dass hier auf 3 Bit gezeigt wird (bei 32-Bit auf 4 Bit).
Und gleichzeitig frage dich, ob es gut ist, wenn man bei einer parallelen Bearbeitung überall den Bezugspunkt einfach so verschiebt Inc(Ziel); Inc(Quelle);
.
OK, in einem Thread ist das wirklich keine gute Idee.
Ich versuche mal einen anderen Ansatz, das mit TTask zu beschleunigen, also einmal den oberen Teil der Bitmap berechnen, dann den unteren Teil, beides halt (fast) gleichzeitig. Da ich in den jeweiligen Threads nur lokale Variablen verwende und auf das zu verändernde Bitmap auf unterschiedliche Bereiche zugreife, dürften doch eigentlich keine Konflikte entstehen, oder?
Dennoch bekommen ich eine Zugriffsverletzung, wenn ich auch den 2. Task starte. Die einzelnen Tasks selber Funktionieren, wenn man nur einen startet, dann macht er, was er soll.
Wo könnte denn jetzt hier der Fehler liegen?
Hier der Source-Code:
Delphi-Quellcode:
H1 := Bitmap.Height
div 2;
// obere Hälfte der Bitmap
H2 := H1+1;
// Startpunkt für die untere Hälfte
SetLength(myTasks, 2);
// Task 1 verändert die obere Hälfte des Bitmaps
myTasks[0] := TTask.Create(
procedure ()
var
Ziel, Quelle : ^TRGBTriple;
x, y: Integer; OK: Boolean;
begin
for y := 0
to H1
do begin
Ziel := Bitmap.Scanline[y];
Quelle := Original.Scanline[y];
for x := 0
to (Bitmap.Width-1)
do begin
if IgnoreWhite
then begin
OK := (Quelle^.rgbtBlue <> 255)
or (Quelle^.rgbtGreen <> 255)
or (Ziel^.rgbtGreen <> 255);
end else begin
OK := True;
end;
if OK
then begin
Ziel^.rgbtBlue := ar[Quelle^.rgbtBlue];
Ziel^.rgbtred := ar[Quelle^.rgbtred];
Ziel^.rgbtGreen := ar[Quelle^.rgbtGreen];
end;
inc(Ziel);
inc(Quelle);
end;
end;
end
);
myTasks[0].Start;
// Task 2 verändert die untere Hälfte des Bitmaps
myTasks[1] := TTask.Create(
procedure ()
var
Ziel, Quelle : ^TRGBTriple;
x, y: Integer; OK: Boolean;
begin
for y := H2
to Bitmap.height-1
do begin
Ziel := Bitmap.Scanline[y];
Quelle := Original.Scanline[y];
for x := 0
to (Bitmap.Width-1)
do begin
if IgnoreWhite
then begin
OK := (Quelle^.rgbtBlue <> 255)
or (Quelle^.rgbtGreen <> 255)
or (Ziel^.rgbtGreen <> 255);
//<-- Hier kommt eine Access-Violation
end else begin
OK := True;
end;
if OK
then begin
Ziel^.rgbtBlue := ar[Quelle^.rgbtBlue];
Ziel^.rgbtred := ar[Quelle^.rgbtred];
Ziel^.rgbtGreen := ar[Quelle^.rgbtGreen];
end;
inc(Ziel);
inc(Quelle);
end;
end;
end
);
myTasks[1].Start;
TTask.WaitForAll(myTasks);
Nachtrag: Manchmal läuft es ohne
Access-Verletzung durch. Gemessen braucht es dann bei einem 3872 x 2592 Pixel großem Bitmap nur ca. 123 MS, während ohne Parallele Bearbeitung es ca. 185 MS dauert. Wäre also schon eine hilfreiche Beschleunigung, wenn man das stabil hinbekommen könnte.