Our website is made possible by displaying online advertisements to our visitors.
Please consider supporting us by disabling your ad blocker or buy a VSO converter software :)

# Converting YUV422 to YUV411 error

Thread
1. Hi
Can anybody tell me what is wrong with this C language function to convert YUV422 to YUV411? The image has the right definition but the colors are all mess up.
static int conv422to411(char * src,char * dst, int width, int height)

{
int y1,y2, y3, y4,u,v;
char * dst_inicial=dst;
int rgb1, rgb2, rgb3, rgb4;
int i=0;
char buffer_yuv[12];
unsigned char *clp=NULL;
{
/* intra frame */
for (i=0; i< width*height*2; i+=8)
{
u=src[i];
y1=src[i+1];
v =src[i+2];
y2=src[i+3];
y3=src[i+5];
y4=src[i+7];
// move to YUV 411 buffer
*dst++ = u; // move U
*dst++ = y1; // move Y1
*dst++ = v; // move V
*dst++ = y2; // move y2
*dst++ = y3; // move y3
*dst++ = y4; // move y4
}
}

Thanks
2. What is your YUV 4:2:2 format? YUY2? UYVY? And the 4:1:1 format? You intend to point sample U and Y?
3. Thanks for your reply.

The YUV 4:2:2's format is UYVY..
The YUV 4:1:1's format is UYVYYY

I didn't understand this question : You intend to point sample U and Y?
4. Are you sure the 4:1:1 format is YUVYYY, not UYYVYY?

Sorry, I made a typo. I meant to ask if you wanted to point sample U and V (not Y). You're reducing two U values to one U value, and two V values to one V value. You're code is doing so by throwing away one U and one V.
5. Sorry the 4:1:1 format is UYVYYY. I included the code for the 4:1:1 to RGB decoder in C# below.
I just want to make the 411 image to be as close to the original 422 is.
To be honest I just throw U and V because I don't know to think a better procedure.

namespace YUYDecoder
{
public class YUYDecoder
{
private int clip(int x){
if (x>255) x=255;
else if (x<0) x=0;
return x;
}

private int get_pixel_yuv(byte y, sbyte u, sbyte v, sbyte x){
int r, g, b;
r=clip(((y<<12) + v*5743 + 2048)>>12);
g=clip(((y<<12) - u*1411 - v*2925 + 2048)>>12);
b=clip(((y<<12) + u*7258 + 2048)>>12);

r = clip(r + x);
g = clip(g + x);
b = clip(b + x);

return (r<<16)|(g<<8)|b;
}

public unsafe byte[] Decode(int width, int height, byte[] buffer, sbyte brightness)
{
byte[] acol = new byte[width * height * 4];

fixed (byte* pcol = acol, pbuf1 = buffer) {
int* col = (int *)pcol;
byte* buf1 = (byte*)pbuf1;
// Stopwatch sw = Stopwatch.StartNew();

for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x += 4, buf1 += 6)
{ UYVYYY
if (x < width)
{
*col++ = get_pixel_yuv(buf1[1], (sbyte)buf1[0], (sbyte)buf1[2], brightness);
*col++ = get_pixel_yuv(buf1[3], (sbyte)buf1[0], (sbyte)buf1[2], brightness);
*col++ = get_pixel_yuv(buf1[4], (sbyte)buf1[0], (sbyte)buf1[2], brightness);
*col++ = get_pixel_yuv(buf1[5], (sbyte)buf1[0], (sbyte)buf1[2], brightness);
}
}
}

// sw.Stop();
// long milliSec = sw.ElapsedMilliseconds;
}

return acol;
}

public bool Brighten(Bitmap b, int nBrightness)
{
// GDI+ return format is BGR, NOT RGB.
BitmapData bmData
= b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
int nVal;
byte* p = (byte*)(void*)Scan0;
int nOffset = stride - b.Width * 3;
int nWidth = b.Width * 3;
for (int y = 0; y < b.Height; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
nVal = (int)(p[0] + nBrightness);
if (nVal < 0) nVal = 0;
if (nVal > 255) nVal = 255;
p[0] = (byte)nVal;
++p;
}
p += nOffset;
}
}
b.UnlockBits(bmData);
return true;
}

}
}
6. Any idea on how I can improve the code ?
Thanks
7. So your code basically works but the colors are wrong? If you replace u and v with 128 (ie replace u=src[i]; with u=128;, and the same for v) do you get a perfect greyscale image?

I would start by changing your "char" definitions for the YUV values to "unsigned char". And the same for the "int y1,y2, y3, y4,u,v". That will prevent possible automatic sign extension problems.

Why don't you get rid of all the temp variables and change the inner loop to:

Code:
```	for (i=0; i< width*height*2; i+=8)
{
// move UYVY(*2) to UYVYYY buffer
*dst++ = src[i];   // move U
*dst++ = src[i+1]; // move Y1
*dst++ = src[i+2]; // move V
*dst++ = src[i+3]; // move y2
*dst++ = src[i+5]; // move y3
*dst++ = src[i+7]; // move y4
}```
8. Hi
I modify the code as your instruction and the image now is entirely green.
Thanks
9. It worked on a small 4x2 image when I tested it. Time for the debugger, I guess.
10. Thanks a lot for your attention. I will make some testing and post the result.
11. Make sure your UYVY image has a mod 4 width. If you're building 16 bit code you will run into overflow problems with larger images.

Statistics