Autor Beitrag
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 30.07.15 23:41 
Hallo,
user profile iconuser32 hat folgendes geschrieben Zum zitierten Posting springen:
Aha. Bitmap Optimierung. Hat mich jemand gerufen? ;]
Folgende Version ist um den Faktor 100 (Hundert) schneller.

Ich bin ehrlich gesagt fasziniert. Wie geht denn so etwas? 100fach schneller. :!:
Vielen, vielen Dank!
Ich habe es gerade getestet: Deine Lösung ermöglicht ja sogar in Echtzeit die waagerechte bzw. senkrechte Verschiebung des Mittelpunktes, d.h. die Kugel kann man drehen! :D

Darf ich dich für weitere Programme "anstellen"? :mrgreen:

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1652
Erhaltene Danke: 243

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Fr 31.07.15 08:04 
Hallo,

jau, das jede Zeile das Bild neu gezeichnet wird ist suboptimal...
Das es bei 960 Zeilen nur 100 mal schneller wird ist erstaunlicher ;-), wieso ist mir das nicht aufgefallen?
Ich habe das Program unter wine laufen und habe access violation:
capture29363

Gruß Horst
P.S:
Unter Win7 habe ich keine Fehler..
Ich habe keine Verbesserung gefunden, obwohl ich keine Unterschiede zwischen single und double habe ( Turbo Delphi ).es dauert bei mir 0.01265 Sekunden pro Bildberechnung.Die Ausgabe auf die Paintbox ist nicht drin.
Für wine/Lazarus musste ich ExtractFilePath nutzen, weil er sonst die Bilder nicht findet.Aber dabei hatte ich kein umgerechnetes Bild.Scanline will da nicht so recht.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
procedure TForm1.Button1Click(Sender: TObject);
var
    bitmap,bitmap2,bitmapz:tbitmap;
    T1,T0 : TDatetime;
    rect:trect;
    P : PByteArray;
    p2: ^byte;
    p3,px: ^byte;

    i,j,n,k,waagerecht,senkrecht,bmw:integer;
    xm,ym:integer;
    bbinv,
    xk,yk,q,xi,yi,sq:single;

procedure ladejpg(const FileName: String; Bild: TBitMap);
var Jpeg: TJpegImage;
begin
  Jpeg:=TJpegImage.Create;
  jpeg.LoadFromFile(filename);
  Bild.Assign(Jpeg);
  jpeg.free;
end;
begin

   ladejpg(ExtractFilePath(application.ExeName)+combobox1.text+'.jpg',image1.Picture.Bitmap);
   application.ProcessMessages;

   //Verschiebung des Spiegelsmittelpunkts
   waagerecht:=bb;
   senkrecht:=bb;

   bitmap2:=tbitmap.create;
   bitmap2.assign(image1.Picture.Bitmap);
   bitmap2.PixelFormat:=pf32bit;

   bitmap:=tbitmap.Create;
   bitmap.width:=bb;
   bitmap.height:=bb;
   //Abbildung auf doppelte Größe strecken
   rect.left:=0;
   rect.Top:=0;
   rect.right:=bb;
   rect.Bottom:=bb;
   bitmap.canvas.copyrect(rect,bitmap2.Canvas,image1.clientrect);
   //Mittelpunkt
   xm:=paintbox1.Width div 2;
   ym:=paintbox1.height div 2;

   bitmapz:=tbitmap.Create;
   bmw :=paintbox1.Width;
   bitmapz.Width:= bmw;
   bitmapz.height:=paintbox1.height;
   bitmapz.PixelFormat:=pf32bit;

   bitmapz.Canvas.Brush.Color:=clwhite;
   bitmapz.Canvas.Rectangle(-1,-1,961,961);
   //version 2
   //zeilenweise pixel ermitteln
   bbinv := 1/bb;
   T0 := now;
For n := 1 to runden do
Begin
   P2 := BitMap.ScanLine[0];
   P3 := bitmapz.ScanLine[0];

   for i:=0 to bb-1 do begin
     yi:=(2*i-senkrecht)*bbinv;  //yi:=(2*i-senkrecht)/bb;
     for j:=0 to bb-1 do begin
           //Umwandeln in komplexe Koordinaten
           xi:=(2*j-waagerecht)*bbinv;
           //Transformation auf die Riemann-Kugel
           sq := xi*xi + yi*yi;
           //nur zeichnen, wenn in unterer Hälfte der Riemann-Kugel
           if sq<1.0 then begin
             q:=480/(sq+1.0);
             px := p3;
             dword(px) := dword(px) -((trunc(yi*q)+ym)*bmw + trunc(xi*q)+xm)*4;
             pDword(px)^ :=  pDword(p2)^;
{           //fuer pf24Bit mal als Gedanke
             k := pDword(p2)^ AND $00FFFFFF;
             pDword(px)^ := pDword(px)^ AND $FF000000 OR k;
}

           end;
           inc(p2,4);
     end;
     dec(p2, 8*bitmap.Width);
   end;
End;
   T1 := now;
   paintbox1.Canvas.Draw(0,0,bitmapz);

   bitmap.free;
   bitmap2.free;
   bitmapz.free;
   Label1.Caption := Format('%10.5f',[(T1-T0)/n*86400.0]);
end;
Einloggen, um Attachments anzusehen!
user32
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 55
Erhaltene Danke: 5



