Brauche mal Hilfe zum WritePixelFast-Befehl

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

Travis

Betreff: Brauche mal Hilfe zum WritePixelFast-Befehl

BeitragSa, Jan 17, 2004 13:22
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, Jan 17, 2004 13:32
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, Jan 17, 2004 18:45
Antworten mit Zitat
Benutzer-Profile anzeigen
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. Rolling Eyes

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

BeitragSa, Jan 17, 2004 19:26
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Wink
MrKeks.net

Travis

BeitragSa, Jan 17, 2004 19:34
Antworten mit Zitat
Benutzer-Profile anzeigen
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. Rolling Eyes
www.funforge.org

Ich hasse WASD-Steuerung.

Man kann alles sagen, man muss es nur vernünftig begründen können.

TheShadow

Moderator

BeitragSa, Jan 17, 2004 20:13
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, Jan 17, 2004 20:58
Antworten mit Zitat
Benutzer-Profile anzeigen
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.

Holzchopf

Meisterpacker

BeitragSa, Jan 17, 2004 22:33
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Wink

MfG

[EDIT] Ich meine nicht die ReadPixel Befehle, sondern ReadByte, da du ja clevererweise die Farbwerte direkt aus der Datei ausliest Very Happy [/EDIT]
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Travis

BeitragSa, Jan 17, 2004 23:02
Antworten mit Zitat
Benutzer-Profile anzeigen
@ Holzchopf

Erstmal vielen Dank für eine Hilfe, jetzt habe ich es verstanden. Very Happy

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

BeitragSo, Jan 18, 2004 1:08
Antworten mit Zitat
Benutzer-Profile anzeigen
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

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group