views:

2416

answers:

5

Hey all,

I'm trying to write a program which takes an SDL_Surface, converts it to an IplImage, uses the cvBlobsLib to find blobs, paints the blobs as spots back over the image, then converts the output IplImage back to an SDL_Surface.

I'm almost done: only converting the IplImage back to an SDL_Surface hasn't been done yet. This IplImage has 3 image channels and is 8 bits per pixel. I think I have two calls I can use:

SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);

I'm currently trying with SDL_CreateRGBsurfaceFrom. I have no idea, however, what the correct values of pitch, Rmask, Gmask and Bmask are. (Amask is 0, because there is no alpha channel.)

Could anybody help me out by explaining how to do this?

Thanks!

Edit: For example, this is code I tried to use:

SDL_Surface *ipl_to_surface (IplImage *opencvimg)
{
    int pitch = opencvimg->nChannels*opencvimg->width;
    printf("Depth %d, nChannels %d, pitch %d\n", opencvimg->depth,
                    opencvimg->nChannels, pitch);
    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)opencvimg->imageData,
                    opencvimg->width,
                    opencvimg->height,
                    opencvimg->depth,
                    pitch,
                    0x0000ff, 0x00ff00, 0xff0000, 0
                    );
    return surface;
}

(SDL Documentation writes "Pitch is the size of the scanline of the surface, in bytes, i.e. widthInPixels*bytesPerPixel.") This outputs "Depth 8, nChannels 3, pitch 1920" and displays a completely red image. I think a solution would be to convert my 8-bits image to 24-bits (1 byte per channel), but I don't know how to do that. Any ideas?

+2  A: 

Ok, I got it working!

I think I was confused by the fact that an OpenCV depth of 8 means a pixel has 8 bits per channel, so in a 3-channel image, a pixel has 24 bits. So when converting that to the SDL meaning of depth, we get 8 * 3 = 24 bits.

The image was 24 bits after all, which SDL supports. So converting the image to SDL is as simple as:

SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)opencvimg->imageData,
                opencvimg->width,
                opencvimg->height,
                opencvimg->depth*opencvimg->nChannels,
                opencvimg->widthStep,
                0xff0000, 0x00ff00, 0x0000ff, 0
                );
return surface;

Sorry for the confusion, I hope this helps anybody searching for the same answer.

Other links of interest: http://www.libsdl.org/cgi/docwiki.cgi/Pixel_Access
And the complete subroutine at: http://paster.dazjorz.com/?p=3714

dazjorz
A: 

Hello,

we are french, and with your code you have saved our project !!!!

we love you !!!

pierre

laurent

♥♥♥ ♥♥♥

A: 

Good job. Thank you. :) By the way, it should work also passing 0 (zero) to [RGBA]-mask parameters. It tells SDL to use default masks, and the default mask for the alpha channel is zero.

A: 

First of all: Thanks!!

Second: It works perfectly with 3 Channel images but I want to display a Single-Channel-IplImage

so there we go:

SDL_Surface *single_channel_ipl_to_surface (IplImage *opencvimg)
{
    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)opencvimg->imageData,
                           opencvimg->width,
                           opencvimg->height,
                           opencvimg->depth*opencvimg->nChannels,
                           opencvimg->widthStep,
                           1, 1, 1 ,0);
    return surface;
}
az
A: 

Hello,

How can i convert an SDL_Surface to an OpenCV IplImage?

Thanks

Iñaki