Einzelnen Beitrag anzeigen

Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.537 Beiträge
 
Delphi 11 Alexandria
 
#12

AW: Tparallel und Bitmap-Bearbeitung

  Alt 19. Nov 2014, 18:37
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.

Geändert von Harry Stahl (19. Nov 2014 um 19:06 Uhr)
  Mit Zitat antworten Zitat