一 I420转NV12
1.I420格式
(1)I420是每四个Y共用一组UV,如果一帧I420图像宽带是width,高度是height,1个像素占1个字节,那么共有width✖height个Y,U和V都是width✖height / 4个,因此一帧I420图像占用字节数是width✖height✖3/2。
(2)I420是先存完所有Y后,在接着存完U,最后存V。

2.NV12格式
(1)NV12是每四个Y共用一组UV,如果一帧NV12图像宽带是width,高度是height,1个像素占1个字节,那么共有width✖height个Y,U和V都是width✖height / 4个,因此一帧I420图像占用字节数是width✖height✖3/2。
(2)NV12是先存完所有Y后,随后U、V交替存储。

3.转换方法
(1)将一帧I420图像中所有Y拷贝到NV12数据区,将一帧I420图像中所有U和V交替拷贝到NV12数据区。
(2)代码:
bool convert_i420_nv12(const char *i420_file_path, size_t width, size_t height, const char *nv12_file_path) {
if (!i420_file_path || !nv12_file_path) {
return false;
}
FILE *fp = fopen(i420_file_path, "rb");
if (!fp) {
return false;
}
fseek(fp, 0, SEEK_END);
size_t file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
size_t y_size = width * height;
size_t uv_size = y_size / 4;
if (file_size != (y_size + uv_size * 2)) {
fclose(fp);
return false;
}
char *i420_content = (char *)malloc(sizeof(char) * file_size);
if (!i420_content) {
fclose(fp);
return false;
}
if (file_size != fread(i420_content, 1, file_size, fp)) {
free(i420_content);
fclose(fp);
return false;
}
fclose(fp);
// convert i420 to nv12
char *nv12_content = (char *)malloc(sizeof(char) * file_size);
if (!nv12_content) {
free(i420_content);
return false;
}
// copy y channel
memcpy(nv12_content, i420_content, y_size);
// copy uv channel

本文详细介绍了I420与UYVY两种色彩空间格式,并提供了从I420到NV12/NV21以及从UYVY到NV12/NV21的转换方法与实现代码。
最低0.47元/天 解锁文章
1929

被折叠的 条评论
为什么被折叠?



