一 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 nv12char *nv12_content = (char *)malloc(sizeof(char) * file_size);if (!nv12_content) {free(i420_content);return false;}// copy y channelmemcpy(nv12_content, i420_content, y_size);// copy uv channelchar *i420_u_base = i420_content + y_size;char *i420_v_base = i420_u_base + uv_size;char *nv12_uv_base = nv12_content + y_size;int i = 0, j = 0;for (;i < uv_size;i++) {nv12_uv_base[j] = i420_u_base[i];nv12_uv_base[j + 1] = i420_v_base[i];j += 2;}free(i420_content);fp = fopen(nv12_file_path, "wb");if (!fp) {free(nv12_content);return false;}if (file_size != fwrite(nv12_content, 1, file_size, fp)) {free(nv12_content);fclose(fp);return false;}free(nv12_content);fclose(fp);return true;
}

二 I420转NV21

1.NV21格式

NV21内存布局基本与NV12类似,只是将NV12中U和V次序互换,如下所示:

2.转换代码

bool convert_i420_nv21(const char *i420_file_path, size_t width, size_t height, const char *nv21_file_path) {if (!i420_file_path || !nv21_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 nv21char *nv21_content = (char *)malloc(sizeof(char) * file_size);if (!nv21_content) {free(i420_content);return false;}// copy y channelmemcpy(nv21_content, i420_content, y_size);// copy uv channelchar *i420_u_base = i420_content + y_size;char *i420_v_base = i420_u_base + uv_size;char *nv21_uv_base = nv21_content + y_size;int i = 0, j = 0;for (;i < uv_size;i++) {nv21_uv_base[j] = i420_v_base[i];nv21_uv_base[j + 1] = i420_u_base[i];j += 2;}free(i420_content);fp = fopen(nv21_file_path, "wb");if (!fp) {free(nv21_content);return false;}if (file_size != fwrite(nv21_content, 1, file_size, fp)) {free(nv21_content);fclose(fp);return false;}free(nv21_content);fclose(fp);return true;
}

三 UYVY转NV12

1.UYVY格式

(1)UYVY是每两个Y共用一组UV,如果一帧UYVY图像宽带是width,高度是height,1个像素占1个字节,那么共有width✖height个Y,U和V都是width✖height / 2个,因此一帧I420图像占用字节数是width✖height✖2。

(2)UYVY是每4个像素中,2个Y共用一组UV,一行像素数是width * 2,如下所示:

2.转换方法

(1)将一帧UYVY图像中所有Y存入NV12图像的缓存区,隔行存入相应的U和V,如下所示:

(2)转换代码:

bool convert_uyvy_nv12(const char *uyvy_file_path, size_t width, size_t height, const char *nv12_file_path) {if (!uyvy_file_path || !nv12_file_path) {return false;}FILE *fp = fopen(uyvy_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 frame_size = width * height * 2;if (file_size != frame_size) {fclose(fp);return false;}char *uyvy_content = (char *)malloc(sizeof(char) * file_size);if (!uyvy_content) {fclose(fp);return false;}if (file_size != fread(uyvy_content, 1, file_size, fp)) {free(uyvy_content);fclose(fp);return false;}fclose(fp);// convert uyvy to nv12frame_size = width * height * 3 / 2;char *nv12_content = (char *)malloc(sizeof(char) * frame_size);if (!nv12_content) {free(uyvy_content);return false;}size_t y_size = width * height;size_t pixels_in_a_row = width * 2;char *nv12_y_ptr = nv12_content;char *nv12_uv_ptr = nv12_content + y_size;int lines = 0;for (int i = 0;i < file_size;i += 4) {// copy y channel*nv12_y_ptr++ = uyvy_content[i + 1];*nv12_y_ptr++ = uyvy_content[i + 3];if (0 == i % pixels_in_a_row) {++lines;}if (lines % 2) {       // extract the UV value of odd rows// copy uv channel*nv12_uv_ptr++ = uyvy_content[i];*nv12_uv_ptr++ = uyvy_content[i + 2];}}free(uyvy_content);fp = fopen(nv12_file_path, "wb");if (!fp) {free(nv12_content);return false;}if (frame_size != fwrite(nv12_content, 1, frame_size, fp)) {free(nv12_content);fclose(fp);return false;}free(nv12_content);fclose(fp);return true;
}

四 UYVY转NV21

方法与转NV12类似,代码如下:

bool convert_uyvy_nv21(const char *uyvy_file_path, size_t width, size_t height, const char *nv21_file_path) {if (!uyvy_file_path || !nv21_file_path) {return false;}FILE *fp = fopen(uyvy_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 frame_size = width * height * 2;if (file_size != frame_size) {fclose(fp);return false;}char *uyvy_content = (char *)malloc(sizeof(char) * file_size);if (!uyvy_content) {fclose(fp);return false;}if (file_size != fread(uyvy_content, 1, file_size, fp)) {free(uyvy_content);fclose(fp);return false;}fclose(fp);// convert uyvy to nv12frame_size = width * height * 3 / 2;char *nv21_content = (char *)malloc(sizeof(char) * frame_size);if (!nv21_content) {free(uyvy_content);return false;}size_t y_size = width * height;size_t pixels_in_a_row = width * 2;char *nv21_y_ptr = nv21_content;char *nv21_uv_ptr = nv21_content + y_size;int lines = 0;for (int i = 0;i < file_size;i += 4) {// copy y channel*nv21_y_ptr++ = uyvy_content[i + 1];*nv21_y_ptr++ = uyvy_content[i + 3];if (0 == i % pixels_in_a_row) {++lines;}if (lines % 2) {       // extract the UV value of odd rows// copy uv channel*nv21_uv_ptr++ = uyvy_content[i + 2];*nv21_uv_ptr++ = uyvy_content[i];}}free(uyvy_content);fp = fopen(nv21_file_path, "wb");if (!fp) {free(nv21_content);return false;}if (frame_size != fwrite(nv21_content, 1, frame_size, fp)) {free(nv21_content);fclose(fp);return false;}free(nv21_content);fclose(fp);return true;
}

五 编译及测试

1.编译:使用g++编译

2.github:GitHub - wangzhicheng2013/common_utility

YUV图像格式转换方法实践相关推荐

  1. 海康彩色工业相机图像格式转换方法(Bayer转RGB)

    海康彩色工业相机图像格式转换方法 1.彩色相机是如何变成彩色的-Bayer的由来 2.工业相机支持的图像格式 3.图像格式转化 4.一些其他的问题 1.彩色相机是如何变成彩色的-Bayer的由来 提到 ...

  2. YUV图像格式进行的ALPHA BLEND操作

    YUV图像格式进行的ALPHA BLEND操作 RGB的alpha blend操作采用如下的公式: 假设 r0 g0 b0 为原始图像的 三个色彩分量, r1 g1 b1 为alpha blend过程 ...

  3. c语言bmp图像YUV转化成RGB,RGB与YUV图像格式的相互转换

    RGB与YUV图像格式的相互转换 (参考上的<RGB与YUV图像视频格式的相互转换>文章,做了些修改) RGB介绍:在记录计算机图像时,最常见的是采用RGB(红.绿,蓝)颜色分量来保存颜色 ...

  4. RAW、RGB、YUV 图像格式区别

    前言 颜色是人的视觉系统对光谱中可见区域的感知效果,它仅存在于人的眼睛和大脑中.为了准确地描述颜色,必须引入色彩空间的概念.正如几何上用坐标空间来描述坐标集合,色彩空间用数学方式来描述颜色集合. 1 ...

  5. RAW、RGB 、YUV三种图像格式理解

    文章目录 1. 背景 2. 相关概念 2.1 颜色与色彩空间 2.2 RAW图像 2.3 RGB图像 2.4 YUV图像 3. 分类简图 RAW.RGB .YUV三种图像格式理解 1. 背景 在工作中 ...

  6. AOE工程实践-银行卡OCR里的图像处理

    AOE工程实践-银行卡OCR里的图像处理 作者:杨科 近期我们开发了一个银行卡 OCR 项目.需求是用手机对着银行卡拍摄以后,通过推理,可以识别出卡片上的卡号. 工程开发过程中,我们发现手机拍摄以后的 ...

  7. OpenCV YUV 与 RGB的互转(草稿)

    YUV 转 RGB cv::Mat yuvImg; /*//下面两行是我自己代码里用来构成YUV图像的数据,可以忽略 yuvImg.create(pInput->height*3/2, pInp ...

  8. 图像处理 花屏_滴滴开源的 AoE:工程实践中的图像处理

    近期,滴滴开源了AOE项目,很多人还是一脸懵逼,不太清楚AOE 到底是干什么的,所以今天我们再来听听官方工程师是怎么介绍的吧,不信你还是听不懂:近期我们开发了一个银行卡 OCR 项目.需求是用手机对着 ...

  9. Android OpenGL ES 学习(十一) –渲染YUV视频以及视频抖音特效

    OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学 ...

最新文章

  1. IDEA打包出现Unable to find main class
  2. 李飞飞下半年或将从 Google离职?李飞飞回应
  3. 资源盗链困扰站长 安全狗内置盗链保护功能
  4. 推荐阅读《赢在下班后》
  5. iOS linker command failed with exit code 1 (use -v to see invocation)多种解决方案汇总
  6. Error creating bean with name ‘fastJsonpResponseBodyAdvice‘ defined in URL xxx
  7. Windows 7 正在走 XP 系统的老路
  8. shell 备份并删除几日内的历史文件
  9. 精确到门牌号的地图_IP地址精准查询工具:能精确到门牌号
  10. python爬取豆瓣top250电影名称_Python--爬取豆瓣TOP250电影信息
  11. 深度学习硬件购买指南
  12. Golang导出并下载excel封装
  13. 机器学习代码整理pLSA、BoW、DBN、DNN
  14. 南京大学2021计算机考研复试线是多少,2021南京大学
  15. 操作系统——(11)多媒体操作系统
  16. 如何将优酷KUX格式转换为MP4格式?
  17. 网页自动刷新的三种方法
  18. Golang-报错-go get github/xxx
  19. DP线和HDMI线相比哪个比较好用?
  20. 使用MPS模型——应对当下全球疫情经济危机互联网寒冬

热门文章

  1. 单片机自制时钟(年月日星期时分秒显示、按键校准)
  2. linux u8 u16 u32 u64,C 语言printf打印各种数据类型的方法(u8/s8/u16/s16.../u64/doub
  3. 提示Microsoft office word 遇到问题需要关闭。还问是否发送错误报告。
  4. 初识OpenVINO
  5. 如何以信创软硬件来实现隐私计算的大规模产业化,听听冲量怎么说
  6. 渝粤题库 陕西师范大学《西方文论》作业
  7. python爬取百度地图数据_百度地图POI数据爬取
  8. Lei ❤函数的初识
  9. Mac磁盘分析工具ncdu使用
  10. 带双参数的双极S型函数