首页 新闻 会员 周边 捐助

YUV 420转RGB

0
悬赏园豆:30 [已解决问题] 解决于 2010-08-17 21:50

在做android项目是设计到了视频传输 实时将摄像头视频传输到C#写的服务端,视频以帧的形式传回 是一个 YUV420格式的 字节数组 现在需要再服务器端还原成图片 ,在网上找了一些算法 但是不会用 对图像这一块不熟悉 希望高手相助。

tandly的主页 tandly | 初学一级 | 园豆:17
提问于:2010-08-17 10:42
< >
分享
最佳答案
1

这里有个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]可以正常转换,已测试通过.

 

namespace GraphicsConsoleApplication
{
class Program
{
static double[,] YUV2RGB_CONVERT_MATRIX = new double[3, 3] { { 1, 0, 1.4022 }, { 1, -0.3456, -0.7145 }, { 1, 1.771, 0 } };

static void Main(string[] args)
{
int width = 352;
int height = 288;
int imgSize = width * height;
int frameSize = imgSize + (imgSize >> 1);

byte[] yuv = new byte[frameSize];
byte[] rgb = new byte[3 * imgSize];

using (FileStream fs = File.OpenRead("E:\\cer\\tempete.cif"))
{
int frame = (int)fs.Length / frameSize;
using (BinaryReader br = new BinaryReader(fs))
{
int index = 0;
while (br.PeekChar() != -1)
{
// 循环读取每一桢
br.Read(yuv, 0, frameSize);

// 转换为 RGB
ConvertYUV2RGB(yuv, rgb, width, height);

// 写 BMP 文件。
WriteBMP(rgb, width, height, string.Format("E:\\cer\\YUV2BMP\\yuv2bmp_{0}.bmp", index++));
}
}
}
}

/// <summary>
/// 将转换后的 RGB 图像数据按照 BMP 格式写入文件。
/// </summary>
/// <param name="rgbFrame">RGB 格式图像数据。</param>
/// <param name="width">图像宽(单位:像素)。</param>
/// <param name="height">图像高(单位:像素)。</param>
/// <param name="bmpFile"> BMP 文件名。</param>
static void WriteBMP(byte[] rgbFrame, int width, int height, string bmpFile)
{
// 写 BMP 图像文件。
int yu = width * 3 % 4;
int bytePerLine = 0;
yu
= yu != 0 ? 4 - yu : yu;
bytePerLine
= width * 3 + yu;

using (FileStream fs = File.Open(bmpFile, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
bw.Write(
'B');
bw.Write(
'M');
bw.Write(bytePerLine
* height + 54);
bw.Write(
0);
bw.Write(
54);
bw.Write(
40);
bw.Write(width);
bw.Write(height);
bw.Write((
ushort)1);
bw.Write((
ushort)24);
bw.Write(
0);
bw.Write(bytePerLine
* height);
bw.Write(
0);
bw.Write(
0);
bw.Write(
0);
bw.Write(
0);

byte[] data = new byte[bytePerLine * height];
int gIndex = width * height;
int bIndex = gIndex * 2;

for (int y = height - 1, j = 0; y >= 0; y--, j++)
{
for (int x = 0, i = 0; x < width; x++)
{
data[y
* bytePerLine + i++] = rgbFrame[bIndex + j * width + x]; // B
data[y * bytePerLine + i++] = rgbFrame[gIndex + j * width + x]; // G
data[y * bytePerLine + i++] = rgbFrame[j * width + x]; // R
}
}

bw.Write(data,
0, data.Length);
bw.Flush();
}
}
}

/// <summary>
/// 将一桢 YUV 格式的图像转换为一桢 RGB 格式图像。
/// </summary>
/// <param name="yuvFrame">YUV 格式图像数据。</param>
/// <param name="rgbFrame">RGB 格式图像数据。</param>
/// <param name="width">图像宽(单位:像素)。</param>
/// <param name="height">图像高(单位:像素)。</param>
static void ConvertYUV2RGB(byte[] yuvFrame, byte[] rgbFrame, int width, int height)
{
int uIndex = width * height;
int vIndex = uIndex + ((width * height) >> 2);
int gIndex = width * height;
int bIndex = gIndex * 2;

int temp = 0;

for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// R分量
temp = (int)(yuvFrame[y * width + x] + (yuvFrame[vIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[0, 2]);
rgbFrame[y
* width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp));

// G分量
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]);
rgbFrame[gIndex
+ y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp));

// B分量
temp = (int)(yuvFrame[y * width + x] + (yuvFrame[uIndex + (y / 2) * (width / 2) + x / 2] - 128) * YUV2RGB_CONVERT_MATRIX[2, 1]);
rgbFrame[bIndex
+ y * width + x] = (byte)(temp < 0 ? 0 : (temp > 255 ? 255 : temp));
}
}
}
}
}
收获园豆:30
Launcher | 高人七级 |园豆:45050 | 2010-08-17 10:49
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册