AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Seltsames Grafik-Phänomen - oder wie ich lernte, DELPHI zu "lieben"...
Thema durchsuchen
Ansicht
Themen-Optionen

Seltsames Grafik-Phänomen - oder wie ich lernte, DELPHI zu "lieben"...

Ein Thema von hathor · begonnen am 30. Jan 2015 · letzter Beitrag vom 1. Feb 2015
Antwort Antwort
hathor
(Gast)

n/a Beiträge
 
#1

Seltsames Grafik-Phänomen - oder wie ich lernte, DELPHI zu "lieben"...

  Alt 30. Jan 2015, 17:14
Seltsames Grafik-Phänomen - oder wie ich lernte, DELPHI zu "lieben"...

Eine kleine Grafik soll 80 x kopiert werden.
Das dauert etwa 12 sec auf meinem Notebook.
Wenn die fertige Grafik gelöscht wird mit FloodFill, dann dauert der Neu-Aufbau nur etwa 3 sec.

Hat jemand eine Erklärung dafür?

Im Anhang ist die EXE:
Bedienung:
Start: baut die Grafik auf
CheckBox SpeedUp beschleunigt den Grafik-Aufbau.
Reset: löscht die Grafik

Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    ProgressBar1: TProgressBar;
    Button3: TButton;
    Memo1: TMemo;
    cbSpeedUp: TCheckBox;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure TerminatedProc(Sender:TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormShow(Sender: TObject);

  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

   type
      TCopyThread = Class(TThread)
      private
        FPoint:TPoint;
        procedure UpdateProgressBar;
      protected
        procedure Execute;Override;
      public
        Constructor Create(p:TPoint);
      End;

var
  Form1: TForm1;
  CopyThread:TCopyThread;
  BitMap1 : TBitMap;
  GTC1, GTC2 : Cardinal;

implementation

{$R *.dfm}

procedure MM(s:string); begin Form1.Memo1.Lines.Add(s); end;

procedure TForm1.Button1Click(Sender: TObject);
var p:TPoint;
begin
if Button1.Tag=1 then Button3.Click; Button1.Tag:= 1;
if cbSpeedUp.Checked then
BEGIN
  Self.Canvas.FloodFill(ClientWidth div 2, ClientHeight div 2, clBlack, fsBorder);
  Self.Canvas.Draw(0,0,BitMap1);
END;

GTC1:= GetTickCount;
  p.X:= BitMap1.Width;
  P.Y:= 0;
  CopyThread:=TCopyThread.Create(p);
  CopyThread.OnTerminate:= TerminatedProc;
  ProgressBar1.Max:= BitMap1.Width*80 * BitMap1.Height;
  ProgressBar1.Position:= 0;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin if Assigned(CopyThread) then begin CopyThread.Terminate; end; end;

procedure TForm1.Button3Click(Sender: TObject);
var MyWindow : cardinal;
begin
  ProgressBar1.Position:= 0;
  Form1.WindowState:= wsMinimized;
  Sleep(100);
  MyWindow := FindWindow( Nil, PWIDECHAR('GRAFIKDEMO-201501'));
  If MyWindow <> 0 Then
  Begin
    ShowWindow(MyWindow, SW_Normal);
    SetForeGroundWindow(MyWindow);
  End;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin BitMap1:= TBitmap.Create; BitMap1.LoadFromFile('BG_Kacheln1.bmp'); end;

procedure TForm1.FormDestroy(Sender: TObject); begin BitMap1.Free; end;

procedure TForm1.FormPaint(Sender: TObject);
begin Self.Canvas.Draw(0,0,BitMap1); end;

procedure TForm1.FormShow(Sender: TObject);
begin Application.Title := 'GRAFIKDEMO-201501'; end;

procedure TForm1.TerminatedProc;
begin
GTC2:= GetTickCount;
MM(' Dauer: '+ INTTOSTR(GTC2-GTC1)+' ms');
Sleep(100); WinApi.Windows.Beep(1800,100);
end;

{ TCopyThread }
constructor TCopyThread.Create(p: TPoint);
begin FPoint:=p; inherited Create(False); end;

procedure TCopyThread.Execute;
var
  i,j:Integer;
  dot:TColorRef;
  DC:HDC;
begin
  FreeOnTerminate:=True;
  DC:=GetDC(Form1.Handle);
  for i := 0 to BitMap1.Width * 80 - 1 do
    for j := 0 to BitMap1.Height - 1 do
      if not Terminated then
         begin
           dot:=GetPixel(DC,i,j);
           SetPixel(DC,i + FPoint.X,j + FPoint.Y,dot);
           Synchronize(UpdateProgressBar);
         end;
end;

procedure TCopyThread.UpdateProgressBar;
begin Form1.ProgressBar1.Position:= Form1.ProgressBar1.Position +1; end;

end.
Angehängte Dateien
Dateityp: zip GRAFIKCOPY.zip (599,8 KB, 8x aufgerufen)

Geändert von hathor (30. Jan 2015 um 21:56 Uhr)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#2

AW: Seltsam - oder wie ich lernte, DELPHI zu "lieben"...

  Alt 30. Jan 2015, 17:32
Sind GetPixel() und SetPixel() nicht am Ende das gleiche wie TCanvas.Pixels[]? Warum kopierst du nicht "ordentlich" mit BitBlt()? Und warum der Thread, der zudem auch noch auf einem nicht gelockten Canvas/DC rumhantiert? (Deinen Code-Style finde ich persölich auch eher zum weglaufen, schwer zu lesen.)

Edit: Noch etwas: Du setzt die Progressbar im Thread für JEDEN Pixel neu. Das frisst UNMENGEN Zeit.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium (30. Jan 2015 um 17:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: Seltsam - oder wie ich lernte, DELPHI zu "lieben"...

  Alt 30. Jan 2015, 17:37
Hallo,

Also abgesehen davon dass dein Code so wie du ihn formatierst absolut unlesbar ist und ich mir nicht sicher bin ob ich dein Problem richtig verstanden habe:

Natürlich ist ein Canvas.Draw tausend mal schneller als ein Thread (der in dem Fall ziemlich unnötig und auch durch den Zugriff auf Form1.Handle potenziell gefährlich ist) in dem GetPixel und SetPixel benutzt wird (die mit Abstand langsamsten Funktionen wenn es um das auslesen/setzen von Pixeln geht).
Ach ja und das Synchronize ist wie Medium auch schon gesagt hat wahrscheinlich nochmal für 30-50% Geschwindigkeitsverlust verantwortlich.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#4

AW: Seltsam - oder wie ich lernte, DELPHI zu "lieben"...

  Alt 30. Jan 2015, 17:45
Ohne Synchronize(UpdateProgressBar); ist der Geschwindigkeitsunterschied noch größer: 10 sec zu 1 sec...

Aber bisher habe ich keine Erklärung dafür, dass ein FloodFill so eine Auswirkung hat!
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#5

AW: Seltsames Grafik-Phänomen - oder wie ich lernte, DELPHI zu "lieben"...

  Alt 31. Jan 2015, 13:32
Hat es auch nicht. Bei mir:
Zitat:
Dauer: 3588 ms
Dauer: 3635 ms
Dauer: 3651 ms
Dauer: 3635 ms
Die ersten 2 Durchläufe ohne Speedup, die letzten beiden mit.

Aber das alles wird komplett bedeutungslos, wenn du das Zeichnen mit vernünftigen Methoden machst, und diesen Thread inkl. der Progressbar los wirst.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.197 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Seltsames Grafik-Phänomen - oder wie ich lernte, DELPHI zu "lieben"...

  Alt 31. Jan 2015, 13:59
Windows ist kein Echtzeit-OS. Und wenn du dein Thread geschätzt 1 Mio. mal jeweils nach 1 ns unterbrichst kann hier jegliche Windows-Aktion (Virenscanner wird aktualisiert. Festplattendefraktmentierung startet, ...) dafür sorgen das die Zeiten sehr weit streuen. Vermutlich wird ein entsprechend ungünstig implementiertes .NET/Java-Programm genau die gleichen Zeiten liefern.

Also bau erstmal dein Programm um (Bessere Zugriffsfunktionen auf Zeichenfläche von Bitmap, kein tausendfaches Synchronize, ...) und schau dann ob diese Streuung noch auftritt.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Seltsames Grafik-Phänomen - oder wie ich lernte, DELPHI zu "lieben"...

  Alt 1. Feb 2015, 12:59
Bevor ich eine Teilaufgabe in einen Thread auslagere mache ich mir Gedanken darüber, wie das in der Realität aussehen würde.

Statt Threads nehme ich dann einfach Mitarbeiter.
Statt einem Pixel nehme ich einen Kieselstein.

Der Mitarbeiter soll also einen ganzen Haufen Kieselsteine von A nach B bewegen.

Möchte ich wirklich, dass der bei jedem einzelnen Kieselstein bei mir vorbeikommt und mich persönlich (Sychronize) informiert, dass er einen weiteren Kieselstein bewegt hat?
Er könnte mir ja auch eine Nachricht hinterlassen (Queue) die ich mir dann bei nächster Gelegenheit anschaue.

Aber will ich wirklich über jeden einzelnen eine Nachricht habe? Oder würden mir ein paar Rückmeldungen auch reichen (alle 10% Fortschritt)?

Wenn man das so durchspielt, dann weiß man, wo man selbst und der Mitarbeiter gestresst/gehemmt ist und das trifft exakt auf die GUI und den Thread zu. Das zusammen mit einer umständlichen Arbeitsweise (GetPixel) bringt jedes System in die Knie.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:21 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz