RGB24->YUV Conversion && EMbedded SDL windows<newbie>

Hi, couple questions:

  1. I want to take a RGB24 image, convert it to YUV (so it can be the
    pixels member of a PSDL_Overlay). The reason I want to do this is
    because the scaling in YUV to a larger size is quite good. Am I
    going to ahve to write my own conversion routine?

RGB24Image -> YUV format (suitable for a overlay) -> Display

I looked at SDL_ConvertSurface, but I don’t think it’s what I need.

  1. I want to display (for example) two images (lets say from two
    cameras attached to my computer) in an app. I want the images to be
    embedded in the application, always in a fixed location - not free
    flowing windows. What’s the easiest way to go about this? I’m
    a sdl newbie but is there a way to attach it to a window,
    or will I need to adjust it’s position based on some event (the app
    being moved on the screen by the user for example).

    The App______________
    [ ]
    [ – – ]
    [ |a | |b | ]
    [ – – ]
    [ ]


a & b are actually beautiful YUV images. The app is equally
beautiful.

Malcolm Rodgers wrote:

Hi, couple questions:

  1. I want to take a RGB24 image, convert it to YUV (so it can be the
    pixels member of a PSDL_Overlay). The reason I want to do this is
    because the scaling in YUV to a larger size is quite good. Am I
    going to ahve to write my own conversion routine?

RGB24Image -> YUV format (suitable for a overlay) -> Display

I looked at SDL_ConvertSurface, but I don’t think it’s what I need.

  1. I want to display (for example) two images (lets say from two
    cameras attached to my computer) in an app. I want the images to be
    embedded in the application, always in a fixed location - not free
    flowing windows. What’s the easiest way to go about this? I’m
    a sdl newbie but is there a way to attach it to a window,
    or will I need to adjust it’s position based on some event (the app
    being moved on the screen by the user for example).

Well for one thing, typically PC cards that do YUV overlays also do RGB
overlays, but SDL apparently doesn’t expose this functionality.

The other thing is AFAIK PC cards also don’t typically support more than
one overlay. You could get around this by combining the two inputs side
by side in the overlay. But you might look at OpenGL as a better
alternative.

It sounds like you need this function I wrote a while back call
CreateOverlayFromSurface. I’m assuming you have the RGB image as an
SDL_Surface (called img in my example) and you will be blitting it to a
screen SDL_Surface at location in the SDL_Rect rc.

A standard way to call it is:
SDL_Overlay* ov;
ov = CreateOverlayFromSurface(img, screen);
if (ov)
{
SDL_DisplayYUVOverlay(ov, &rc);
}
It’s as easy as that. Here’s the CreateOverlayFromSurface function:

// Creates and returns a YUV Overlay from the SDL_Surface src that is
// to be blitted on to the SDL_Surface screen (scr) when doing
// a SDL_DisplayYUVOverlay.
// Uses getpixel from the SDL docs
SDL_Overlay* CreateOverlayFromSurface(SDL_Surface* src,
SDL_Surface* scr)
{
SDL_Overlay* ov = SDL_CreateYUVOverlay(src->w,
src->h,
SDL_IYUV_OVERLAY,
scr);
if (ov)
{
Uint8 R, G, B;
Uint8 Y, U, V;
Uint32 pix;
SDL_PixelFormat* fmt = src->format;

 // Lock surfaces
 SDL_LockSurface(src);
 SDL_LockYUVOverlay(ov);
 // Perform RGB->YUV conversion
 // for more details see http://www.webartz.com/fourcc/indexyuv.htm
 for (int y = 0; y < src->h; y++)
   for (int x = 0; x < src->w; x++)
   {
     pix = getpixel(src, x, y);

     // If there's a palette, look up the RGB value in the palette,
     //   otherwise get the RGB values from the pixel.
     if (fmt->palette)
     {
         SDL_Color* col = fmt->palette->colors + pix;
         R = col->r;
         G = col->g;
         B = col->b;
     }
     else
     {
         R = (pix & fmt->Rmask) >> fmt->Rshift;
         G = (pix & fmt->Gmask) >> fmt->Gshift;
         B = (pix & fmt->Bmask) >> fmt->Bshift;
     }

     Y =  (0.257 * R) + (0.504 * G) + (0.098 * B) + 16;
     U = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128;
     V =  (0.439 * R) - (0.368 * G) - (0.071 * B) + 128;

     // Plane 0 is the Y plane
     ov->pixels[0][ov->pitches[0] * y + x] = Y;

     // Only put in every other pixel for U and V planes
     if (x % 2 == 0 && y % 2 == 0)
     {
       int ay = y / 2;  // Actual x and y in the pixel data
       int ax = x / 2;
       // Plane 1 is the U plane
       ov->pixels[1][ov->pitches[1] * ay + ax] = U;

       // Plane 2 is the V plane
       ov->pixels[2][ov->pitches[2] * ay + ax] = V;
     }
   }

 SDL_UnlockYUVOverlay(ov);
 SDL_UnlockSurface(src);

}

return ov;
}

This stores the YUV information in the IYUV format, I’m not sure if this
is the best format, but it’s the easiest to understand. I hope this helps.

-Jeff
p.s. For completeness I’ll include the getpixel routine:
/*

  • Return the pixel value at (x, y)

  • NOTE: The surface must be locked before calling this!
    */
    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 */
    }
    }

Malcolm Rodgers wrote:> Hi, couple questions:

  1. I want to take a RGB24 image, convert it to YUV (so it can be the
    pixels member of a PSDL_Overlay). The reason I want to do this is
    because the scaling in YUV to a larger size is quite good. Am I
    going to ahve to write my own conversion routine?

RGB24Image -> YUV format (suitable for a overlay) -> Display

I looked at SDL_ConvertSurface, but I don’t think it’s what I need.

  1. I want to display (for example) two images (lets say from two
    cameras attached to my computer) in an app. I want the images to be
    embedded in the application, always in a fixed location - not free
    flowing windows. What’s the easiest way to go about this? I’m
    a sdl newbie but is there a way to attach it to a window,
    or will I need to adjust it’s position based on some event (the app
    being moved on the screen by the user for example).

    The App


[ ]
[ – – ]
[ |a | |b | ]
[ – – ]
[ ]

a & b are actually beautiful YUV images. The app is equally
beautiful.