Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Meai

Frischling

  • »Meai« ist der Autor dieses Themas
  • Private Nachricht senden

1

20.07.2008, 22:23

SDL: Kapiere surface->pixels einfach nicht

Schönen Tag!
Ich weiß, die Fragen werden mitunter lächerlich klingen, aber finde einfach ums Biegen und Brechen keine ordentliche Erklärung.
Folgendes Problem:
Da zu meinem Erstaunen die SDL gar keine eingebaute Funktion hat einen Pixel zu setzen versuchte ich mich schlau zu machen wie das denn funktioniert. Bin darauf gestoßen:

Quellcode

1
2
3
4
5
6
7
8
SDL_Surface *screen;
void putpixel(int x, int y, int color)
{
    unsigned int *ptr = (unsigned int*)screen->pixels;
    
    int lineoffset = y * (screen->pitch / 4);
    ptr[lineoffset + x] = color;
}


Soweit sogut, nur will ich das noch besser verstehen.
Meine konkreten Fragen:
1,
Wie kann es sein dass ein Bildschirm von zb. 600x400 Pixeln in einer einzigen Integervariable gespeichert wird? (bzw. in einem einzigen Integerspeicherbereich auf den der Pointer zeigt)
2,
Wenn ich mir "(unsigned int*)screen->pixels" mit "cout" ausgeben lasse bekomme ich eine einzige Zahl heraus. (65320). Wie werden darin die Pixel unterschieden?
3,
Dann stellt sich mir dazu die Frage was genau das "screen->pitch" bedeutet...die Erklärungen im Internet sprechen immer nur davon dass man durch 4 dividieren muss weil ein Byteformat zurückgegeben wird. Und es sozusagen eine "Scanlinie" ist. Habt ihr da eine ausführlichere Erklärung?
4,
Warum braucht man überhaupt ein lineoffset, was genau ist das? Ich rate mal dass man dadurch irgendwie die Pixel im Integerpointer unterscheiden kann...
(warum greift man nicht per x und y auf den entsprechenden Wert im "pixels" zu?..ja, das is kein array aber....bin verwirrt)
5,
Warum multipliziert man zuerst y, addiert x später an anderer Stelle? Ihr seht schon, ich tu mir sehr schwer, will das aber trotzdem verstehen.

Bin für alles dankbar!

Kasenoru

Frischling

Beiträge: 79

Beruf: Softwareentwickler

  • Private Nachricht senden

2

21.07.2008, 11:47

Zitat

1,
Wie kann es sein dass ein Bildschirm von zb. 600x400 Pixeln in einer einzigen Integervariable gespeichert wird? (bzw. in einem einzigen Integerspeicherbereich auf den der Pointer zeigt)


Weil bei 32 Bit nunmal 4 Bytes(32 Bits) benötigt werden, um einen Pixel zu speichern. In deinem Fall ein 4 Byte vorzeichenloser Integer.
Für z.b. 16 Bit würden nur 2 Bytes benötigt werden.

Beachte aber das 32 Bit != 32 Bit. Das Format ist trotz der Größe nicht immer gleich.

Es könnte ARGB sein, RGBA, BGRA, etc.
Daher ist es wichtig, das wenn du mit SDL bessere Geschwindigkeiten erreichen willst, du mit SDL_DisplayFormat deine Surfaces immer in das gleiche Format wie das des Bildschirms umwandelst. Es reicht nämlich nicht, wenn deine Grafiken 32 Bit sind und dein Bildschirm auch. Denn wie gesagt, 32 Bit != 32 Bit. Gilt natürlich auch für andere Formate.

Der Pointer zeigt, wie du schon erkannt hast, auf einen Speicherbereich. Mit dem [] Operator kannst du jeden einzelnen Integer des
Speicherbereiches durchgehen.

Der Bereich ist in Bytes: Breite * Höhe * 4 groß.

Zitat

Dann stellt sich mir dazu die Frage was genau das "screen->pitch" bedeutet...die Erklärungen im Internet sprechen immer nur davon dass man durch 4 dividieren muss weil ein Byteformat zurückgegeben wird. Und es sozusagen eine "Scanlinie" ist. Habt ihr da eine ausführlichere Erklärung?


Pitch ist in dem Fall die länge einer Pixelreihe in Bytes. Da du den Speicherbereich aber als Integer-Array behandelst, brauchst du die länge in Integers. Sprich in 4 Byte Stücken. Daher durch 4 teilen.

