Brauche mal Hilfe zum WritePixelFast-Befehl
Übersicht

![]() |
TravisBetreff: Brauche mal Hilfe zum WritePixelFast-Befehl |
![]() Antworten mit Zitat ![]() |
---|---|---|
Dieser Befehl treibt mich noch zum Wahnsinn. Er ist zwar tausend mal schneller als Plot, aber auch mindestens genauso viel komplizierter.
Ich habe mal versucht ein BitMap auf dem Bildschirm explodieren zu lassen, d.h. es zerspringt in einzelne Pixel. Mit Plot funktioniert alles wunderbar, ist aber natürlich zu langsam. Jetzt habe ich das ganze auf WritePixelFast umgestellt und nun gibt es jedes mal eine "Memory access violation", sobald mehrere Pixel den Bildschirm verlassen. Außerdem werden die Funktionen, die die Pixel löschen sollen, sobald sie den Bildschirm verlassen offenbar außer Kraft gesetzt und die Pixel tauchen dann auf der anderen Seite wieder auf. Hier mal die Codes. Zuerst die Fehlerfreie Plot-Version: Code: [AUSKLAPPEN] InputFile$ = ("Explosion.bmp") Graphics 1024, 768, 16, 1 SetBuffer BackBuffer() ; --- Bilddatei laden Datei = ReadFile(InputFile$) SeekFile Datei, 18 ; Pos für Breite in Pixeln ResX = ReadShort(Datei) SeekFile Datei, 22 ; Pos für Höhe in Pixeln ResY = ReadShort(Datei) Rest = (ResX Mod 4): If Rest = 4 Then Rest = 0 ; Restbytes bis zur teilbarkeit durch 4 Type Pixel Field blue, green, red, x#, y#, speed#, winkel# End Type SeekFile Datei, 54 ; Leseposition auf Anfang der Bildinfos setzen For x = ResY To 1 Step -1 For y = 1 To ResX p.pixel = New pixel p\blue = ReadByte(Datei) p\green = ReadByte(Datei) p\red = ReadByte(Datei) p\x# = x p\y# = y p\winkel# = Rnd(0,359) p\speed# = Rnd(4,9) Next SeekFile(Datei, FilePos(Datei) + Rest) ; Zeilenende suchen Next CloseFile Datei BildY = 384 BildX = 412 ; --- Bild anzeigen For p.pixel = Each pixel Color p\red, p\green, p\blue If Not p\red = 248 And p\green = 0 And p\blue = 248 Then ; Transparentfarbe Plot p\y# + BildX, p\x# + BildY EndIf Next Flip Delay 1000 Repeat Cls ; --- Bild anzeigen For p.pixel = Each pixel Color p\red, p\green, p\blue If Not p\red = 248 And p\green = 0 And p\blue = 248 Then ; Transparentfarbe Plot p\y# + BildX, p\x# + BildY EndIf Next ; --- Bild zerstreuen For p.pixel = Each pixel p\x# = p\x# + Cos(p\Winkel#) * p\speed# p\y# = p\y# + Sin(p\Winkel#) * p\speed# Next ; --- Verlorene Pixel löschen For p.pixel = Each pixel If p\x > 1024 Or p\x < 0 Then Delete p: Exit If p\y > 768 Or p\y < 0 Then Delete p: Exit Next Flip Until KeyHit(1) Und jetzt die fehlerhafte WritePixelFast-Version: Code: [AUSKLAPPEN] InputFile$ = ("Explosion.bmp") Graphics 1024, 768, 16, 1 SetBuffer BackBuffer() ; --- Bilddatei laden Datei = ReadFile(InputFile$) SeekFile Datei, 18 ; Pos für Breite in Pixeln ResX = ReadShort(Datei) SeekFile Datei, 22 ; Pos für Höhe in Pixeln ResY = ReadShort(Datei) Rest = (ResX Mod 4): If Rest = 4 Then Rest = 0 ; Restbytes bis zur teilbarkeit durch 4 Type Pixel Field blue, green, red, x#, y#, speed#, winkel# End Type SeekFile Datei, 54 ; Leseposition auf Anfang der Bildinfos setzen For x = ResY To 1 Step -1 For y = 1 To ResX p.pixel = New pixel p\blue = ReadByte(Datei) p\green = ReadByte(Datei) p\red = ReadByte(Datei) p\x# = x p\y# = y p\winkel# = Rnd(0,359) p\speed# = Rnd(4,9) Next SeekFile(Datei, FilePos(Datei) + Rest) ; Zeilenende suchen Next CloseFile Datei BildY = 384 BildX = 412 ; --- Bild anzeigen LockBuffer BackBuffer() For p.pixel = Each pixel Color p\red, p\green, p\blue If Not p\red = 248 And p\green = 0 And p\blue = 248 Then ; Transparentfarbe Pixelfarbe=255*$1000000 + p\red*$10000 + p\green*$100 + p\blue WritePixelFast(p\y+BildX, p\x+BildY, Pixelfarbe) EndIf Next UnlockBuffer BackBuffer() Flip Delay 1000 Repeat Cls ; --- Verlorene Pixel löschen For p.pixel = Each pixel If p\x# > 1024 Then Delete p: Exit If p\y# > 768 Delete p: Exit If p\x# < 0 Then Delete p: Exit If p\y# < 0 Then Delete p: Exit Next ; --- Bild anzeigen LockBuffer BackBuffer() For p.pixel = Each pixel Color p\red, p\green, p\blue If Not p\red = 248 And p\green = 0 And p\blue = 248 Then ; Transparentfarbe Pixelfarbe=255*$1000000 + p\red*$10000 + p\green*$100 + p\blue WritePixelFast(p\y+BildX, p\x+BildY, Pixelfarbe) EndIf Next UnlockBuffer BackBuffer() ; --- Bild zerstreuen For p.pixel = Each pixel p\x# = p\x# + Cos(p\Winkel#) * p\speed# p\y# = p\y# + Sin(p\Winkel#) * p\speed# Next Flip Until KeyHit(1) Das Bild wird zuerst fehlerfrei dargestellt, bleibt 1000ms bestehen und explodiert dann, wie gewollt. Sobald aber einige Pixel den Bildschirm verlassen (und ungewollter weise auf der Gegenseite wieder erscheinen anstatt gelöscht zu werden) gibt's ne Memory access violation. |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
![]() |
Vertex |
![]() Antworten mit Zitat ![]() |
---|---|---|
Du musst bei WritePixelFast immer auf die Größe achten.
Wenn man ein Image mit 100 * 100 Pixel hat darf man nur von X(0-99),Y(0-99) schreiben, alles was darüber ist X(>99),Y(>99) wird ohne Fehlerüberprüfung weiter in den Speicher gespiechert. Deswegen setzt er mal die Pixel auf die nächste Seite, oder bei mir ist es oft so, das der Mauspointer unter Windows noch welche Pixel mit dran gehangen bekommt. Also Regionen beachten! Da Blitz z.Z. nicht läuft, kann ich das jetzt leider nicht testen. mfg olli |
||
vertex.dreamfall.at | GitHub |
![]() |
Travis |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich verstehe momentan nicht, was du meinst. Mein Testbild ist 288 x 32 Pixel groß. Ich habe das jetzt so verstanden, daß die X/Y-Werte nicht größer sein sollten, wie die Bildbreite/höhe. ![]() Der Fehler tritt immer in folgender Zeile auf: WritePixelFast(p\y+BildX, p\x+BildY, Pixelfarbe) Was mich irritiert ist, das die Pixel, wenn sie z.B. rechts den Bildschirm verlassen, links wieder auftauchen. Das habe ich doch gar nicht einprogrammiert! Die sollen doch gelöscht werden. |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
![]() |
Mr.Keks |
![]() Antworten mit Zitat ![]() |
---|---|---|
Travis hat Folgendes geschrieben: Was mich irritiert ist, das die Pixel, wenn sie z.B. rechts den Bildschirm verlassen, links wieder auftauchen. Das habe ich doch gar nicht einprogrammiert! Die sollen doch gelöscht werden. wenn sie rechts rausgehen, tauchen sie eine zeile weiter unten links wieder auf. das liegt einfach daran, dass die pixel in folgender reihenfolge gespeichert werden:
1,2,3 4,5,6 7,8,9 wenn jetzt also ein pixel in reihe 1 (bei zählweise 0,1,2...) an der 4. position gespeichert werden soll, rechnet bb: 3 pixel pro reihe, und vierte position. also reihe*pixelproreihe+pixelinreihe = stelle, an der der pixel im speicher landen soll. in diesem fall: 1*3+4 = 7 -> der pixel landet in der nächsten reihe. wenn du unterhalb oder oberhalb zeichnest, sind es speicherpositionen, die eigentlich anderen bildern oder dateien gehören. unter umständen zeichnest du dann auch in dinge, in die man besser nicht zeichnen sollte ![]() |
||
MrKeks.net |
![]() |
Travis |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hmpf. Ich sag's ja, der Befehl treibt mich noch zum Wahnsinn. Erst dieses blöde Farbystem und dann Das. Da werde ich mich jetzt nicht weiter drin vertiefen. ![]() |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
![]() |
TheShadowModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
RGB-Berechnung ist gut in Hilfe dokumentiert - und wenn pixel rechts hingehen und links rauskommen, dann hast du definitiv fehler gemacht und außerhalb des images gezeichnet... Normalerweise ist ein PC-Absturz bei solcher Vorgehensweise garantiert | ||
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2 |
![]() |
Travis |
![]() Antworten mit Zitat ![]() |
---|---|---|
Außerhalb des Images? Ist damit der Bildschirm gemeint? Normalerweise können die Pixel aber doch die Bildschirmgrenze nicht überschreiten, weil ich sie vorher lösche.
Code: [AUSKLAPPEN] For p.pixel = Each pixel If p\x > 1024 Or p\x < 0 Then Delete p: Exit If p\y > 768 Or p\y < 0 Then Delete p: Exit Next Diese Befehle werden aber einfach ignoriert. Selbst, wenn ich einen kleineren Bereich angebe z.B. ein Feld von 320x240 in Bildschirmmitte, bewegen sich die Pixel einfach drüber weg. |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
![]() |
HolzchopfMeisterpacker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Natürlich kommt der Fehler nur, wenn ausserhalb des Bildschirms gezeichnet wird, aber beim Zeichnen addierst du ja zu den Koordinaten noch BildX und BildY, beim prüfen jedoch nicht.
Ausserdem hat das Exit in der Abfrage dazu geführt, dass immer höchstens ein Punkt gelöscht wurde, dabei konnten ja mehrere gleichzeitig aus dem Bildschirm treten. Ich hab noch ein paar Sachen geändert: - Bei der Schlaufe, die das bild einliest, hast du x und y vertauscht (bild wurde 90° gedreht eingelesen). - Bei den ReadPixel und WritePixel befehlen hast du zuerst p\y + bildX und p\x + bildY geschrieben, also X und Y Koordinate der Punkte vertauscht (was sich mit dem X und Y vertauschen vom einlesen ergänzen würde) Dadurch, dass du p\y als X Koordinate brauchst, und p\x als Y Koordinate, stimmt die Abfrage dann auch nichtmehr, du prüfst dann theoretisch Y auf einen bereich von 0 - 1024 statt X, ausserdem geht der Bereich nur von 0 - 1023, der Y Bereich nur von 0 - 767. Hier der funktionierende Code: Code: [AUSKLAPPEN] InputFile$ = ("C:\Dateien\ta.bmp") Graphics 1024, 768, 16, 1 SetBuffer BackBuffer() ; --- Bilddatei laden Datei = ReadFile(InputFile$) SeekFile Datei, 18 ; Pos für Breite in Pixeln ResX = ReadShort(Datei) SeekFile Datei, 22 ; Pos für Höhe in Pixeln ResY = ReadShort(Datei) Rest = (ResX Mod 4): If Rest = 4 Then Rest = 0 ; Restbytes bis zur teilbarkeit durch 4 Type Pixel Field blue, green, red, x#, y#, speed#, winkel# End Type SeekFile Datei, 54 ; Leseposition auf Anfang der Bildinfos setzen ; Hier war x und y vertauscht! For y = ResY To 1 Step -1 For x = 1 To ResX p.pixel = New pixel p\blue = ReadByte(Datei) p\green = ReadByte(Datei) p\red = ReadByte(Datei) p\x# = x p\y# = y p\winkel# = Rnd(0,359) p\speed# = Rnd(4,9) Next SeekFile(Datei, FilePos(Datei) + Rest) ; Zeilenende suchen Next CloseFile Datei BildY = 384 BildX = 512 ; --- Bild anzeigen LockBuffer BackBuffer() For p.pixel = Each pixel Color p\red, p\green, p\blue If Not p\red = 248 And p\green = 0 And p\blue = 248 Then ; Transparentfarbe Pixelfarbe=255*$1000000 + p\red*$10000 + p\green*$100 + p\blue ; Vorher: WritePixelFast(p\y+BildX, p\x+BildY, Pixelfarbe) ; Also: X und Y vertauscht ... WritePixelFast(p\x+BildX, p\y+BildY, Pixelfarbe) EndIf Next UnlockBuffer BackBuffer() Flip Delay 1000 Repeat Cls ; --- Verlorene Pixel löschen For p.pixel = Each pixel ;Schleife auf KEINEN Fall verlassen wenn schon nur ein Punkt gelöscht wird!!! ; Ausserdem gehen die Bereiche von 0-1023 resp. 0-767 If p\x#+bildx > 1023 Or p\y#+bildy > 767 Or p\y#+bildy < 0 Or p\x#+bildx < 0 Then Delete p Next ; --- Bild anzeigen LockBuffer BackBuffer() For p.pixel = Each pixel Color p\red, p\green, p\blue If Not p\red = 248 And p\green = 0 And p\blue = 248 Then ; Transparentfarbe Pixelfarbe=255*$1000000 + p\red*$10000 + p\green*$100 + p\blue ; Hier war ebenfalls X und Y vertauscht! WritePixelFast(p\x+BildX, p\y+BildY, Pixelfarbe) EndIf Next UnlockBuffer BackBuffer() ; --- Bild zerstreuen For p.pixel = Each pixel p\x# = p\x# + Cos(p\Winkel#) * p\speed# p\y# = p\y# + Sin(p\Winkel#) * p\speed# Next Flip Until KeyHit(1) So, ich hoffe, ich konnte dir helfen ![]() MfG [EDIT] Ich meine nicht die ReadPixel Befehle, sondern ReadByte, da du ja clevererweise die Farbwerte direkt aus der Datei ausliest ![]() |
||
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BY ♫ BinaryBorn - Yogurt ♫ (31.10.2018) Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm |
![]() |
Travis |
![]() Antworten mit Zitat ![]() |
---|---|---|
@ Holzchopf
Erstmal vielen Dank für eine Hilfe, jetzt habe ich es verstanden. ![]() Die Schleife, in der ich die Punkte gelöscht habe, habe ich sofort nach der Löschung verlassen, weil ich ja dummerweise für jede Bildschirmseite eine eigene If-Zeile hatte. Und wenn jetzt ein Punkt durch die erste Zeile gelöscht wurde und die Bedingung der zweiten Zeile auch erfüllt wurde, war der Punkt schon gelöscht und es gab eine Fehlermeldung. Mussmir wohl angweöhnen das zukünftig in eine Zeile zu schreiben. Diese Dreher mit den X und Y-Werten stammen noch aus einem anderen Programm von mir, mit dem ich BitMaps eingelesen habe. Da habe ich alles mit DIM-Feldern gemacht und wenn ich die Werte nicht vertauscht hatte war ein Feld immer zu klein. Aber wo ich jetzt Types verwende, besteht das Problem ja gar nicht mehr. Nochmals Danke für den Hinweis. Noch mal eine Frage zum Löschen. In folgender Zeile: If p\x#+bildx > 1023 Or p\y#+bildy > 767 Or p\y#+bildy < 0 Or p\x#+bildx < 0 Then Delete p Da ist BildX und BildY, also die Position, mit eingerechnet. Ich verstehe nicht so ganz, warum das nötig ist. |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
![]() |
Vertex |
![]() Antworten mit Zitat ![]() |
---|---|---|
Tavis Du prüfst ob z.B. X größer ist als 1024 bei einem Buffer der
1024 Pixel breit ist. Das ist falsch, denn den X Wert 1024 draf er garnicht annehmen. Der ganz linke Pixel hat nämlich die X Koordinate 0, somit hat der Pixel ganz rechts die Koordinaten 1023. Da Blitz den Speicher so berechnet: Pixel = Y * Höhe * 4 + X (Die 4 steht für 32 Bit Farbtiefe / also 4 Byte) kann es dazu kommen, das Du eben in ein Pitch (also Zeile) verrutscht, und bei links wieder anfängst. mfg olli |
||
vertex.dreamfall.at | GitHub |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group