由于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;
}
用c语言实现3个yuv420图片左右或者上下拼接,可以输入图片的宽和高、3个yuv420图片的文件名、左右还是上下拼接

原文地址: https://www.cveoy.top/t/topic/uev 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录