C# yuv数据转 RGB bmp文件保存
1 namespace GraphicsConsoleApplication 2 { 3 class Program 4 { 5 static double[,] YUV2RGB_CONVERT_MATRIX = new double[3, 3] { { 1, 0, 1.4022 }, { 1, -0.3456, -0.7145 }, { 1, 1.771, 0 } }; 6 7 static void Main(string[] args) 8 { 9 int width = 352; 10 int height = 288; 11 int imgSize = width * height; 12 int frameSize = imgSize + (imgSize >> 1); 13 14 byte[] yuv = new byte[frameSize]; 15 byte[] rgb = new byte[3 * imgSize]; 16 17 using (FileStream fs = File.OpenRead("E:\\cer\\tempete.cif")) 18 { 19 int frame = (int)fs.Length / frameSize; 20 using (BinaryReader br = new BinaryReader(fs)) 21 { 22 int index = 0; 23 while (br.PeekChar() != -1) 24 { 25 // 循环读取每一桢 26 br.Read(yuv, 0, frameSize); 27 28 // 转换为 RGB 29 ConvertYUV2RGB(yuv, rgb, width, height); 30 31 // 写 BMP 文件。 32 WriteBMP(rgb, width, height, string.Format("E:\\cer\\YUV2BMP\\yuv2bmp_{0}.bmp", index++)); 33 } 34 } 35 } 36 } 37 38 /// <summary> 39 /// 将转换后的 RGB 图像数据按照 BMP 格式写入文件。 40 /// </summary> 41 /// <param name="rgbFrame">RGB 格式图像数据。</param> 42 /// <param name="width">图像宽(单位:像素)。</param> 43 /// <param name="height">图像高(单位:像素)。</param> 44 /// <param name="bmpFile"> BMP 文件名。</param> 45 static void WriteBMP(byte[] rgbFrame, int width, int height, string bmpFile) 46 { 47 // 写 BMP 图像文件。 48 int yu = width * 3 % 4; 49 int bytePerLine = 0; 50 yu = yu != 0 ? 4 - yu : yu; 51 bytePerLine = width * 3 + yu; 52 53 using (FileStream fs = File.Open(bmpFile, FileMode.Create)) 54 { 55 using (BinaryWriter bw = new BinaryWriter(fs)) 56 { 57 bw.Write('B'); 58 bw.Write('M'); 59 bw.Write(bytePerLine * height + 54); 60 bw.Write(0); 61 bw.Write(54); 62 bw.Write(40); 63 bw.Write(width); 64 bw.Write(height); 65 bw.Write((ushort)1); 66 bw.Write((ushort)24); 67 bw.Write(0); 68 bw.Write(bytePerLine * height); 69 bw.Write(0); 70 bw.Write(0); 71 bw.Write(0); 72 bw.Write(0); 73 74 byte[] data = new byte[bytePerLine * height]; 75 int gIndex = width * height; 76 int bIndex = gIndex * 2; 77 78 for (int y = height - 1, j = 0; y >= 0; y--, j++) 79 { 80 for (int x = 0, i = 0; x < width; x++) 81 { 82 data[y * bytePerLine + i++] = rgbFrame[bIndex + j * width + x]; // B 83 data[y * bytePerLine + i++] = rgbFrame[gIndex + j * width + x]; // G 84 data[y * bytePerLine + i++] = rgbFrame[j * width + x]; // R 85 } 86 } 87 88 bw.Write(data, 0, data.Length); 89 bw.Flush(); 90 } 91 } 92 } 93 94 /// <summary> 95 /// 将一桢 YUV 格式的图像转换为一桢 RGB 格式图像。 96 /// </summary> 97 /// <param name="yuvFrame">YUV 格式图像数据。</param> 98 /// <param name="rgbFrame">RGB 格式图像数据。</param> 99 /// <param name="width">图像宽(单位:像素)。</param> 100 /// <param name="height">图像高(单位:像素)。</param> 101 static void ConvertYUV2RGB(byte[] yuvFrame, byte[] rgbFrame, int width, int height) 102 { 103 int uIndex = width * height; 104 int vIndex = uIndex + ((width * height) >> 2); 105 int gIndex = width * height; 106 int bIndex = gIndex * 2; 107 108 int temp = 0; 109 110 for (int y = 0; y < height; y++) 111 { 112 for (int x = 0; x < width; x++) 113 { 114 // R分量 115 temp = (int)(yuvFrame[y * width + x] + (yuvFrame[vIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[0, 2]); 116 rgbFrame[y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp)); 117 118 // G分量 119 temp = (int)(yuvFrame[y * width + x] + (yuvFrame[uIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[1, 1] + (yuvFrame[vIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[1, 2]); 120 rgbFrame[gIndex + y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp)); 121 122 // B分量 123 temp = (int)(yuvFrame[y * width + x] + (yuvFrame[uIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[2, 1]); 124 rgbFrame[bIndex + y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp)); 125 } 126 } 127 } 128 } 129 }
这里有个C++嵌汇编的代码:
http://blog.lmtw.com/b/guanyhu/archives/2006/38878.html
这里有个C++的代码:
http://blog.csdn.net/zsJum/archive/2007/11/18/1891155.aspx
你可以把这两个编译成dll,然后在C#中通过P/Invoke调用.
要不,你也可以把它改成C#版本的.第二个改起来容易.
根据此论坛[http://topic.csdn.net/u/20071017/12/6de49307-07e5-42fe-9e7e-047ab918cae6.html]的回答,我修改了C#版本,使用其提供的文件[http://trace.eas.asu.edu/yuv/tempete.zip]可以正常转换,已测试通过.
来源:转载