用c语言实现3张yuv420图片拼接函数
假设我们有三张YUV420格式的图片,分别为yuv1、yuv2和yuv3,每张图片的宽度和高度为w和h。我们需要实现一个拼接函数,将这三张图片按照从左到右的顺序拼接成一张图片,并返回拼接后的YUV420数据。
具体实现如下:
#include <stdio.h>
#include <stdlib.h>
// 定义YUV420结构体
typedef struct {
unsigned char *y; // Y分量
unsigned char *u; // U分量
unsigned char *v; // V分量
int width; // 宽度
int height; // 高度
} YUV420;
// 将YUV420格式的数据写入文件
void write_yuv420_to_file(YUV420 *yuv, const char *filename) {
FILE *fp = fopen(filename, "wb");
if (fp == NULL) {
printf("Error: failed to open file %s.\n", filename);
return;
}
// 写入Y分量数据
fwrite(yuv->y, sizeof(unsigned char), yuv->width * yuv->height, fp);
// 写入U分量数据
fwrite(yuv->u, sizeof(unsigned char), yuv->width * yuv->height / 4, fp);
// 写入V分量数据
fwrite(yuv->v, sizeof(unsigned char), yuv->width * yuv->height / 4, fp);
fclose(fp);
}
// 拼接三张YUV420格式的图片
YUV420 *yuv420_concat(YUV420 *yuv1, YUV420 *yuv2, YUV420 *yuv3) {
int w = yuv1->width + yuv2->width + yuv3->width; // 拼接后图片的宽度
int h = yuv1->height; // 拼接后图片的高度
YUV420 *yuv = (YUV420 *)malloc(sizeof(YUV420)); // 分配内存
yuv->width = w;
yuv->height = h;
yuv->y = (unsigned char *)malloc(w * h);
yuv->u = (unsigned char *)malloc(w * h / 4);
yuv->v = (unsigned char *)malloc(w * h / 4);
// 拼接Y分量
int i, j;
for (i = 0; i < h; i++) {
// 拼接yuv1图片的Y分量
for (j = 0; j < yuv1->width; j++) {
yuv->y[i * w + j] = yuv1->y[i * yuv1->width + j];
}
// 拼接yuv2图片的Y分量
for (j = 0; j < yuv2->width; j++) {
yuv->y[i * w + j + yuv1->width] = yuv2->y[i * yuv2->width + j];
}
// 拼接yuv3图片的Y分量
for (j = 0; j < yuv3->width; j++) {
yuv->y[i * w + j + yuv1->width + yuv2->width] = yuv3->y[i * yuv3->width + j];
}
}
// 拼接U、V分量
for (i = 0; i < h / 2; i++) {
// 拼接yuv1图片的U分量
for (j = 0; j < yuv1->width / 2; j++) {
yuv->u[i * w / 4 + j] = yuv1->u[i * yuv1->width / 2 + j];
}
// 拼接yuv2图片的U分量
for (j = 0; j < yuv2->width / 2; j++) {
yuv->u[i * w / 4 + j + yuv1->width / 2] = yuv2->u[i * yuv2->width / 2 + j];
}
// 拼接yuv3图片的U分量
for (j = 0; j < yuv3->width / 2; j++) {
yuv->u[i * w / 4 + j + yuv1->width / 2 + yuv2->width / 2] = yuv3->u[i * yuv3->width / 2 + j];
}
// 拼接yuv1图片的V分量
for (j = 0; j < yuv1->width / 2; j++) {
yuv->v[i * w / 4 + j] = yuv1->v[i * yuv1->width / 2 + j];
}
// 拼接yuv2图片的V分量
for (j = 0; j < yuv2->width / 2; j++) {
yuv->v[i * w / 4 + j + yuv1->width / 2] = yuv2->v[i * yuv2->width / 2 + j];
}
// 拼接yuv3图片的V分量
for (j = 0; j < yuv3->width / 2; j++) {
yuv->v[i * w / 4 + j + yuv1->width / 2 + yuv2->width / 2] = yuv3->v[i * yuv3->width / 2 + j];
}
}
return yuv;
}
int main() {
// 读取三张YUV420格式的图片
YUV420 yuv1, yuv2, yuv3;
yuv1.width = 640;
yuv1.height = 360;
yuv1.y = (unsigned char *)malloc(yuv1.width * yuv1.height);
yuv1.u = (unsigned char *)malloc(yuv1.width * yuv1.height / 4);
yuv1.v = (unsigned char *)malloc(yuv1.width * yuv1.height / 4);
FILE *fp1 = fopen("yuv1.yuv", "rb");
fread(yuv1.y, sizeof(unsigned char), yuv1.width * yuv1.height, fp1);
fread(yuv1.u, sizeof(unsigned char), yuv1.width * yuv1.height / 4, fp1);
fread(yuv1.v, sizeof(unsigned char), yuv1.width * yuv1.height / 4, fp1);
fclose(fp1);
yuv2.width = 640;
yuv2.height = 360;
yuv2.y = (unsigned char *)malloc(yuv2.width * yuv2.height);
yuv2.u = (unsigned char *)malloc(yuv2.width * yuv2.height / 4);
yuv2.v = (unsigned char *)malloc(yuv2.width * yuv2.height / 4);
FILE *fp2 = fopen("yuv2.yuv", "rb");
fread(yuv2.y, sizeof(unsigned char), yuv2.width * yuv2.height, fp2);
fread(yuv2.u, sizeof(unsigned char), yuv2.width * yuv2.height / 4, fp2);
fread(yuv2.v, sizeof(unsigned char), yuv2.width * yuv2.height / 4, fp2);
fclose(fp2);
yuv3.width = 640;
yuv3.height = 360;
yuv3.y = (unsigned char *)malloc(yuv3.width * yuv3.height);
yuv3.u = (unsigned char *)malloc(yuv3.width * yuv3.height / 4);
yuv3.v = (unsigned char *)malloc(yuv3.width * yuv3.height / 4);
FILE *fp3 = fopen("yuv3.yuv", "rb");
fread(yuv3.y, sizeof(unsigned char), yuv3.width * yuv3.height, fp3);
fread(yuv3.u, sizeof(unsigned char), yuv3.width * yuv3.height / 4, fp3);
fread(yuv3.v, sizeof(unsigned char), yuv3.width * yuv3.height / 4, fp3);
fclose(fp3);
// 拼接三张YUV420格式的图片
YUV420 *yuv = yuv420_concat(&yuv1, &yuv2, &yuv3);
// 将拼接后的YUV420数据写入文件
write_yuv420_to_file(yuv, "yuv_concat.yuv");
// 释放内存
free(yuv->y);
free(yuv->u);
free(yuv->v);
free(yuv);
free(yuv1.y);
free(yuv1.u);
free(yuv1.v);
free(yuv2.y);
free(yuv2.u);
free(yuv2.v);
free(yuv3.y);
free(yuv3.u);
free(yuv3.v);
return 0;
}
使用以上代码可以将三张YUV420格式的图片拼接成一张图片,并将拼接后的YUV420数据写入文件。需要注意的是,由于YUV420格式的图片中U和V分量的宽度和高度都是原图的一半,所以在拼接时需要分别考虑。
原文地址: https://www.cveoy.top/t/topic/uls 著作权归作者所有。请勿转载和采集!