概述
为了更加理解yuv,下面以YUV420图像作为例子,记录一下进行水平拼接的思路和实现
YUV420
YUV是一种原始图像格式,没有经过编码,比较方便软件处理。本文处理的图像格式为YUV420,图像数据中的亮度Y和色度UV分离,并在内存中连续存储,按照YUYV的方式进行存储。比如一张 4 × 2 图像,以YUV420sp的格式存储就是:Y1Y2Y3Y4Y5Y6Y7Y8U1V1U2V2,所占的内存空间为:width * height * 3 / 2(同理,YUV422所占的内存空间为:width * height * 2)
水平拼接
相较于垂直拼接,水平拼接稍微复杂一些,需要对图像的每一行进行处理。需要将两幅图对应行的Y连接在一起组成新的Y行,对应行的UV连接在一起组成新的UV行,再把新的UV连接到Y后面。用图片描述如下:
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *file = NULL;
FILE *yuv1 = NULL;
FILE *yuv2 = NULL;
int imgWidth = 1920;
int imgHeight = 1080;
int i = 0;
char filename[64] = {0};
snprintf(filename, sizeof(filename), "/out.yuv");
//拼接后的yuv文件
file = fopen(filename, "w+");
if (NULL == file)
return -1;
//拼接前的yuv图像1
yuv1 = fopen("/yuv001.yuv", "r");
if (NULL == yuv1)
return -1;
//拼接前的yuv图像2
yuv2 = fopen("/yuv002.yuv", "r");
if (NULL == yuv1)
return -1;
char *imgY1, *imgY2;
//开辟内存
imgY1 = (char *)malloc(imgWidth * imgHeight * 3 / 2); //yuv420
if(NULL == imgY1)
return -1;
imgY2 = (char *)malloc(imgWidth * imgHeight * 3 /2); //yuv420
if(NULL == imgY1)
return -1;
//读取拼接前的两张yuv图像数据
if((imgWidth * imgHeight *3 / 2) != fread(imgY1, 1, imgWidth * imgHeight * 3 / 2, yuv1))
return -1;
if((imgWidth * imgHeight *3 / 2) != fread(imgY2, 1, imgWidth * imgHeight * 3 / 2, yuv2))
return -1;
//水平拼接yuv420
for (i = 0; i < imgHeight; i++)
{
fwrite(imgY1, 1, imgWidth*3/2, file);
fwrite(imgY2, 1, imgWidth*3/2, file);
imgY1 += imgWidth*3/2;
imgY2 += imgWidth*3/2;
}
return 0;
}
结果
使用两张1920 * 1080 的YUV图像进行了测试,可以实现水平拼接,也可以多次拼接