Seite 1 von 1

Hilfe zur Grafikspeichermanipulation

Verfasst: 15.01.2005 21:57
von Kekskiller
Seit dem ich von jemandem eine sehr geniale Spriterotationsfunktion bekommen
habe, geht mir die Möglichkeit nicht mehr aus dem Kopf, direkt im
Bildschrimspeicher Pixel einzukritzeln, nur weiß ich nicht wirklich, wie das
mit dem Aufbau ist... Wissen tuh ich schon, dass man entsprechend die richtigen
Positionen der Pixel errechnen, bzw rauspointern muss, nur fehlen mir da
Details, genaue Beschreibungen und alles andere drum rum. Es ist mir wichtig,
alles mögliche darüber herauszufinden, nur weiß ich nicht... nunja, wie...
Also, könnt ihr mir da helfen? Am besten irgendwer kann mir einen Link zu
einem Tuto, einer Seite oder sonstwas liefern, oder am besten selbst erklären,
begierig bin ich, mehr darüber zu wissen.

Verfasst: 16.01.2005 00:34
von Robert Wünsche
Um den Bildbuffer direkt zu manipulieren, muss man erstmal wissen, wie der aufgebaut ist.
Der Buffer besteht aus zeilen und spalten, dabei hat jedes Pixel der gewählten farbtiefe entsprechen viele Bytes platz, in denen die Farbinformation gespeichert ist.

Chematisch:
-------------------------------------------------------------
zeile | Pixel || Pixel |
| Byte 1 | byte 2 | byte 3 || Byte 1 | byte 2 | byte 3| . . .
| Rot | Grün | Blau || Rot | Grün | Blau |
-------------------------------------------------------------
zeile | Pixel || Pixel |
| Byte 1 | byte 2 | byte 3 || Byte 1 | byte 2 | byte 3| . . .
| Rot | Grün | Blau || Rot | Grün | Blau |
-------------------------------------------------------------
zeile | Pixel || Pixel |
| Byte 1 | byte 2 | byte 3 || Byte 1 | byte 2 | byte 3| . . .
| Rot | Grün | Blau || Rot | Grün | Blau |
-------------------------------------------------------------

Um die Farbinformation zu Manipulieren muss man mit dem befehl

Code: Alles auswählen

DrawingBuffer()
erstmal wissen, wo überhaupt der Drawingbuffer anfängt, wenn der wert nicht 0 ergibt, kann man andere benötigte informationen bedenkenlos einsetzen, wenn der wert 0 ergibt, ging irgentetwas schief und man kann nicht direkt auf den Buffer zugreifen !
Andere benötigte informationen:

Code: Alles auswählen

DrawingBufferPixelFormat()
Das Format, in dem die Farbinformationen abgelegt werden.

Code: Alles auswählen

DrawingBufferPitch()
Die länge in bytes einer Zeile.

Beachte:
Mit den Hier genannten Methoden wird der Backbuffer beschrieben !

Die genanten Befehle müssen nach dem Starten des Zeichenforgangs auf den Gewünschten Bildschirm ausgeführt werden !

Das Pixelformat der Drawingbuffers kann folgende werte annehmen:

#PB_PixelFormat_8Bits
Format:
Nach der gewählten Farbpalette

#PB_PixelFormat_15Bits
Format:
5 Bit: Rot
5 Bit: Grün
5 Bit: Blau

#PB_PixelFormat_16Bits
Ist im forum genau beschrieben

#PB_PixelFormat_24Bits_RGB
8 Bit: Rot
8 Bit: Grün
8 Bit: Blau

#PB_PixelFormat_24Bits_BGR
8 Bit: Blau
8 Bit: Grün
8 Bit: Rot

#PB_PixelFormat_32Bits_RGB
? : Ist irgentwo im forum beschrieben
Fermutet (einfachste lösung):
8 Bit: Rot
8 Bit: Grün
8 Bit: Blau
rest : ?

#PB_PixelFormat_32Bits_BGR
? : Ist irgentwo im Forum beschrieben
Vermutet (einfachste lösung):
8 Bit: Blau
8 Bit: Grün
8 Bit: Rot
rest : ?

Und noch etwas code zu verdeutlichung:

Code: Alles auswählen

Structure Buffer
  xauf.l
  yauf.l
  tiefe.l
  titel.s
  
  bufferadresse.l
  bufferzeile.l
  bufferformat.l
EndStructure

;werte initialisieren:
aktuell.Buffer\xauf  = 800
aktuell.Buffer\yauf  = 600
aktuell.Buffer\tiefe = 32
aktuell.Buffer\titel = "Buffer"

;initialisiering:
If InitSprite() = 0
  MessageRequester("Fehler !", "Konnte die DirectX 7.0 anzeige-umgebung nicht initialisieren !")
  End
EndIf

