Reputation: 1148
In Android, I have a byte[]
of individual r,g,b,a colors that make up the pixels of an image.
I need to convert these colors to YUV420 planar or semi-planar (depending on the device) before I can use Android's MediaCodec and MediaMuxer to create an MP4 of these images.
I'm currently testing on my Nexus 10 which reports that it uses COLOR_FormatYUV420Planar
.
Here's the code I have to convert RGB to YUV420 planar:
private void convertRGBAtoYUV420P(byte[] rgba, byte[] yuv, int width, int height)
{
final int frameSize = width * height;
final int chromasize = frameSize / 4;
int yIndex = 0;
int uIndex = frameSize;
int vIndex = frameSize + chromasize;
int R, G, B, Y, U, V;
int index = 0;
int rgbaIndex = 0;
for (int j = 0; j < height; j++)
{
for (int i = 0; i < width; i++)
{
R = rgba[rgbaIndex++] + 128; // My rgba bytes are -128 to 127
G = rgba[rgbaIndex++] + 128;
B = rgba[rgbaIndex++] + 128;
rgbaIndex++; // skip A
Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
yuv[yIndex++] = (byte)clamp(Y);
if (j % 2 == 0 && index % 2 == 0)
{
yuv[uIndex++] = (byte)clamp(U);
yuv[vIndex++] = (byte)clamp(V);
}
index++;
}
}
}
I found this code from this blog.
It works, just the color isn't correct. White is gray and all other colors are just wrong. Can't quite figure out what is wrong in the code above, but I feel like it might have to do with the fact that my r,g,b,a bytes are in a range from -128 to 127, but I try to correct that by adding 128 to them.
Second question, how would the above code change when I need to convert from RGB to YUV420 semi-planar instead?
Upvotes: 3
Views: 3237
Reputation: 1698
Just so there's an answer to go with this question.
The problem is that adding 128 to the byte values doesn't restore it's original value.
Because the color space is defined in values between 0 and 255. They are not simply shifted downwards towards negative number to get it to fit in a signed byte. All of the higher values for the colors (> 127) are encoded to fit in a signed byte, ranging from -128 to -1.
In order to restore the value to what you want, you need to apply the & 0xff
mask to each of the byte values.
Upvotes: 5