How to init SDL without a window?

Started by
8 comments, last by rabbit7 17 years, 5 months ago
Hi, I'm just doing a quick image processing libary. I'm using certain functions from the main api and SDL_image. However i'm not wanting to initialise the screen since it's only ever going to be run from a console. If I don't include part or all of the following I get a 'Segmentation fault' when I call my load_image function.

   if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )

   {

      return 1;    

   }

    

   //Set up the screen

   screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
Any direction?
Advertisement
Im not sure what are the exact dependancies of the SDL graphics functions and SDL_Init( SDL_INIT_VIDEO ) and SDL_SetVideoMode.

I would recommend leaving SDL_Init( SDL_INIT_VIDEO ) in, but omitting the call to SDL_SetVideoMode as that shouldnt be required.

Use a debugger to trace the SDL calls that cause segfaults.

Obvious examples are SDL_DisplayFormat*() or attempting to access the members of SDL_GetVideoSurface().

As long as you dont attempt to blit from or to the non-existant display surface you should be all right without SDL_SetVideoMode, that is after all the function you want to avoid calling to create a console application.

Show your load_image function code.

.

Yeah, I just tried this and rip-off is correct. You need to initalize the video subsystem, but you don't need to set the video mode. I tried loading and saving images, direct pixel access, and blitting, and it all worked.

Also SDL_DisplayFormat will not crash, it just returns NULL.

About stdout, if you are using MSVC, and create a console project, you will be able to use stdout. If you create a windows project, it will be redirected to stdout.txt. I'm not sure about other compilers.
Cheers all,

I've changed my load_image function to avoid using SDL_DisplayFormat. That now works fine, I wasn't sure if I wanted to optimise anyway.

The following is libsdl example of getting a pixel. The following line seems to the reason:

int bpp = surface->format->BytesPerPixel;

What other ways are there to avoid this call?


Uint32 getpixel(SDL_Surface *surface, int x, int y){    int bpp = surface->format->BytesPerPixel;    /* Here p is the address to the pixel we want to retrieve */    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;    switch(bpp) {    case 1:        return *p;    case 2:        return *(Uint16 *)p;    case 3:        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)            return p[0] << 16 | p[1] << 8 | p[2];        else            return p[0] | p[1] << 8 | p[2] << 16;    case 4:        return *(Uint32 *)p;    default:        return 0;       /* shouldn't happen, but avoids warnings */    }}
I really can't understand why this is giving me:
   Fatal signal: Segmentation Fault (SDL Parachute Deployed)

It shouldn't depend on anything, surely?

Q. I'm using g++ 'n' gedit on Fed4, which debugger / trace program would you reccomend?
Also with a bit of hard coding, it seems this is also included:
   SDL_GetRGB ( pix , surffmt , &color.r , &color.g , &color.b );
The code I used included getpixel and putpixel and they worked fine for me. You should be able to inspect the format of any surface except the video surface (obviously).

Can you post your whole code? Or, if it's too long, an example that demostrates the problem?
Yep, this will be too long! (p.s. very stripped down)

