SDL get_pixel problem



  • Also hier erstmal der quellcode:

    const int MAP_WIDTH = 2000;
    const int MAP_HEIGHT = 600;
    
    [...]
    Uint32 get_pixel32( SDL_Surface *surface, int x, int y )
    {
        //Convert the pixels to 32 bit
        Uint32 *pixels = (Uint32 *)surface->pixels;
    
        //Get the requested pixel
        return pixels[ ( y * surface->w ) + x ];
    }
    
    bool loadMap(string url)
    {
    
    	cMap.mapImage = IMG_Load ( url.c_str() );
    
    	if(cMap.mapImage->w == MAP_WIDTH && cMap.mapImage->h == MAP_HEIGHT)
    	{
    		Uint32 p;
    		Uint8 r, g, b;
    		for(int i = 0; i < MAP_WIDTH; i++)
    		{
    			for(int j = 0; j < MAP_HEIGHT; j++)
    			{
    				p = get_pixel32(cMap.mapImage, i, j); //<------------------------ ERROR
    				SDL_GetRGB(p, screen->format, &r, &g, &b);
    				if(r+g+b == 0)
    				{
    					cMap.collisionMap[i][j] = false;
    				}
    				else
    				{
    					cMap.collisionMap[i][j] = true;
    				}
    			}
    		}
    
    		return true;
    
    	}
    	else
    	{
    		cMap.mapImage = NULL;
    	}
    	return false;
    }
    [...]
    
    SDL_Surface *createEmptyFromScreen(int w, int h, SDL_Surface *from)
    {
    	return SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, from->format->BitsPerPixel, from->format->Rmask, from->format->Gmask, from->format->Bmask, from->format->Amask );
    }
    
    [...]
    
    cMap.mapImage = createEmptyFromScreen(MAP_WIDTH, MAP_HEIGHT, screen);
    
    [...]
    
    if(!loadMap("testmap.bmp"))
    	return 1;
    

    Seltsamerweise beendet sich mein programm hier sofort, und zwar auf grund der Zeile
    p = get_pixel32(cMap.mapImage, i, j);

    warum?
    die surface wurde doch auf die richtige größe initialisiert und bevor ich den pixel hole, überprüf ich doch sogar noch ob breite und höhe stimmen

    die schleife wird allerdings vor dem absturz noch mehrfach durchlaufen (weis leider nicht wie oft)



  • Du hast die Surface nicht gesperrt. Das musst du aber tun, bevor du auf die Pixel zugreifen kannst. Anschließend das Entsperren nicht vergessen.



  • TomasRiker schrieb:

    Du hast die Surface nicht gesperrt. Das musst du aber tun, bevor du auf die Pixel zugreifen kannst. Anschließend das Entsperren nicht vergessen.

    jo hat leider nix gebracht 😞

    bool loadMap(string url)
    {
    
    	cMap.mapImage = IMG_Load ( url.c_str() );
    
    	if(cMap.mapImage->w == MAP_WIDTH && cMap.mapImage->h == MAP_HEIGHT)
    	{
    		SDL_LockSurface(cMap.mapImage);
    		Uint32 p;
    		Uint8 r, g, b;
    		for(int i = 0; i < MAP_WIDTH; i++)
    		{
    			for(int j = 0; j < MAP_HEIGHT; j++)
    			{
    				p = get_pixel32(cMap.mapImage, i, j);
    				SDL_GetRGB(p, screen->format, &r, &g, &b);
    				if(r+g+b == 0)
    				{
    					cMap.collisionMap[i][j] = false;
    				}
    				else
    				{
    					cMap.collisionMap[i][j] = true;
    				}
    			}
    		}
    		SDL_UnlockSurface(cMap.mapImage);
    		return true;
    
    	}
    	else
    	{
    		cMap.mapImage = NULL;
    	}
    	return false;
    }
    

    -> selbes problem



  • Ist deine Surface denn auch eine 32-Bit-RGB-Surface?



  • ja wie schon geschrieben

    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
    
    cMap.mapImage = createEmptyFromScreen(MAP_WIDTH, MAP_HEIGHT, screen);
    
    SDL_Surface *createEmptyFromScreen(int w, int h, SDL_Surface *from)
    {
    	return SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, from->format->BitsPerPixel, from->format->Rmask, from->format->Gmask, from->format->Bmask, from->format->Amask );
    }
    

    wie auch schon geschrieben... die schleife läuft rel. oft durch...bricht erst nach ziemlich vielen durchläufen ab

    edit: ich habe die getpixel methode auch in anderen programmen verwendet..da gabs nie probleme... 😕



  • Du hast aber nirgenwo in deinem Posting geschrieben, was SCREEN_BPP ist. Außerdem lädst du das Bild ja aus einer Datei:

    cMap.mapImage = IMG_Load ( url.c_str() );
    

    Wenn diese geladene Surface - von IMG_Load zurückgegeben - nicht 32-Bit ist, sondern z.B. 24-Bit, dann erklärt das, warum es irgendwann crasht.



  • const int SCREEN_BPP = 32;



  • Ich habe noch was zu meinem letzten Posting dazugeschrieben.
    Der Funktion IMG_Load ist deine SCREEN_BPP-Variable herzlich egal.
    Und BMP-Dateien sind für gewönlich mit 24 BPP gespeichert (da sie keinen Alphakanal aufnehmen können).



  • hm hab als ich meinen post gemacht hab deinen nicht gesehen...
    wenn ich ein 24 bit bild in eine 32 bit surface lade, wird die surface dann zu 24 bit umgewandelt? und wieso stürzt der denn dann ab? werden die 24 bit farbwerte denn nicht einfach in die 32 vars gecastet? was muss ich denn jetzt ändern ?

    edit: habs getestet, du hast recht! hast nen tipp wie ich die 24 in 32 bit umwandle?
    was ist bei bmp's der unterschied zwischen 24 und 32 bit ?



  • hmm jetzt lad ich ne 32 bit bitmap, funzt auch, nur wenn ich sie blitte, bleibt der bildschirm einfach schwarz



  • Du kannst eine SDL-Surface im gewünschten Format erzeugen (32 Bit) und dort einfach die Original-Surface reinkopieren (Blt).
    Warum es abstürzt? Ist doch klar: im Speicher ist ein Pixel 3 Bytes groß, du liest aber jedes Mal vier. D.h. du kriegst nicht nur falsche Farben, sondern liest auch zu weit, und irgendwann liest du über den Speicherbereich hinaus.

    Beispiel für ein Bild mit nur 8 Pixeln:
    
    So liegen die Daten im Speicher (bei 24 Bits):
    RGBRGBRGBRGBRGBRGBRGBRGB
    1  2  3  4  5  6  7  8   (Pixel-Nr.)
    
    und so liest du:
    RGBARGBARGBARGBARGBARGBARGBARGBA
    1   2   3   4   5   6   7   8    (Pixel-Nr.)
    

    Beim 7. Pixel bist du schon über's Ziel hinausgeschossen.



  • jau danke habs gecheckt...kannst mir trotzdem sagen, warum das blitten nicht geht ?



  • Nicht ohne den Code zu sehen 😉



  • jo, code so wie eben, mit ner 32 bit bitmap und

    SDL_Rect ir;
    ir.x = 0;
    ir.y = 0;
    ir.w = MAP_WIDTH;
    ir.h = MAP_HEIGHT;
    SDL_Rect sr;
    sr.x = 0;
    sr.y = 0;
    sr.w = SCREEN_WIDTH;
    sr.h = SCREEN_HEIGHT;
    SDL_BlitSurface(cMap.mapImage, &ir, screen, &sr);
    //apply_surface( 0, 0, pSurface, screen );
    if( SDL_Flip( screen ) == -1 )
    {
    	return 1;    
    }
    

    in der hauptprogrammschleife

    edit:

    if(SDL_BlitSurface(cMap.mapImage, &ir, screen, &sr) != 0)
    		{
    			return 1;
    		}
    

    bricht NICHT ab Oo



  • Du versuchst, die komplette Map - die größer ist als der Bildschirm (wie ich annehme) - auf den Bildschirm zu blitten. Ändere dein Source-Rectangle mal so, dass es höchstens so groß wie der Bildschirm ist.
    Daran könnte es liegen ...



  • TomasRiker schrieb:

    Du versuchst, die komplette Map - die größer ist als der Bildschirm (wie ich annehme) - auf den Bildschirm zu blitten. Ändere dein Source-Rectangle mal so, dass es höchstens so groß wie der Bildschirm ist.
    Daran könnte es liegen ...

    ist es doch

    ir.w = MAP_WIDTH; 
    ir.h = MAP_HEIGHT;
    


  • Benutze anstatt Rects einfach mal NULL. Ich glaube das sollte gehen, wenn du das ganze Bild blitten willst.



  • das bild ist aber grösser als mein fenster



  • Hast du's probiert?



  • Stefan schrieb:

    Hast du's probiert?

    ja


Anmelden zum Antworten