wrong colors with Xv extension and image format id: 0x59565955 (UYVY) from an rgb mapping
Tomas Carnecky
tom at dbservice.com
Thu Jan 22 02:36:59 PST 2009
On 01/22/2009 11:26 AM, Amos Tibaldi wrote:
>
>
> 2009/1/22 Tomas Carnecky <tom at dbservice.com <mailto:tom at dbservice.com>>
>
> On 01/22/2009 06:15 AM, Amos Tibaldi wrote:
>
>
> Hello,
> I am trying to use the Xv extension in order to display images on
> windows. I have obtained the image formats with
> xvc.fo <http://xvc.fo> <http://xvc.fo> = XvListImageFormats(
> xvc.display, xvc.port, (int
>
> *)&formats );
> and I have chosen the format
> id: 0x59565955 (UYVY)
> guid: 55595659-0000-0010-8000-00aa00389b71
> bits per pixel: 16
> number of planes: 1
> type: YUV (packed)
>
>
> [snip]
>
>
> and to display the image with
> void XVWindow::Redraw()
> {
> unsigned short int u, y, v;
> RGBToUYVY(255,255,0,&u,&y,&v);
> unsigned short int thecolor = u << 12 | y << 8 | v << 4 | y;
>
> for ( int y=0; y<ImageHeight; y++ )
> for ( int x=0; x<ImageWidth; x++ )
> ((unsigned short int *)BGimage->data)[ y * ImageWidth + x ] =
> thecolor;
>
> counter++;
> XvPutImage( xvc.display, xvc.port, window, gc,
> BGimage, 0, 0, ImageWidth, ImageHeight,
> 0, 0, WindowWidth, WindowHeight );
> }
>
>
> I think you are confused by 'bits per pixel: 16' in the Xv format
> list. Your code in :Redraw() that composes the pixel is wrong. I
> know I couldn't explain it better, so I'm including a link to a
> website that explains it pretty well:
> http://www.fourcc.org/yuv.php#YUY2
> (Each macropixel is 32 bits, so each of the YUV components is 8 bit
> and not 4 like you used in your code)
>
> tom
>
>
> Hello, BGImage->data_size is equal to w x h x 2 bytes (2B per pixel in
> the data allocated), and X has calculated it. Moreover I have tried even
> with
> <<24 |<<16|<<8 and the thing is the same. Are you sure of that?
>
Yes, I'm sure of that.
There's one Y per pixel, U and V are downsampled (one U and one V per
two pixels). You need to process two pixels at once. Y0 and Y1 is
separate for each pixel, U0 and V0 is for both pixels.
Your code should be:
for ( int x=0; x<ImageWidth/2; x+=2 ) {
// get r,g,b of pixel one, convert that to Y0
// get r,g,b of pixel two, convert that to Y1
// average of r,g,b of pixel one+two, convert that to U0 and V0
// assuming BGimage->data is of type 'unsigned char', eg. 8 bit
// now we write one 'macropixel' or two 'screen-pixels'
// that's 32bits, but because it's two screen pixels, the effective
// 'bits per pixel' is 16.
BGimage->data[ y * ImageWidth + (x + 0) ] = Y0;
BGimage->data[ y * ImageWidth + (x + 1) ] = U0;
BGimage->data[ y * ImageWidth + (x + 2) ] = Y1;
BGimage->data[ y * ImageWidth + (x + 3) ] = V0;
}
More information about the xorg
mailing list