*** CODE ***
//	compile://		g++ -lSDL -lSDL_image main.cpp -o main////	usage://		 ./main -d imgs01/test2.pnm imgs01/test3.pnm imgs01/test.bmp 20///*	PLACES WHERE IT HANGS!	====== ===== == ======		Uint32 getpixel(SDL_Surface *surface, int x, int y)	// FUNCTION (where)		int bpp = surface->format->BytesPerPixel;	// LINE (what)	SDL_Color get_rgb(int pix, SDL_PixelFormat *surffmt)		SDL_GetRGB ( pix , surffmt , &color.r , &color.g , &color.b );		void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)		int bpp = surface->format->BytesPerPixel;    int save_image_bmp( const char *file, SDL_Surface * surf )  		int iret = SDL_SaveBMP(surf, file);	*/#include "SDL/SDL.h"#include "SDL/SDL_image.h"#include <string>int sdl_init(){    printf("Initialising SDL\n");	    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )    {        return 1;        }        //Set up the screen        printf("   SDL initialised\n");    return 0;}int sdl_cleanup(){	SDL_Quit();}int save_image_bmp( const char *file, SDL_Surface * surf )  {	printf("   Saving image\n");	int iret = SDL_SaveBMP(surf, file);	printf("      Saved image\n");	return iret;}SDL_Surface *load_image_pnm( std::string fname ){	printf("   Loading pnm image\n");		SDL_Surface* sret = NULL;		//	return surface		// load sample.pnm into image	SDL_Surface *image;	SDL_RWops *rwop;	rwop=SDL_RWFromFile(fname.c_str(), "rb");	image=IMG_LoadPNM_RW(rwop);	if(!image) {		printf("IMG_LoadPNM_RW: %s\n", IMG_GetError());		// handle error	}		//If nothing went wrong in loading the image	if( image != NULL )	{		//Create an optimized image		//sret = SDL_DisplayFormat( image );		sret = image;				//Free the old image		SDL_FreeSurface( image );	}	printf("      Load success\n");	return sret;}int rgb_compare_range(SDL_Color c1, SDL_Color c2, int tol){	if ( 	( (c1.r >= c2.r - tol) && (c1.r <= c2.r + tol) ) &&			( (c1.g >= c2.g - tol) && (c1.g <= c2.g + tol) ) &&			( (c1.b >= c2.b - tol) && (c1.b <= c2.b + tol) )		)	{		return 1;	}	return 0;}Uint32 getpixel(SDL_Surface *surface, int x, int y){	printf("   Getting pixel\n");    //int bpp = 4;    int bpp = surface->format->BytesPerPixel;    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;	    switch(bpp) {    case 1:        return *p;    case 2:        return *(Uint16 *)p;    case 3:        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)            return p[0] << 16 | p[1] << 8 | p[2];        else            return p[0] | p[1] << 8 | p[2] << 16;    case 4:        return *(Uint32 *)p;    default:        return 0;       /* shouldn't happen, but avoids warnings */    }	printf("      Got pixel succesfully\n");}void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel){	printf("   Putting pixel\n");	//int bpp = 4;    int bpp = surface->format->BytesPerPixel;    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;    switch(bpp) {    case 1:        *p = pixel;        break;    case 2:        *(Uint16 *)p = pixel;        break;    case 3:        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {            p[0] = (pixel >> 16) & 0xff;            p[1] = (pixel >> 8) & 0xff;            p[2] = pixel & 0xff;        } else {            p[0] = pixel & 0xff;            p[1] = (pixel >> 8) & 0xff;            p[2] = (pixel >> 16) & 0xff;        }        break;    case 4:        *(Uint32 *)p = pixel;        break;    }    printf("      Pixel put succesfully\n");}SDL_Color get_rgb(int pix, SDL_PixelFormat *surffmt){	SDL_Color c ;	printf("   Getting RGB\n");	SDL_GetRGB ( pix , surffmt , &c.r , &c.g , &c.b );	//c.r = 255; c.g = 100; c.b = 100;	printf("   Got RGB succesfully\n");	return c;}SDL_Surface * image_difference(SDL_Surface *surf1, SDL_Surface *surf2, int tol){	printf ( "Image find differences\n" );		SDL_Surface* sret = NULL;		//	our return surface		sret = surf1;		SDL_PixelFormat *surffmt1 = surf1->format;	SDL_PixelFormat *surffmt2 = surf2->format;		int num_diff = 0;	int w1 = surf1->w;	int h1 = surf1->h;	int w2 = surf2->w;	int h2 = surf2->h;	int w, h;	//	SIMPLIFIED CHECKING !!!!	w = w1;	h = h1;			int ud = 65504;		//	diff colour	int us = 35100;		//	same colour		for (int i = 0; i < w-1; i++)	{		for (int j = 0; j < h-1; j++)		{			// GET COLOUR 1			Uint32 u1 = getpixel(surf1, i, j);	//	SDL_Surface *surface, int x, int y				SDL_Color c1 = get_rgb(u1, surffmt1);	// int pix, SDL_PixelFormat *surffmt1					// GET COLOUR 2			Uint32 u2 = getpixel(surf2, i, j);	// SDL_Surface *surface, int x, int y				SDL_Color c2 = get_rgb(u2, surffmt2);	// int pix, SDL_PixelFormat *surffmt1									// CHECK THE COLOURS			int iret = rgb_compare_range(c1, c2, tol); // SDL_Color c1, SDL_Color c2, int tol			if ( iret == 1 )			{				num_diff++;				putpixel(sret, i, j, ud);	// SDL_Surface *surface, int x, int y, Uint32 pixel			}			else			{				putpixel(sret, i, j, us);	// SDL_Surface *surface, int x, int y, Uint32 pixel			}		}	}	printf("   Finished finding differences\n");	return sret;}void img_diff(std::string fn1, std::string fn2, char * fout, int tol){	SDL_Surface* img1 = load_image_pnm( fn1 );	SDL_Surface* img2 = load_image_pnm( fn2 );	SDL_Surface* s = image_difference(img1, img2, tol);	//	SDL_Surface *surf1, SDL_Surface *surf2	int iret = save_image_bmp(fout, s);	//	const char *file, SDL_Surface * surf	//SDL_FreeSurface( img1 );	//SDL_FreeSurface( img2 );	//SDL_FreeSurface( s );}int main( int argc, char* args[] ){	printf("Welcome to imgproc\n");			sdl_init();		int t1 = SDL_GetTicks();	// get num milliseconds since init		// SIMPLIFIED !!!		if (argc == 6)	{		printf("Comparing differences %s to %s\n", args[2], args[3]);		img_diff( args[2], args[3], args[4], atoi(args[5]) );	//	std::string fn1, std::string fn2)	}	else { printf("Wrong number of arguments\n");               printf("   usage:\n      ./main -d imgs01/test2.pnm imgs01/test3.pnm imgs01/test.bmp 20\n"); }		sdl_cleanup();		int t2 = SDL_GetTicks();	// get num milliseconds since init	int t3 = t2 - t1;	printf("Duration: %d milliseconds...\n", t3);        return 0;    }


*** CODE END ***

A solution would be muchos appreciated!
I tested everything but your load_image_pnm function (I don't know what pnm's are). Everything ran without a problem, so I've concluded that your problem must be in this function.

SDL_Surface *load_image_pnm( std::string fname ){	printf("   Loading pnm image\n");	SDL_Surface* sret = NULL;		//	return surface	// load sample.pnm into image	SDL_Surface *image;	SDL_RWops *rwop;	rwop=SDL_RWFromFile(fname.c_str(), "rb");	image=IMG_LoadPNM_RW(rwop);	if(!image)        {		printf("IMG_LoadPNM_RW: %s\n", IMG_GetError());		// handle error	}	//If nothing went wrong in loading the image	if( image != NULL )	{		//Create an optimized image		//sret = SDL_DisplayFormat( image );		sret = image;   ///////////////////// A		//Free the old image		SDL_FreeSurface( image );  /////////////// B	}	printf("      Load success\n");	return sret;}


The problem, I think, is on the lines marked A and B. On line A you set your sret to be the image. They now point at the same surface. On line be, you free the "old" image, but it is the same as the new image. This is probably a holdover from when you were calling SDL_DisplayFormat. Since you free the only image you had, the function fails.

Hope that was it.

This topic is closed to new replies.

Advertisement