Autor Beitrag
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 05.09.10 15:07 
user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Btw. Du kannst mit einem einzigen Scanline Aufruf auf das gesamte Bitmap zugreifen. Musst einfach auf die Ränder aufpassen, und ob die Bitmap verkehrt rum im Speicher liegt.
:nixweiss:

1x Scanline für ganzes Bild.
ausblenden 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:
procedure TForm1.Button1Click(Sender: TObject);
const
  N = 256;
var
  X, Y: Integer;
  Bitmap: TBitmap;
  Base, Pixel: PCardinal;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.Width := N;
    Bitmap.Height := N;
    Bitmap.PixelFormat := pf32bit;
    // Get base pointer for bitmap
    Base := Bitmap.ScanLine[Bitmap.Height - 1]; 

    for X := 0 to N - 1 do
      for Y := 0 to N - 1 do
      begin
        Pixel := Base;
        Inc(Pixel, X + Y * N); // Should use BytesPerScanline for other pixelformats
        Pixel^ := Integer((X and Y) > 0) * $FFFFFF// The Image
      end;

    Image1.Picture.Bitmap.Assign(Bitmap); // Assign to Image
  finally
    Bitmap.Free;
  end;
end;


Zuletzt bearbeitet von delfiphan am So 05.09.10 15:33, insgesamt 1-mal bearbeitet

Für diesen Beitrag haben gedankt: Tilman
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: So 05.09.10 15:33 
und wenn du die 2 schleifen tauschst kommst du mit einem Inc(Pixel) aus
dann sparst du dir die multiplikation, da deine variante schon fast langsamer ist, als ein ständiger scanline aufruf.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 05.09.10 15:35 
Mir ging es oben nicht darum, optimierten Code zu zeigen. Das X + Y * N wär überhaupt nicht nötig, da der Pointer bei jedem Durchlauf sowieso nur 4 hochzählt. Ich wollte aber andeuten, dass man eigentlich mit BytesPerScanline arbeiten sollte, wenn man andere Pixelformats verwendet.
Folgendes würde für den Fall oben reichen:
ausblenden Delphi-Quelltext
1:
2:
  Base^ := Integer((X and Y) > 0) * $FFFFFF// The Image
  Inc(Base);


Aber bei mir läuft das sowieso in 0.1ms durch. Da noch weiter zu optimieren wäre reine Zeitverschwendung. Wenn die Performance so wichtig ist, würde ich dann doch auf Hardwarebeschleunigung zurückgreifen, da kriegst du den Gradienten geschenkt.
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: So 05.09.10 16:09 
Und ich wollte drauf hinweisen, dass scanline nicht viel mehr macht, als eine multiplikation und einen speicherzugriff. also soviel wie dein code auch.
dein letzter post stimmt nicht: du müsstest noch die x und y schleife vertauschen.
gut bei nem quadrat ist das egal, aber vom prinzip.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 05.09.10 16:11 
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Und ich wollte drauf hinweisen, dass scanline nicht viel mehr macht, als eine multiplikation und einen speicherzugriff. also soviel wie dein code auch.
dein letzter post stimmt nicht: du müsstest noch die x und y schleife vertauschen.
gut bei nem quadrat ist das egal, aber vom prinzip.

Richtig, das müsste man noch ändern.
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: So 05.09.10 16:11 
Zitat:
ausblenden Delphi-Quelltext
1:
Base := Bitmap.ScanLine[Bitmap.Height - 1];					

*mist*e! Habe gerade völlig unabhängig vom TE dieses Problem gehabt (ich will eine Textur in OpenGL laden), und gleichzeitig wird hier die Lösung gepostet! :o

Meine Lösung auf die ich nach längerer Suche gekommen war sah so aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
   var
      bm: tBitmap;
      buffer: windows.BITMAP;
  begin
    bm := tBitmap.Create;
    [..]
    getObject(bm.Handle,sizeof(buffer),@buffer);
    // und buffer.bmBits enthält dann den Zeiger auf die Pixeldaten

