Skip to content

Instantly share code, notes, and snippets.

@irwinwilliams
Created May 27, 2021 16:55
Show Gist options
  • Save irwinwilliams/316166d9701d04828a140d478a5e007c to your computer and use it in GitHub Desktop.
Save irwinwilliams/316166d9701d04828a140d478a5e007c to your computer and use it in GitHub Desktop.
A simple C# method that _attempts_ to convert a BMP formatted byte array to NV12
public void BMPtoNV12(byte[] yuv420sp, byte[] argb, int width, int height)
{
int frameSize = width * height;
int yIndex = 0;
int uvIndex = frameSize;
uint a;
int R, G, B, Y, U, V;
int index = 0;
for (int j = 0; j < height; j++)
{
//int index = width * j;
for (int i = 0; i < width; i++)
{
a = (argb[index] & 0xff000000) >> 24; // a is not used obviously
R = (argb[index] & 0xff0000) >> 16;
G = (argb[index] & 0xff00) >> 8;
B = (argb[index] & 0xff) >> 0;
// well known RGB to YUV algorithm
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;
//NV12
//Related to I420, NV12 has one luma "luminance" plane Y and one plane with U and V values interleaved.
//In NV12, chroma planes(blue and red) are subsampled in both the horizontal and vertical dimensions by a factor of 2.
//For a 2×2 group of pixels, you have 4 Y samples and 1 U and 1 V sample.
//It can be helpful to think of NV12 as I420 with the U and V planes interleaved.
//Here is a graphical representation of NV12.Each letter represents one bit:
//For 1 NV12 pixel: YYYYYYYY UVUV
//For a 2 - pixel NV12 frame: YYYYYYYYYYYYYYYY UVUVUVUV
//For a 50 - pixel NV12 frame: Y×8×50(UV)×2×50
//For a n - pixel NV12 frame: Y×8×n(UV)×2×n
yuv420sp[yIndex++] = (byte)((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
if (j % 2 == 0 && i % 2 == 0)
{
yuv420sp[uvIndex++] = (byte)((U < 0) ? 0 : ((U > 255) ? 255 : U));
yuv420sp[uvIndex++] = (byte)((V < 0) ? 0 : ((V > 255) ? 255 : V));
}
index++;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment