SDL_CreateRGBSurfaceFrom

Hello,
I was wondering about the correct behavior of SDL_CreateRGBSurfaceFrom().
Here’s a code example:

Code:

SDL_Surface * dup (SDL_Surface *img)
{
Uint8 *pixels;
SDL_Surface *ret;

if (SDL_MUSTLOCK(img))
	SDL_LockSurface(img);

pixels = malloc(img->h * img->pitch * img->format->BytesPerPixel);
memcpy(pixels, img->pixels, img->h * img->pitch * img->format->BytesPerPixel);

if (SDL_MUSTLOCK(img))
	SDL_UnlockSurface(img);

ret = SDL_CreateRGBSurfaceFrom(pixels, img->w, img->h, img->format->BytesPerPixel, img->pitch,
			       img->format->Rmask, img->format->Gmask, img->format->Bmask, img->format->Amask);

return ret;

}

int main (void)
{
SDL_Surface *screen, *img1, *img2;

SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);

img1 = IMG_Load("test.png");
img2 = dup(img1);

printf("BytesPerPixel (img1): %d\n", img1->format->BytesPerPixel);
printf("BytesPerPixel (img2): %d\n", img2->format->BytesPerPixel);

return 0;

}

Running this program with a test.png of 24-bit depth gives me

BytesPerPixel (img1): 3
BytesPerPixel (img2): 1

So I should copy PixelFormat into the new surface to get it right.
And do checks for a palettized image for which the palette should be copied also, perhaps.
Is this right?
And why this function does not create a PixelFormat, while the SDL_CreateRGBSurface do?
I’m using SDL 1.2.13.
Thanks,
tano

Hi while using SDl2.0 and ffmpeg i haev managed to display the image
that was originally in yuvp420 format to RGB using the
SDL_CreateRGBSurfaceFrom as shown in the code below.

The problem is that i get three images(R G and B) next to each other
rather than only one image with the three layers overlaped in the
displayed window.
What is wrong ?
thanks?


texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24,
SDL_TEXTUREACCESS_STREAMING, codec_context->width,
codec_context->height);//3 plane texture

 frame = avcodec_alloc_frame();

 pFrameRGB = avcodec_alloc_frame();
     if (pFrameRGB == NULL)
     {
      printf("Cannot allocate pFrame\n");
      exit(-1);
     }

     unsigned char* pixels;
     int pitch;
     uint8_t *buffer;
     int numBytes;
     // Determine required buffer size and allocate buffer
     numBytes=avpicture_get_size(PIX_FMT_RGB24, w,h);
     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));


     // Assign appropriate parts of buffer to image planes in pFrameRGB
     // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
     // of AVPicture
     avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,w, h);



     while (av_read_frame(format_context, &avpacket) >= 0) {

     	//if(avpacket.stream_index==audiostream) {
     	  //      NSLog(@"Audio.. i'll solve the video first...");
     	    //} else
     	if (avpacket.stream_index == videostream) {
     		// Video stream packet


     		avcodec_decode_video2(codec_context, frame, &frame_finished, 

&avpacket);

     		if(frame_finished)
     		{
     			if(avpicture_alloc(&picture, PIX_FMT_RGB24, w,h) < 0){
     				fprintf(stderr, "problem allocating picture!\n");
     				exit(1);
     			}

     			img_convert_ctx  = sws_getCachedContext(img_convert_ctx,
     					w,
     					h,
     					//codec_context->pix_fmt,
     					PIX_FMT_YUV420P,
     					w,
     					h,
     					PIX_FMT_RGB24,
     					SWS_BICUBIC,
     					NULL,
     					NULL,
     					NULL);

     			if (img_convert_ctx == NULL)
     			{
     				fprintf(stderr, "Cannot initialize the conversion context!\n");
     				exit(1);
     			}



     			int s = sws_scale(
     					img_convert_ctx,
     					frame->data,
     					frame->linesize,
     					0,
     					h,
     					picture.data,
     					picture.linesize);



     			if (!texture) {
     				fprintf(stderr, "Couldn't set create texture: %s\n", 

SDL_GetError());
exit(-1);
}

     			 SDL_Surface *image = SDL_CreateRGBSurfaceFrom(
     			        					 	 picture.data[0],
     			        					 	w,
     			        					 	h,
     			        					 	24,
     			        					 	w,
     			        					 	 0, 0, 0, 0);
     			 SDL_BlitSurface(image, 0, window, 0);
     			 SDL_LockSurface(image);
     		     texture = SDL_CreateTextureFromSurface(renderer, image);



     		     if (!texture) {
     		    	 fprintf(stderr, "Couldn't set create texture: %s\n", 

SDL_GetError());
exit(-1);
}

     		     if (SDL_RenderCopy(renderer, texture, NULL, NULL) < 0)
     		     {
     		    	 fprintf(stderr, "SDL_RenderCopy FAILED: %s\n", 

SDL_GetError());
return -1;
}

     		     SDL_RenderPresent(renderer);

     		     SDL_Delay(20); // Video delay
     		     avpicture_free(&picture);

     		     SDL_UnlockTexture(texture);

     		}//frame
     av_free_packet(&avpacket);

     	}//avpacket

David martin wrote:

                 SDL_Surface *image = SDL_CreateRGBSurfaceFrom(
                                                  picture.data[0],
                                                 w,
                                                 h,
                                                 24,
                                                 w,
                                                  0, 0, 0, 0);

I believe your pitch (fifth argument) should be w * 3, not w, as in
24-bit RGB there are 3 bytes for each pixel.

From the SDL documentation:

“Pitch is the size of the scanline of the surface, in bytes, i.e.
widthInPixels*bytesPerPixel.”

Great that did the trick. I have modified the pitch to w*3 so that the
surface looks like that now:
SDL_Surface image = SDL_CreateRGBSurfaceFrom(
picture.data[0],
w,
h,
24,
w
3,
0, 0, 0, 0);

Got correct image !!!
thanksOn 03/14/2012 05:31 PM, Bl0ckeduser wrote:

David martin wrote:

SDL_Surface *image = SDL_CreateRGBSurfaceFrom(
picture.data[0],
w,
h,
24,
w,
0, 0, 0, 0);

I believe your pitch (fifth argument) should be w * 3, not w, as in
24-bit RGB there are 3 bytes for each pixel.

From the SDL documentation:

“Pitch is the size of the scanline of the surface, in bytes, i.e.
widthInPixels*bytesPerPixel.”

Got correct image !!!

Please note that you are doing far more copies/allocations than needed.

Also you are doing them on every frame, and if you want 25fps on "slower"
systems that code will give you some problems.

Ideally you can blit with swscale from the original frame data to your
texture without the two intermediate passes you are doing.–
Bye,
Gabry

Can you show me how ?On 03/15/2012 01:34 PM, Gabriele Greco wrote:

Got correct image !!!

Please note that you are doing far more copies/allocations than needed.

Also you are doing them on every frame, and if you want 25fps on
"slower" systems that code will give you some problems.

Ideally you can blit with swscale from the original frame data to your
texture without the two intermediate passes you are doing.


Bye,
Gabry


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org