Dazu stellt sich mir die Frage, warum 1. scanline verkehrt herum läuft, und 2. die Funktion nicht gut dokumentiert ist. Denn scanline[0] hatte ich natürlich als erstes probiert :?

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: So 05.09.10 16:14 
ähm...scanline läuft richtig rum:
von 0,0->0,1->0,2...->0,h

deine lösung sollte im zugriff langsamer sein. und vermutlich musst du das auch wieder freigeben. bin nicht ganz sicher.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 05.09.10 16:15 
Wieso, weiss ich nicht genau aber vermutlich war das für gewisse Fälle schneller. Man google nach "bottom-up dib".

Wenn man die Art des Bitmaps nicht genau kennt, sollte man ScanLine verwenden. Es berücksichtigt die Alignment am Rand und bottom-up vs. top-down. Wenn man das Bitmap kennt, kann man sich die Fallunterscheidungen sparen. Ein grosser Geschwindigkeitsunterschied wird das aber tatsächlich nicht machen.


Zuletzt bearbeitet von delfiphan am So 05.09.10 16:17, insgesamt 1-mal bearbeitet
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: So 05.09.10 16:15 
Scanline läuft richtig rum; allerdings werden Bitmaps im Speicher von Unten nach Oben abgelegt, daher die umgekehrte Zeilenzählung.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1085
Erhaltene Danke: 53

WinXP, Win7, Win10
Delphi 7 Enterprise, XE
BeitragVerfasst: So 05.09.10 16:17 
So ich versuch mal wieder zu Antworten was ich alles gemacht habe!
Bevor ihr euch die besten Ideen untereinander erklärt :rofl: und ich evtl gar nix mehr verstehe!

@delfiphan: Was mache ich aber mit der StartFarbe. Bei Dir würde es mit schwarz beginnen und in weiss enden. Wenn ich es richtig sehe, und wie dann mit der 2.bitmap. Das OpenGL/DirectX besser sind ist auch mir klar! Nur ist es auch ne Zeit und verstehen frage. Siehst Doch selbst wie lange ich nur für so ein bischen brauche :P

@Flamefire: Deine Funktioniert, nur muss man nicht mit 0 Anfangen sondern mit
ausblenden Delphi-Quelltext
1:
pl:= peakbufl.ScanLine[peakbufl.Height-1];					

und die For schleife dann rückwärts laufen lassen!
So wie es bei Dir steht kommt es zum peng schon nach dem 2. Durchlauf! Getestet :wink:
Jedenfalls bei mir! Allerdings wüsste ich jetzt nicht wie ich in der gleichen Forschleife die 2.bitmap mit der Farbe fülle und zwar entgegengesetzt!
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
was meinst du nun mit invertieren?
da die Farben der unteren Bitmap andersrum sind als oben?
jo das meinte ich!

Bin aber auch an @BenBE Idee dran. Nur muss ich erst mal wieder verstehen was er mit SizeOf(PixelRGB) meint/hernimmt :?

Anbei weis ich immer noch nicht was man hier evtl noch machen kann!
ausblenden Delphi-Quelltext
1:
2:
3:
r:= trunc(102+ (255 - 102) / peakbufl.Height *ypos);
g:= trunc(113+ (255 - 113) / peakbufl.Height *ypos);
b:= trunc(126+ (255 - 126) / peakbufl.Height *ypos);


Gruss Alf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: So 05.09.10 16:20 
Okay ihr habt natürlich völlig recht, nur stellt sich um so mehr die Frage warum in meinen Ausgaben der Hilfe (Delphi 7 und Delphi 2006) kein Pieps davon erwähnt wird, das Scanline[height-1] die gesamten Pixeldaten liefert. Hätte mir ne Stunde rumgesuche erspart ^^

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 05.09.10 16:21 
Mein Code löst weder das Gescheindigkeitsproblem noch generiert es einen Gradienten. Es zeigt lediglich, dass es reicht, 1x Scanline aufzurufen. ;)

---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

user profile iconTilman hat folgendes geschrieben Zum zitierten Posting springen:
Okay ihr habt natürlich völlig recht, nur stellt sich um so mehr die Frage warum in meinen Ausgaben der Hilfe (Delphi 7 und Delphi 2006) kein Pieps davon erwähnt wird, das Scanline[height-1] die gesamten Pixeldaten liefert. Hätte mir ne Stunde rumgesuche erspart ^^