;Öffnen des Bildschirmes:
If OpenScreen(aktuell.Buffer\xauf,aktuell.Buffer\yauf,aktuell.Buffer\tiefe,aktuell.Buffer\titel) = 0
  MessageRequester("Fehler !", "Konnte einen Bildschirm  mit den Massen: "+Str(aktuell.Buffer\xauf)+"x"+Str(aktuell.Buffer\yauf)+"x"+Str(aktuell.Buffer\tiefe)+" nicht öffnen !")
  End
EndIf

If StartDrawing(ScreenOutput()) = 0
  MessageRequester("Fehler !","Konnte auf den Bildschirm nicht zeichnen !")
  End
Else
  
  ;adresse initialisieren :
  aktuell.Buffer\bufferadresse = DrawingBuffer() 
  ;andere Benötigte daten holen:
  aktuell.Buffer\bufferformat  = DrawingBufferPixelFormat()   ;müsste 7 ergeben
  aktuell.Buffer\bufferzeile   = DrawingBufferPitch() 
  
  StopDrawing()
EndIf

;überprüfen:
If aktuell.Buffer\bufferadresse = 0
  MessageRequester("Fehler !","Konnte Den Bildschirmspeicher nicht initialisieren !")
  End
EndIf

;format überprüfen(testweise):
If aktuell.Buffer\bufferformat <> 7
  MessageRequester("Fehler !","Falsches Faerbformat !")
  End
EndIf

;debugen:
Debug aktuell.Buffer\bufferadresse
Debug aktuell.Buffer\bufferformat
Debug aktuell.Buffer\bufferzeile

;Initialisierung beendet !
;======================================================================================
;Die Praxis:

;blau schreiben:
PokeB(aktuell.Buffer\bufferadresse,255)
;nächste zeile:
PokeB(aktuell.Buffer\bufferadresse + aktuell.Buffer\bufferzeile,255)

FlipBuffers()

Delay(8000)
End
PS: Es konnen noch stellenweise Falsche informationen forliegen, dh.: alles ohne Gewähr !

Verfasst: 16.01.2005 04:00
von Zaphod
der grafikspeicher hat keine zeilen und spalten sondern ist linear.
den punkt an der stelle x,y erreichst du demnach mit x+y*DrawingBufferPitch()

DrawingBufferPitch ist nötig, da eine zeile nicht unbedingt die selbe breite hat, wie die screenbreite, da viele grafikkarten zusätzliche informationen zb für den blitter hinter die zeile schreiben.

willst du mehr als einen pixel zeichnen solltest du drawingbufferpitch in eine variable schreiben und diese benutzen.

die farbwerte die du schreiben willst, speicherst du am besten in purebasic variablen gleicher bitbreite, also in variablen vom typ long für 32 bit farbtiefe, word für 16 bit farbtiefe und byte für 8 bit farbtiefe. wie man pixel für 24 bit farbtiefe effizient behandelt weiß ich allerdings nicht.

Verfasst: 16.01.2005 11:58
von Kekskiller
Vielen Dank, Leute, werde gleich mal ein wenig rumprobieren.
Das hilft mir schon ein ganzes Eckchen weiter. *freu*

Verfasst: 17.01.2005 19:29
von Kekskiller
Nunja, ich, äh... ähäm *kratzkratz* ... jetzt hab ich rausgefunden, wie und
auf was für Weisen ich Positionen von Pixeln herausbekommen kann, ja...
Aber das mit den Farben ist mir gerade ein ziemliches Rätsel. Beispielcode:

Code: Alles auswählen

InitSprite()
InitKeyboard()
OpenScreen(320,240, 16, "Screen")

StartDrawing(ScreenOutput())
  bufferadresse.l = DrawingBuffer()
  bufferpixelformat.l = DrawingBufferPixelFormat()
  bufferpitch.l = DrawingBufferPitch() ;länge in bytes einer bildschirmzeile
StopDrawing()

PokeB(bufferadresse + (99 * 2 + 100 * bufferpitch), 255)

StartDrawing(ScreenOutput())
  Plot(100,100,RGB(255,255,255))
StopDrawing()

FlipBuffers()

Delay(5000)
Nach einigem Rumprobieren fand ich heraus, dass man die Adresse von
einer XY-Position per: Bufferadresse + (X * 2 + Y * BufferPitch)
knacken kann, hierbei auch vielmals Dank an Zaphod für den
Rechnungsteil. Nur will mir das mit den Farbwerten einafch nicht in den
Kopf gehen... Auch mit der Darstellung da unten... ich weiß nicht, das
kapier ich jetzt mit dem, was ich bereits weiß nicht. Tschuldigung, aber
ich brauche nochmals ein Eckchen Unterstützung.

Verfasst: 17.01.2005 19:38
von Kaeru Gaman
das alte 16bit/24bit problem...

vielleicht hilft dir dieser thread:

http://robsite.de/php/pureboard/viewtopic.php?t=1094