用c语言实现3个yuv420图片左右或者上下拼接,可以输入图片的宽和高、3个yuv420图片的文件名、左右还是上下拼接
由于YUV420的数据格式是每4个像素共用一组UV数据,因此拼接时需要考虑到像素对齐的问题。下面是一个简单的实现示例,仅供参考:
#include <stdio.h>
#include <stdlib.h>
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
void merge_yuv420(char *out_file, char *in_file1, char *in_file2, char *in_file3, int width, int height, int mode) {
int i, j, k, w, h, y_size, uv_size;
FILE *fp_out, *fp_in1, *fp_in2, *fp_in3;
unsigned char *data1, *data2, *data3, *out_data;
int out_width, out_height;
// 打开输入输出文件
fp_out = fopen(out_file, "wb");
fp_in1 = fopen(in_file1, "rb");
fp_in2 = fopen(in_file2, "rb");
fp_in3 = fopen(in_file3, "rb");
if (!fp_out || !fp_in1 || !fp_in2 || !fp_in3) {
printf("Failed to open file.\n");
return;
}
// 计算输出图片尺寸和大小
if (mode == 0) { // 左右拼接
out_width = width * 3;
out_height = height;
} else { // 上下拼接
out_width = width;
out_height = height * 3;
}
y_size = out_width * out_height;
uv_size = y_size / 4;
// 分配内存
data1 = (unsigned char*)malloc(y_size * sizeof(unsigned char));
data2 = (unsigned char*)malloc(y_size * sizeof(unsigned char));
data3 = (unsigned char*)malloc(y_size * sizeof(unsigned char));
out_data = (unsigned char*)malloc(y_size + 2 * uv_size * sizeof(unsigned char));
if (!data1 || !data2 || !data3 || !out_data) {
printf("Failed to allocate memory.\n");
return;
}
// 读取YUV420数据
fread(data1, sizeof(unsigned char), y_size, fp_in1);
fread(data2, sizeof(unsigned char), y_size, fp_in2);
fread(data3, sizeof(unsigned char), y_size, fp_in3);
// 拼接Y数据
if (mode == 0) { // 左右拼接
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
out_data[i * out_width + j] = data1[i * width + j];
out_data[i * out_width + j + width] = data2[i * width + j];
out_data[i * out_width + j + 2 * width] = data3[i * width + j];
}
}
} else { // 上下拼接
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
out_data[i * out_width + j] = data1[i * width + j];
out_data[(i + height) * out_width + j] = data2[i * width + j];
out_data[(i + 2 * height) * out_width + j] = data3[i * width + j];
}
}
}
// 拼接UV数据
for (k = 0; k < 2; k++) {
if (mode == 0) { // 左右拼接
for (i = 0; i < height / 2; i++) {
for (j = 0; j < width / 2; j++) {
out_data[y_size + i * out_width / 2 + j] = data1[y_size + i * width / 2 + j];
out_data[y_size + i * out_width / 2 + j + uv_size / 2] = data2[y_size + i * width / 2 + j];
out_data[y_size + i * out_width / 2 + j + 2 * uv_size / 2] = data3[y_size + i * width / 2 + j];
}
}
} else { // 上下拼接
for (i = 0; i < height / 2; i++) {
for (j = 0; j < width / 2; j++) {
out_data[y_size + i * out_width / 2 + j] = data1[y_size + i * width / 2 + j];
out_data[y_size + (i + height / 2) * out_width / 2 + j] = data2[y_size + i * width / 2 + j];
out_data[y_size + (i + 2 * height / 2) * out_width / 2 + j] = data3[y_size + i * width / 2 + j];
}
}
}
y_size += uv_size;
}
// 写入YUV420数据
fwrite(out_data, sizeof(unsigned char), y_size, fp_out);
// 释放内存和关闭文件
free(data1);
free(data2);
free(data3);
free(out_data);
fclose(fp_in1);
fclose(fp_in2);
fclose(fp_in3);
fclose(fp_out);
}
int main() {
int width, height, mode;
char in_file1[256], in_file2[256], in_file3[256], out_file[256];
// 输入图片尺寸和文件名
printf("Input image width and height:\n");
scanf("%d %d", &width, &height);
printf("Input 3 YUV420 image files:\n");
scanf("%s %s %s", in_file1, in_file2, in_file3);
printf("Input merge mode (0 for left-right, 1 for top-bottom):\n");
scanf("%d", &mode);
printf("Input output file name:\n");
scanf("%s", out_file);
// 拼接YUV420图片
merge_yuv420(out_file, in_file1, in_file2, in_file3, width, height, mode);
return 0;
}
原文地址: https://www.cveoy.top/t/topic/uev 著作权归作者所有。请勿转载和采集!