Zitat

Warum braucht man überhaupt ein lineoffset, was genau ist das? Ich rate mal dass man dadurch irgendwie die Pixel im Integerpointer unterscheiden kann...
(warum greift man nicht per x und y auf den entsprechenden Wert im "pixels" zu?..ja, das is kein array aber....bin verwirrt)


Ein Array ist ein Zeiger auf einen Speicherbereich.

Zitat

Warum multipliziert man zuerst y, addiert x später an anderer Stelle? Ihr seht schon, ich tu mir sehr schwer, will das aber trotzdem verstehen.


Stell dir dein Bild wie eine Rechteckige Anordnung von Pixeln vor.
Die Position 0,0 liegt oben links. Die Position 0,1 ist der Pixel ganz links
eine Reihe tiefer. Usw.

Durch Pitch / 4 weist du, wie lang eine Pixelreihe ist.
Wenn du jetzt einen Pixel an 0,5 Platzieren willst, musst du zur 5. Pixelreihe springen. Daher y * länge einer Pixelreihe. Klingt logisch oder?

Nun hast du also schonmal die richtige Reihe, aber was ist mit der Spalte?
Das ist ganz einfach, du addierst einfach noch den X Wert hinzu, um in der richtigen Spalte zu landen. Verstanden? Stell es dir wirklich mal bildlich vor. Es ist wirklich nicht schwer zu verstehen.

Mit freundlichen Grüßen

Kasenoru

Meai

Frischling

  • »Meai« ist der Autor dieses Themas
  • Private Nachricht senden

3

21.07.2008, 14:48

Danke für deine Antwort!
Bin jetzt etwas über eine Stunde an diesem Post gesessen, überlegt, umgeschrieben, große Teile die mir klar wurden weggelöscht und jetzt bin ich an einem Punkt angelangt wo ich glaube dass mir alles klar ist dank dir :D
Hier mein Erkenntnisweg, hoffentlich ist es tatsächlich so richtig :)
:

Zitat

Der Pointer ist wie du schon erkannt hast ein Zeiger auf einen Speicherbereich. Mit dem [] Operator kannst du jeden einzelnen Integer des
Speicherbereiches durchgehen.

Ahhh, ok also sind Speicherbereiche äquivalent zu eindimensionalen Arrays! Komme aus Java und da hat man (oder ich) diese Sachen noch nicht so genau wissen müssen.

Zitat


Durch Pitch / 4 weist du, wie lang eine Pixelreihe ist.

Ah, interessant. Also ist screen->pitch ein einzelner Integerwert in Bytes.

Zitat


Wenn du jetzt einen Pixel an 0,5 Platzieren willst, musst du zur 5. Pixelreihe springen. Daher y * länge einer Pixelreihe. Klingt logisch oder?

Nun hast du also schonmal die richtige Reihe, aber was ist mit der Spalte?
Das ist ganz einfach, du addierst einfach noch den X Wert hinzu, um in der richtigen Spalte zu landen. Verstanden? Stell es dir wirklich mal bildlich vor. Es ist wirklich nicht schwer zu verstehen.

Wundervoll ich habs kapiert :D
Man geht soviele Pixelzeilen durch bis man an der richtigen Reihe angelangt ist, dann muss man nicht mehr soviel auf einmal weitergehen, sondern nur mehr "spaltenweise". Deswegen Addition!
Jeder Pixel ist also ein Eintrag im Array! (ein 4 Byte großer Integereintrag...also 11111111 1111111 1111111 11111111)..dessen Farbe man leicht dank der hexadezimalen Schreibweise identifizieren und verändern kann.


Zitat

Der Bereich ist in Bytes: Breite * Höhe * 4 groß.

Ok stell mir den Speicherbereich so vor, das müsste jetzt stimmen:

ABCDEFG <-Adresse auf den Speicherbereich
Speicherbereich von ABCDEG:
00011111 1111111 1111111 11111111 (Pixel 0/0)
11111111 1111111 1111111 11111111 (Pixel 1/0)
11111111 1111111 1111111 11111111 (Pixel 2/0)
etc
Zugrif auf die Einträge:
ABCDEFG[0] = 00011111 1111111 1111111 11111111

Vielen Dank nochmal und schöne Grüße!
[/code]

Werbeanzeige