1.1、Nv12转Bitmap
int w = 1920;
int h = 1080;
int iImageSize = w * h * 3;
byte[] bRgbData = new byte[iImageSize];
int iYuvSize = iImageSize / 2;
byte[] bYuvData = new byte[iYuvSize];
nv12ToRgb(bRgbData, bYuvData, w, h);
Bitmap ShowBitmap = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
BitmapData bmpData = ShowBitmap.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
System.Runtime.InteropServices.Marshal.Copy(bRgbData, 0, bmpData.Scan0, iImageSize);
ShowBitmap.UnlockBits(bmpData); // 解锁内存区域
1.2、Nv12转Bitmap函数
private void nv12ToRgb(byte[] bRgbData, byte[] bYuvData, int w, int h)
{
int iPosUV = 0;
int iStepY = w;
int iStepUV = w;
int iStepRGB = w * 3;
int iOffsetUV = w * h;
int iIndex1 = 0;
int iIndex2 = 0;
for (int i = 0; i < h; i += 2)
{
for (int j = 0; j < w; j += 2)
{
int y11 = Math.Max(0, (int)(bYuvData[i * iStepY + j + 0])) << 20;
int y12 = Math.Max(0, (int)(bYuvData[i * iStepY + j + 1])) << 20;
int y21 = Math.Max(0, (int)(bYuvData[(i + 1) * iStepY + j + 0])) << 20;
int y22 = Math.Max(0, (int)(bYuvData[(i + 1) * iStepY + j + 1])) << 20;
int u = (int)(bYuvData[iPosUV * iStepUV + iOffsetUV + j + 0]) - 128;
int v = (int)(bYuvData[iPosUV * iStepUV + iOffsetUV + j + 1]) - 128;
int ruv = 524288 + 2130771 * v;
int guv = 524288 - 413812 * v - 608826 * u;
int buv = 524288 + 1195254 * u;
//填第1行的RGB的两个像素
bRgbData[i * iStepRGB + iIndex1 + 0] = LimitValue((y11 + buv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 1] = LimitValue((y11 + guv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 2] = LimitValue((y11 + ruv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 3] = LimitValue((y12 + buv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 4] = LimitValue((y12 + guv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 5] = LimitValue((y12 + ruv) >> 20);
iIndex1 += 6;
//填第2行的RGB的两个像素
bRgbData[(i + 1) * iStepRGB + iIndex2 + 0] = LimitValue((y21 + buv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 1] = LimitValue((y21 + guv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 2] = LimitValue((y21 + ruv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 3] = LimitValue((y22 + buv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 4] = LimitValue((y22 + guv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 5] = LimitValue((y22 + ruv) >> 20);
iIndex2 += 6;
}
iPosUV++;
iIndex1 = 0;
iIndex2 = 0;
}
}
//转出来的Rgb值范围0 - 255
private byte LimitValue(int iValue)
{
if (iValue < 0) return 0;
if (iValue > 255) return 255;
else return (byte)iValue;
//return (byte)(iValue <= 255 ? iValue : iValue > 0 ? 255 : 0);
}
2.1、Yuv422转Bitmap
int w = 1920;
int h = 1080;
int iImageSize = w * h * 3;
byte[] bRgbData = new byte[iImageSize];
int iYuvSize = iImageSize * 2;
byte[] bYuvData = new byte[iYuvSize];
Yuv2Rgb(bRgbData, bYuvData, w, h);
Bitmap ShowBitmap = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
BitmapData bmpData = ShowBitmap.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
System.Runtime.InteropServices.Marshal.Copy(bRgbData, 0, bmpData.Scan0, iImageSize);
ShowBitmap.UnlockBits(bmpData); // 解锁内存区域
2.2、Yuv422转Bitmap函数
private void nv12ToRgb(byte[] bRgbData, byte[] bYuvData, int w, int h)
{
int iPosUV = 0;
int iStepY = w;
int iStepUV = w;
int iStepRGB = w * 3;
int iOffsetUV = w * h;
int iIndex1 = 0;
int iIndex2 = 0;
for (int i = 0; i < h; i += 2)
{
for (int j = 0; j < w; j += 2)
{
int y11 = Math.Max(0, (int)(bYuvData[i * iStepY + j + 0])) << 20;
int y12 = Math.Max(0, (int)(bYuvData[i * iStepY + j + 1])) << 20;
int y21 = Math.Max(0, (int)(bYuvData[(i + 1) * iStepY + j + 0])) << 20;
int y22 = Math.Max(0, (int)(bYuvData[(i + 1) * iStepY + j + 1])) << 20;
int u = (int)(bYuvData[iPosUV * iStepUV + iOffsetUV + j + 0]) - 128;
int v = (int)(bYuvData[iPosUV * iStepUV + iOffsetUV + j + 1]) - 128;
int ruv = 524288 + 2130771 * v;
int guv = 524288 - 413812 * v - 608826 * u;
int buv = 524288 + 1195254 * u;
//填第1行的RGB的两个像素
bRgbData[i * iStepRGB + iIndex1 + 0] = LimitValue((y11 + buv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 1] = LimitValue((y11 + guv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 2] = LimitValue((y11 + ruv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 3] = LimitValue((y12 + buv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 4] = LimitValue((y12 + guv) >> 20);
bRgbData[i * iStepRGB + iIndex1 + 5] = LimitValue((y12 + ruv) >> 20);
iIndex1 += 6;
//填第2行的RGB的两个像素
bRgbData[(i + 1) * iStepRGB + iIndex2 + 0] = LimitValue((y21 + buv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 1] = LimitValue((y21 + guv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 2] = LimitValue((y21 + ruv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 3] = LimitValue((y22 + buv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 4] = LimitValue((y22 + guv) >> 20);
bRgbData[(i + 1) * iStepRGB + iIndex2 + 5] = LimitValue((y22 + ruv) >> 20);
iIndex2 += 6;
}
iPosUV++;
iIndex1 = 0;
iIndex2 = 0;
}
}
//转出来的Rgb值范围0 - 255
private byte LimitValue(int iValue)
{
if (iValue < 0) return 0;
if (iValue > 255) return 255;
else return (byte)iValue;
//return (byte)(iValue <= 255 ? iValue : iValue > 0 ? 255 : 0);
}