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:
- 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.
-
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.