BeitragVerfasst: Fr 31.07.15 18:40 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,
user profile iconuser32 hat folgendes geschrieben Zum zitierten Posting springen:
Aha. Bitmap Optimierung. Hat mich jemand gerufen? ;]
Folgende Version ist um den Faktor 100 (Hundert) schneller.

Ich bin ehrlich gesagt fasziniert. Wie geht denn so etwas? 100fach schneller. :!:
Vielen, vielen Dank!
Ich habe es gerade getestet: Deine Lösung ermöglicht ja sogar in Echtzeit die waagerechte bzw. senkrechte Verschiebung des Mittelpunktes, d.h. die Kugel kann man drehen! :D

Darf ich dich für weitere Programme "anstellen"? :mrgreen:

Beste Grüße
Mathematiker


Sicher, wenn ich helfen kann immer gerne :tongue:
Wobei ich mich selbst noch als Optimierungs-Newbie sehe..

Joa, Canvas-Funktionen wie LineTo oder Pixels, sind sehr einfach und praktisch, aber bei Software Rendering kann man es echt vergessen.
Einzelnd aufgerufen okay, aber sobald eine Schleife dabei ist....


user profile iconHorst_H hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,

jau, das jede Zeile das Bild neu gezeichnet wird ist suboptimal...
Das es bei 960 Zeilen nur 100 mal schneller wird ist erstaunlicher ;-), wieso ist mir das nicht aufgefallen?
Ich habe das Program unter wine laufen und habe access violation:
[Bild: capture29363]

Gruß Horst
P.S:
Unter Win7 habe ich keine Fehler..
Ich habe keine Verbesserung gefunden, obwohl ich keine Unterschiede zwischen single und double habe ( Turbo Delphi ).es dauert bei mir 0.01265 Sekunden pro Bildberechnung.Die Ausgabe auf die Paintbox ist nicht drin.
Für wine/Lazarus musste ich ExtractFilePath nutzen, weil er sonst die Bilder nicht findet.Aber dabei hatte ich kein umgerechnetes Bild.Scanline will da nicht so recht.

Du meinst Lazarus kennt nicht Single/Double? :shock: Oder nur keinen Geschwindigkeitsunterschied gemessen?
Ich vermute das kommt wohl auf den Compiler an.
Bei mir läuft das ursprüngliche Programm, alleine durch Umstellen auf Single, ca 33% schneller.
Deswegen hab ich auch Sachen wie sq() gegen x*x getauscht, weil diese Funktionen meistens mit Extended rechnen und zudem ja noch zusätzlich eine externe Funktion aufgerufen wird.
Würde mich mal interessieren, ob wenn du die FPU manuell auf 32-bit setzt, das immer noch gleich schnell ist.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1652
Erhaltene Danke: 243

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Fr 31.07.15 23:52 
Hallo,

natürlich kennt Lazarus wie Turbo Delphi single und double.
Es ändert das Tempo bei mir nicht.
Das ich kein Bild unter Linux/wine bekomme liegt einfach nur am geänderten Aufbau der Bitmaps.
Unter Windows ist die oberste Zeile 0 im hohen Speicherbereich und die anderen kommen im Speicher davor.
Man wandert von Zeile zu Zeile zu kleineren Speicheradressen.
Unter Linux ist es genau andersherum.
Zeile 0 ist oben auf dem Bildschirm und die niedrigste Postion im Speicher und man wandert im Speicher zu höheren Adressen.
Deshalb stimmt die Bestimmung von px nicht mehr, weil die Zeilen jetzt falsch berechnet werden zudem von der falschen Startposition.Das gibt nur deshalb nicht immer eine Zugriffsverletzung, weil das Bitmap das davor erzeugt ist auch oft genau davor liegt und völlig überschrieben wird, was keiner sieht, es wird ja nicht zur Anzeige gebracht.

Gruß Horst
user32
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 55
Erhaltene Danke: 5



BeitragVerfasst: Sa 01.08.15 04:05 
Moderiert von user profile iconNarses: Komplettzitat des vorigen Beitrags entfernt.

Ja, stimmt. Ich wusste garnicht, dass es bei Linux anders ist. Naja, man könnte sagen Linux hat es richtig gemacht und Microsoft falsch :)
Aber wenn du die Pointer Adressen umstellst, sollte es bei Linux ja dann auch gehen.
SMO
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 120
Erhaltene Danke: 18


D2005 Personal
BeitragVerfasst: So 02.08.15 01:45 
user profile iconHorst_H hat folgendes geschrieben Zum zitierten Posting springen:
bekomme liegt einfach nur am geänderten Aufbau der Bitmaps.
Unter Windows ist die oberste Zeile 0 im hohen Speicherbereich und die anderen kommen im Speicher davor.
Man wandert von Zeile zu Zeile zu kleineren Speicheradressen.
Unter Linux ist es genau andersherum.


Stimmt, unter Windows sind Bitmaps gewöhnlich "bottom-up". Aber man kann auch "top-down" Bitmaps anlegen, dafür muss man einfach eine negative Höhe angeben. Delphis TBitmap Kapselung unterstützt das allerdings nicht, d.h. man müsste die Windows-API direkt benutzen.
Wenn man ordentlich programmiert, dann ist der Speicheraufbau von Bitmaps eigentlich irrelevant. Entweder ruft man für jede Zeile TBitmap.Scanline auf um den passenden Pointer zu bekommen, oder man ermittelt initial den "Pitch" (Schrittweite von einer Scanline zur nächsten, im Fall von Windows eben ein negativer Wert) und addiert ihn nach jeder Zeile auf den aktuellen Scanline-Pointer.