Das muss auch nicht zwingend so sein (du kannst auch theoretisch ein top-bottom dib mit TBitmap betreiben). Das ganze benötigt aber Systemwissen und ist nicht wirklich ein Delphi-Feature, daher auch nicht so dokumentiert, denk ich mal.

// Sorry, Mods, bitte Posts zusammenführen, falls erwünscht.
elundril
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3747
Erhaltene Danke: 123

Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
BeitragVerfasst: So 05.09.10 16:30 
user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:

Anbei weis ich immer noch nicht was man hier evtl noch machen kann!
ausblenden Delphi-Quelltext
1:
2:
3:
r:= trunc(102+ (255 - 102) / peakbufl.Height *ypos);
g:= trunc(113+ (255 - 113) / peakbufl.Height *ypos);
b:= trunc(126+ (255 - 126) / peakbufl.Height *ypos);


Gruss Alf


Spart vielleicht nicht viel Zeit aber machts kürzer und schöner:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
nenner := peakbufl * ypos;
r := trunc(102 + (153 / nenner));
g := trunc(113 + (142 / nenner));
b := trunc(126 + (129 / nenner));


lg elundril

_________________
This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: So 05.09.10 16:56 
ausblenden Delphi-Quelltext
1:
2:
3:
r:= trunc(102+ (255 - 102) / peakbufl.Height *ypos);
g:= trunc(113+ (255 - 113) / peakbufl.Height *ypos);
b:= trunc(126+ (255 - 126) / peakbufl.Height *ypos);

eher zu:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
factor:=ypos/peakbufl.Height;
r:= trunc(102+ (255 - 102) *factor);
g:= trunc(113+ (255 - 113) *factor);
b:= trunc(126+ (255 - 126) *factor);


möglichkeit wäre noch 3 arrays[0..height] zu erzeugen (bei resize) und dort die werte schon zu berechnen (als fertiger RBG-Wert)
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 05.09.10 16:59 
Wenn Geschwindigkeit, dann mit Integers rechnen.
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1085
Erhaltene Danke: 53

WinXP, Win7, Win10
Delphi 7 Enterprise, XE
BeitragVerfasst: So 05.09.10 17:02 
user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
Spart vielleicht nicht viel Zeit aber machts kürzer und schöner:
ausblenden Delphi-Quelltext
1:
2:
nenner := peakbufl * ypos;
r := trunc(102 + (153 / nenner));//<----kommt es hier nicht zu EZeroDivide ;)


user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Wenn Geschwindigkeit, dann mit Integers rechnen.

Hab ich schon gemacht funct mit der Farbe nicht!

Gruss ALf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: So 05.09.10 17:14 
integer gehen wirklich nicht.
und dein fehler kommt vom abschreiben...erst denken ;-)
oder nimm meins. da ist dasschon gefixt
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1085
Erhaltene Danke: 53

WinXP, Win7, Win10
Delphi 7 Enterprise, XE
BeitragVerfasst: So 05.09.10 17:19 
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
und dein fehler kommt vom abschreiben...erst denken ;-)

hab nicht abgeschrieben, weil ich selbst schon versucht hatte das hübscher zu machen und den gleichen Fehler gemacht habe :P
Gruss Alf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 05.09.10 17:46 
user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
integer gehen wirklich nicht.

Du musst einfach zuerst multiplizieren, dann dividieren.
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1085
Erhaltene Danke: 53

WinXP, Win7, Win10
Delphi 7 Enterprise, XE
BeitragVerfasst: So 05.09.10 18:48 
Bei aller Diskusion wurde vergessen wie ich es machen kann das ich, wenn ich schon nur mit 1*scanline arbeite, die Farbe nun für die 2.Bitmap verändern kann? Meine Versuche haben ja nix gebracht!
@BenBE Vorschlag bekomme ich auch nicht gebacken :( .Währe ja auch ne überlegung wert.
Gruss ALf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!