Linux下YVU420转MP4工具下载,yuv420p转jpg linux(纯C语言实现)

author : quinncy(博客园)

最近在做一个关于图像采集的项目,需要将yuv420p的图像转换成jpg格式进行传输

在网上看到了很多方法,如利用libjpeg,ffmpeg等

偶然在论坛上看到了有人的博客里面写了利用纯C语言完成图像转换,

如果移植到arm板上就不需要安装各种库支持,因此打算试试

操作平台:ubuntu16.04

这是从论坛上下载的源代码

由于我在项目中采集到的图片是yuv420p格式的,因此需要对代码进行修改

先说test.c

里面有一个get_Y_U_V()函数

实现的功能是将图像文件的在一个数组里面的yuv数据分别读取到in_y,in_u,in_v里面

核心部分是下列代码:

1 int i = 0;2 int y_n =0;3 int u_n =0;4 int v_n =0;5 int u = 0;6 int v = 2;7

8 while(i

不难看出,图像文件中的存储格式为UYUV格式的!

但是由于我在项目中生成的是YUV420p格式的图像,因此需要修改这部分的代码

yuv420p文件存储格式如下:

234dd98297831630ec7f3aedef9e1762.png

因此,我更改了get_Y_U_V函数的核心代码部分如下:

1 while(i < 1280*720)2 {3 in_Y[y_n] =rData[i];4 i++;5 y_n++;6 }7 while(i < 1280*720*5/4)8 {9 in_U[u_n] =rData[i];10 i++;11 u_n++;12 }13 while(i < 1280*720*3/2)14 {15 in_V[v_n] =rData[i];16 i++;17 v_n++;18

19 }

这样就可以分别把yuv的数据存放到in_Y,in_U,in_V里面了。

然后再说YUV2Jpg函数里面

1 unsigned char*pYBuf;2 unsigned char*pUBuf;3 unsigned char*pVBuf;4 int nYLen = nStride *height;5

6 pYBuf = (unsigned char*)malloc(nYLen);7 pUBuf = (unsigned char*)malloc(nYLen);8 pVBuf = (unsigned char*)malloc(nYLen);

定义了三个指针分别指向了nYLen大小的空间

可以得到需要将每个像素点的yuv数据分别存放在pYBuf,pUBuf,pVBuf中

比如第一个像素点的yuv数据,应该是放在pYBuf[0],pUBuf[0],pVBuf[0],依次类推

因为yuv420p的数据格式中,y的数据刚好等于图像大小,最容易处理

而u,v数据是4个像素点共用一组数据,因此需要对应拓展存储到数组的相应位置

拓展的函数在processUV()

1 int i=0;2 while(i

这是论坛源代码里面的处理函数

由于UYUV格式里面的数据是两个像素点共用一组uv数据,因此上面的处理应该很容易理解

而我所用的是yuv420p,需要四个像素点共用,因此修改函数为如下:

1 inti,j;2 int count = 0;3 for(i = 0; i < height; i+=2)4 {5 for(j = 0; j < nStride; j+=2)6 {7 pUVBuf[i * width + j] =pTmpUVBuf[count];8 pUVBuf[i * width + j + 1] =pTmpUVBuf[count];9 pUVBuf[i * width + j + width] =pTmpUVBuf[count];10 pUVBuf[i * width + j + width + 1] =pTmpUVBuf[count];11 count++;12 }13 }

这样处理之后,就可以将uv数据分别与像素点对应起来!

下面将main函数贴出来:

1 intmain()2 {3 unsigned char* in_Y = (unsigned char*)malloc(1280*720);//4 unsigned char* in_U = (unsigned char*)malloc(1280* 720/4);//5 unsigned char* in_V = (unsigned char*)malloc(1280* 720 / 4);//6 unsigned char* pData = (unsigned char*)malloc(1280 * 720);//7 unsigned char* rData = (unsigned char*)malloc(1280*720*3/2);8

9 unsigned long dwSize = 0;10 FILE *rfp = fopen("./00001.yuv","rb");11 if(NULL ==rfp)12 fprintf(stderr,"fopen fp error:%s\n",strerror(errno));13 fread(rData,1280*720*3/2,1,rfp);14 get_Y_U_V(rData,in_Y,in_U,in_V,1280,720);15

16

17 YUV2Jpg(in_Y,in_U,in_V,1280,720,100,1280,pData,&dwSize);18 FILE *fp = fopen("2.jpg","wb");19 fwrite(pData,dwSize,1,fp);20 fclose(fp);21

22 free(rData);23 free(in_Y);24 free(in_U);25 free(in_V);26 free(pData);27

28 return 0;29 }

修改00001.yuv部分为你的yuv图像路径与文件名

再将图像的大小改为你的图像数据(我用的是1280x720的)

应该就可以生成2.jpg格式的图像了

注:

这个在linux(ubuntu16.04)上面使用gcc编译后已经验证成功,可以将00001.yuv格式图像转换为2.jpg

但是使用arm-linux-gcc编译后,在arm板上执行不了,会出现内存不够的现象

尝试使用malloc后,内存问题解决,但是又发现执行时间太长(大概1个半小时左右),

打算用在arm板上的慎用!!!

完整代码已经上传到github上面,里面包含测试文件00001.yuv文件,以及生成的2.jpg图像,链接如下:

现在已经通过libjpeg实现arm板上面的yuv420p到jpg的图像转换,后面会写相关的博客~~

要将 YVU420SP 格式的图像换为 YUV 数据格式,然后再将 YUV 数据换为 RGB 数据格式,并最终将 RGB 数据写入图像文件,您可以使用以下代码: ```cpp #include <opencv2/opencv.hpp> int main() { // 读取 YVU420SP 格式的图像 cv::Mat yvuImage = cv::imread("input.yvu", cv::IMREAD_UNCHANGED); // 提取 Y 分量 cv::Mat yImage(yvuImage.rows, yvuImage.cols, CV_8UC1); cv::extractChannel(yvuImage, yImage, 0); // 提取 U 和 V 分量 cv::Mat uvImage(yvuImage.rows / 2, yvuImage.cols, CV_8UC2); cv::extractChannel(yvuImage, uvImage, 1); // 合并 U 和 V 分量,形成 YUV420P 数据 std::vector<cv::Mat> yuvChannels = {yImage, uvImage}; cv::Mat yuvImage; cv::merge(yuvChannels, yuvImage); // 将 YUV420P 数据换为 RGB 数据 cv::Mat rgbImage; cv::cvtColor(yuvImage, rgbImage, cv::COLOR_YUV2BGR_I420); // 保存换后的 RGB 图像 cv::imwrite("output.jpg", rgbImage); return 0; } ``` 在上述代码中,我们首先使用 `cv::imread` 函数读取一个 YVU420SP 格式的图像(例如,名为 "input.yvu" 的文件)。然后,我们使用 `cv::extractChannel` 函数分别提取 Y、U 和 V 分量。接下来,我们将 U 和 V 分量合并为一个 `cv::Mat` 对象 `yuvImage`,形成 YUV420P 数据。最后,我们使用 `cv::cvtColor` 函数将 YUV420P 数据换为 RGB 数据,并使用 `cv::imwrite` 函数将换后的 RGB 图像保存为图像文件(例如,名为 "output.jpg" 的文件)。 请注意,上述代码中的文件路径和名称需要根据实际情况进行修改,并且需要正确安装和链接 OpenCV 库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值