How to convert an OpenCV IplImage to an SDL_Surfac

2020-07-13 07:25发布

问题:

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?

回答1:

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



回答2:

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,
                           0xffffff, 0xffffff, 0xffffff,0);
    return surface;
}