假设我们有三张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分量的宽度和高度都是原图的一半,所以在拼接时需要分别考虑。

用c语言实现3张yuv420图片拼接函数

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

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