C语言实现NV12图片拼接:左右和上下拼接方法
以下是一个实现将两张NV12格式的图片左右拼接的C语言代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define WIDTH 640
#define HEIGHT 480
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, 'Usage: %s file1.nv12 file2.nv12\n', argv[0]);
return 1;
}
// 打开文件1
FILE *f1 = fopen(argv[1], 'rb');
if (!f1) {
perror('Failed to open file1');
return 1;
}
// 打开文件2
FILE *f2 = fopen(argv[2], 'rb');
if (!f2) {
perror('Failed to open file2');
return 1;
}
// 读取文件1的数据
uint8_t *data1 = (uint8_t *)malloc(WIDTH * HEIGHT * 3 / 2);
if (!data1) {
perror('Failed to allocate memory for file1');
return 1;
}
size_t n1 = fread(data1, 1, WIDTH * HEIGHT * 3 / 2, f1);
if (n1 != WIDTH * HEIGHT * 3 / 2) {
fprintf(stderr, 'Failed to read data from file1\n');
return 1;
}
// 读取文件2的数据
uint8_t *data2 = (uint8_t *)malloc(WIDTH * HEIGHT * 3 / 2);
if (!data2) {
perror('Failed to allocate memory for file2');
return 1;
}
size_t n2 = fread(data2, 1, WIDTH * HEIGHT * 3 / 2, f2);
if (n2 != WIDTH * HEIGHT * 3 / 2) {
fprintf(stderr, 'Failed to read data from file2\n');
return 1;
}
// 创建输出文件
FILE *fout = fopen('output.nv12', 'wb');
if (!fout) {
perror('Failed to create output file');
return 1;
}
// 将两张图片左右拼接
uint8_t *out = (uint8_t *)malloc(WIDTH * HEIGHT * 3);
if (!out) {
perror('Failed to allocate memory for output');
return 1;
}
for (int i = 0; i < HEIGHT; i++) {
// 拼接Y分量
memcpy(out + i * WIDTH * 2, data1 + i * WIDTH, WIDTH);
memcpy(out + i * WIDTH * 2 + WIDTH, data2 + i * WIDTH, WIDTH);
// 拼接UV分量
for (int j = 0; j < WIDTH / 2; j++) {
out[WIDTH * HEIGHT + i * WIDTH + j * 2] = data1[WIDTH * HEIGHT + i / 2 * WIDTH + j];
out[WIDTH * HEIGHT + i * WIDTH + j * 2 + 1] = data1[WIDTH * HEIGHT + i / 2 * WIDTH + j + WIDTH / 2];
out[WIDTH * HEIGHT * 3 / 2 + i * WIDTH + j * 2] = data2[WIDTH * HEIGHT + i / 2 * WIDTH + j];
out[WIDTH * HEIGHT * 3 / 2 + i * WIDTH + j * 2 + 1] = data2[WIDTH * HEIGHT + i / 2 * WIDTH + j + WIDTH / 2];
}
}
// 将拼接后的图片写入输出文件
size_t n3 = fwrite(out, 1, WIDTH * HEIGHT * 3, fout);
if (n3 != WIDTH * HEIGHT * 3) {
fprintf(stderr, 'Failed to write data to output file\n');
return 1;
}
// 释放内存和关闭文件
free(data1);
free(data2);
free(out);
fclose(f1);
fclose(f2);
fclose(fout);
return 0;
}
该代码将两张NV12格式的图片左右拼接,并将结果写入名为output.nv12的文件中。可以通过修改代码将其改为上下拼接。需要注意的是,该代码仅适用于相同宽度和高度的图片。如果要拼接不同大小的图片,需要进行额外的处理。
实现上下拼接:
在代码中,将Y分量和UV分量的拼接方式调整如下:
// 拼接Y分量
memcpy(out + i * WIDTH * 2, data1 + i * WIDTH, WIDTH);
memcpy(out + (i + HEIGHT) * WIDTH * 2, data2 + i * WIDTH, WIDTH);
// 拼接UV分量
for (int j = 0; j < WIDTH / 2; j++) {
out[WIDTH * HEIGHT + i * WIDTH + j * 2] = data1[WIDTH * HEIGHT + i / 2 * WIDTH + j];
out[WIDTH * HEIGHT + i * WIDTH + j * 2 + 1] = data1[WIDTH * HEIGHT + i / 2 * WIDTH + j + WIDTH / 2];
out[WIDTH * HEIGHT * 3 / 2 + (i + HEIGHT / 2) * WIDTH + j * 2] = data2[WIDTH * HEIGHT + i / 2 * WIDTH + j];
out[WIDTH * HEIGHT * 3 / 2 + (i + HEIGHT / 2) * WIDTH + j * 2 + 1] = data2[WIDTH * HEIGHT + i / 2 * WIDTH + j + WIDTH / 2];
}
代码说明:
- 文件读取: 代码首先打开两个NV12格式的输入文件,并分别读取文件内容到data1和data2数组中。
- 内存分配: 为输出文件创建一个数组out,其大小为两张图片的总大小。
- 拼接操作: 代码分别对Y分量和UV分量进行拼接,并将拼接后的数据写入out数组。
- 写入输出文件: 代码将out数组中的数据写入output.nv12文件。
- 内存释放和文件关闭: 代码最后释放分配的内存,并关闭所有打开的文件。
注意事项:
- 该代码假设两张图片的宽度和高度相同。如果要拼接不同大小的图片,需要进行额外的处理。
- 代码中定义了WIDTH和HEIGHT宏,分别代表图片的宽度和高度。根据实际情况修改这些宏的值。
- 代码中使用memcpy函数来复制数据,可以根据实际情况选择更合适的复制方法。
应用场景:
该代码可应用于图像处理、视频编解码等领域,例如:
- 将多张图片合并成一张大图。
- 将视频帧拼接成连续的视频流。
- 实现图像的分割和拼接等操作。
扩展阅读:
- NV12格式:https://en.wikipedia.org/wiki/YUV#NV12
- C语言内存管理:https://www.tutorialspoint.com/cprogramming/c_memory_management.htm
- 图像处理库:https://www.opencv.org/
原文地址: https://www.cveoy.top/t/topic/lGOb 著作权归作者所有。请勿转载和采集!