【音视频数据数据处理 2】【YUV篇】将YUV420P_I420数据旋转90°

  • 一、理论分析(以yuv420p_i420格式为例)
  • 二、顺时针旋转90° 代码实现
  • 三、顺时针旋转180° 代码实现
  • 四、旋转90°-180°-270°-镜像旋转,完整代码实现
  • 五、运行结果

本文接着前文:
《【音视频数据数据处理 1】【YUV篇】分离YUV420P像素数据中的Y、U、V分量》

一、理论分析(以yuv420p_i420格式为例)

如下,以2x4的源图为例:

而,经过顺时针旋转90度后

取数据时,相当于下面黑色方向的箭头。

本文链接:《【音视频数据数据处理 2】【YUV篇】将YUV420P_I420数据旋转90°-180°-270°-镜像旋转》

二、顺时针旋转90° 代码实现

核心代码如下:

//  顺时针旋转90度
// 格式为:YY YY YY YY ... UU...VV
void Rotate_90_YUV420_I420(char *path, int width, int height)
{int i, j; FILE *file = fopen(path, "rb+"); //只读打开源文件FILE *file_r = fopen("yuv420p_i420_90.y", "wb+");    //可读可写创建 Y分量文件 // 申请 width * hight * 3 / 2 的内存unsigned char *p, *pic = (unsigned char *)malloc(sizeof(char) * width * height * 3 / 2);unsigned char *d, *pic_d = (unsigned char *)malloc(sizeof(char) * width * height * 3 / 2);size_t num=0;num = fread(pic, 1, width*height*3/2, file);   // 读取源图片的所有内容,每个数据块为1字节 printf("读取 %d 个字节的数据\n", num);            //旋转 Y分量 p = pic;d = pic_d;for(i = 0; i<width; i++)for(j = 0; j<height; j++)*d++ = *(p + i + (height-j)*width);  //p[i][height-j];printf("旋转Y分分量完毕 num=%d \n", d-pic_d);  // 旋转 U分量p += width * height;             for(i = 0; i<width/2; i+=1)for(j = 0; j<height/2; j++){*d++ = *(p + i + (height/2 -j) * width/2);  //p[i][height/2-j];}printf("旋转U分分量完毕 num=%d \n", d-pic_d);// 旋转 V分量p += width * height / 4;            for(i = 0; i<width/2; i+=1)for(j = 0; j<height/2; j++){*d++ = *(p + i + (height/2 -j) * width/2);  //p[i][height/2-j];}printf("旋转V分分量完毕 num=%d \n", d-pic_d);// 写入旋转后的图         num = fwrite(pic_d, 1, width * height *3 / 2, file_r);     // 保存Y分量,pic[0, width*height] ,每个数据块写1字节 printf("写入 %d 个字节的数据\n", num);    free(pic);free(pic_d);fclose(file);fclose(file_r);
}

运行结果如下

三、顺时针旋转180° 代码实现

//  顺时针旋转180度
// 格式为:YY YY YY YY ... UU...VV
void Rotate_180_YUV420_I420(char *path, int width, int height)
{int i, j; FILE *file = fopen(path, "rb+"); //只读打开源文件FILE *file_r = fopen("yuv420p_i420_180.y", "wb+");   //可读可写创建 Y分量文件 // 申请 width * hight * 3 / 2 的内存unsigned char *p, *pic = (unsigned char *)malloc(sizeof(char) * width * height * 3 / 2);unsigned char *d, *pic_d = (unsigned char *)malloc(sizeof(char) * width * height * 3 / 2);size_t num=0;num = fread(pic, 1, width*height*3/2, file);   // 读取源图片的所有内容,每个数据块为1字节 printf("读取 %d 个字节的数据\n", num);            //旋转 Y分量 p = pic;d = pic_d;for(i = 0; i<height; i++)for(j = 0; j<width; j++)*d++ = *(p + width-j + (height-i)*width);  //p[heidht-i][widht-j];printf("旋转Y分分量完毕 num=%d \n", d-pic_d);  // 旋转 U分量p += width * height;             for(i = 0; i<height/2; i++)for(j = 0; j<width/2; j++)*d++ = *(p + width/2-j + (height/2-i)*width/2);  //p[heidht-i][widht-j];printf("旋转U分分量完毕 num=%d \n", d-pic_d);// 旋转 V分量// 旋转 U分量p += width * height / 4;             for(i = 0; i<height/2; i++)for(j = 0; j<width/2; j++)*d++ = *(p + width/2-j + (height/2-i)*width/2);  //p[heidht-i][widht-j];printf("旋转V分分量完毕 num=%d \n", d-pic_d);// 写入旋转后的图           num = fwrite(pic_d, 1, width * height *3 / 2, file_r);     // 保存Y分量,pic[0, width*height] ,每个数据块写1字节 printf("写入 %d 个字节的数据\n", num);    free(pic);free(pic_d);fclose(file);fclose(file_r);
}

四、旋转90°-180°-270°-镜像旋转,完整代码实现

#include <stdio.h>
#include <stdlib.h>// 顺时针旋转 n*90 度
// 格式为:YY YY YY YY ... UU...VV
// path:源图地址  width,height 源图宽高
// rota: 希望旋转的度数
void Rotate_YUV420_I420(char *path, int width, int height, int rota)
{int i, j, num; // 找开源文件 FILE *file_d, *file = fopen(path, "rb+");  //只读打开源文件// 申请 width * hight * 3 / 2 的内存unsigned char *p, *pic = (unsigned char *)malloc(sizeof(char) * width * height * 3 / 2);unsigned char *d, *pic_d = (unsigned char *)malloc(sizeof(char) * width * height * 3 / 2);num = fread(pic, 1, width*height*3/2, file);   // 读取源图片的所有内容,每个数据块为1字节 printf("读取 %d 个字节的数据\n", num);    // 根据旋转度数,计算switch( rota ){// 镜像旋转0度case 1:      // 创建旋转后的文件名 file_d = fopen("yuv420p_i420_0_mirror.yuv", "wb+");  //可读可写创建 Y分量文件  //旋转 Y分量 p = pic;d = pic_d;for(i = 0; i<height; i++)for(j = 0; j<width; j++)*d++ = *(p + width-j + (i)*width);   //p[height-j][i]printf("旋转Y分分量完毕 num=%d \n", d-pic_d);   // 旋转 U,分量p += width * height;            for(i = 0; i<height/2; i++)for(j = 0; j<width/2; j++)*d++ = *(p + width/2-j + (i)*width/2);    //p[height-j][i]printf("旋转U分分量完毕 num=%d \n", d-pic_d);// 旋转 V分量p += width * height / 4;            for(i = 0; i<height/2; i++)for(j = 0; j<width/2; j++)*d++ = *(p + width/2-j + (i)*width/2);    //p[height-j][i]printf("旋转V分分量完毕 num=%d \n", d-pic_d);break;     // 90度case 2:       // 创建旋转后的文件名 file_d = fopen("yuv420p_i420_90.yuv", "wb+");    //可读可写创建 Y分量文件 //旋转 Y分量 p = pic;d = pic_d;for(i = 0; i<width; i++)for(j = 0; j<height; j++)*d++ = *(p + i + (height-j)*width);   //p[height-j][i]printf("旋转Y分分量完毕 num=%d \n", d-pic_d);   // 旋转 U,分量p += width * height;            for(i = 0; i<width/2; i++)for(j = 0; j<height/2; j++)*d++ = *(p + i + (height/2-j)*width/2);   //p[height-j][i]printf("旋转U分分量完毕 num=%d \n", d-pic_d);// 旋转 V分量p += width * height / 4;            for(i = 0; i<width/2; i++)for(j = 0; j<height/2; j++)*d++ = *(p + i + (height/2-j)*width/2);   //p[height-j][i]printf("旋转V分分量完毕 num=%d \n", d-pic_d);break; // 镜像90度case 3:     // 创建旋转后的文件名 file_d = fopen("yuv420p_i420_90_mirror.yuv", "wb+"); //可读可写创建 Y分量文件 //旋转 Y分量 p = pic;d = pic_d;for(i = 0; i<width; i++)for(j = 0; j<height; j++)*d++ = *(p + width-i + (height-j)*width);     //p[height-j][i]printf("旋转Y分分量完毕 num=%d \n", d-pic_d);   // 旋转 U,分量p += width * height;            for(i = 0; i<width/2; i++)for(j = 0; j<height/2; j++)*d++ = *(p + width-i + (height/2-j)*width/2);     //p[height-j][i]printf("旋转U分分量完毕 num=%d \n", d-pic_d);// 旋转 V分量p += width * height / 4;            for(i = 0; i<width/2; i++)for(j = 0; j<height/2; j++)*d++ = *(p + width-i + (height/2-j)*width/2);     //p[height-j][i]printf("旋转V分分量完毕 num=%d \n", d-pic_d);break; // 180度 case 4:     // 创建旋转后的文件名 file_d = fopen("yuv420p_i420_180.yuv", "wb+");   //可读可写创建 Y分量文件 //旋转 Y分量 p = pic;d = pic_d;for(i = 0; i<height; i++)for(j = 0; j<width; j++)*d++ = *(p + j + (height-i)*width);   //p[height-i][j]printf("旋转Y分分量完毕 num=%d \n", d-pic_d);   // 旋转 U,分量p += width * height;            for(i = 0; i<height/2; i++)for(j = 0; j<width/2; j++)*d++ = *(p + j + (height/2-i)*width/2); //p[height/2-i][j]printf("旋转U分分量完毕 num=%d \n", d-pic_d);// 旋转 V分量p += width * height / 4;            for(i = 0; i<height/2; i++)for(j = 0; j<width/2; j++)*d++ = *(p + j + (height/2-i)*width/2); //p[height/2-i][j]printf("旋转V分分量完毕 num=%d \n", d-pic_d);break; // 旋转270度   case 5:     // 创建旋转后的文件名 file_d = fopen("yuv420p_i420_270.yuv", "wb+");   //可读可写创建 Y分量文件  //旋转 Y分量 p = pic;d = pic_d;for(i = 0; i<width; i++)for(j = 0; j<height; j++)*d++ = *(p + width-i + (j)*width);   //p[height-j][i]printf("旋转Y分分量完毕 num=%d \n", d-pic_d);   // 旋转 U,分量p += width * height;            for(i = 0; i<width/2; i++)for(j = 0; j<height/2; j++)*d++ = *(p + width/2-i + (j)*width/2);    //p[height-j][i]printf("旋转U分分量完毕 num=%d \n", d-pic_d);// 旋转 V分量p += width * height / 4;            for(i = 0; i<width/2; i++)for(j = 0; j<height/2; j++)*d++ = *(p + width/2-i + (j)*width/2);    //p[height-j][i]printf("旋转V分分量完毕 num=%d \n", d-pic_d);break; default:if(rota != 0)printf("不支持旋转%d度,当前不旋转\n", rota); // 创建旋转后的文件名 file_d = fopen("yuv420p_i420_0.yuv", "wb+");    //可读可写创建 Y分量文件  // 写入旋转后的图          num = fwrite(pic, 1, width * height *3 / 2, file_d);   // 保存Y分量,pic[0, width*height] ,每个数据块写1字节 printf("写入 %d 个字节的数据\n", num);    free(pic);free(pic_d);fclose(file);fclose(file_d);return;} // 写入旋转后的图           num = fwrite(pic_d, 1, width * height *3 / 2, file_d);     // 保存Y分量,pic[0, width*height] ,每个数据块写1字节 printf("写入 %d 个字节的数据\n", num);    free(pic);free(pic_d);fclose(file);fclose(file_d);
}int main(void)
{char path[]="yuv420p_i420.yuv";//Split_YUV420_I420(path, 720, 480);Rotate_YUV420_I420(path,720, 480, 0);        // 旋转 0°Rotate_YUV420_I420(path,720, 480, 1);       // 镜像旋转 0°Rotate_YUV420_I420(path,720, 480, 2);     // 旋转90°Rotate_YUV420_I420(path,720, 480, 3);       // 镜像旋转90°Rotate_YUV420_I420(path,720, 480, 4);     // 旋转180°Rotate_YUV420_I420(path,720, 480, 5);      // 旋转270°return 0;
}

五、运行结果

图片太多,我就放一起显示了:

《视音频数据处理入门:RGB、YUV像素数据处理》
《图文详解YUV420数据格式》
《YUV420图像旋转90算法的优化》

【音视频数据数据处理 2】【YUV篇】将YUV420P_I420数据旋转90°-180°-270°-镜像旋转相关推荐

  1. iOS音视频的那些事儿(一):数据的采集和编码

    1.AVFoundation简介 AVFoundation是苹果在iOS和OS X系统中用于处理基于时间的媒体数据的Objective-C框架. 供使用者来开发媒体类型的应用程序. 如果只是进行简单的 ...

  2. Android IOS WebRTC 音视频开发总结(六二)-- 大数据解密国外实时通讯行业开发现状...

    Android IOS WebRTC 音视频开发总结(六二)-- 大数据解密国外实时通讯行业开发现状 本文主要介绍国外实时通讯行业现状,文章最早发表在我们的微信公众号上,详见这里,欢迎关注微信公众号b ...

  3. linux摄像头 sdl,Linux音视频(SDL与YUV)

    SDL是一个比较底层的音视频处理库,很多UI系统的内核都用到它,我们还可以用它来处理摄像头中YUV数据. 拓展: SDL(Simple DirectMedia Layer)是一个跨平台的底层开发库,提 ...

  4. 音视频大合集最终篇;学废了

    前言 加企鹅群:1079654574 解锁 <音视频八大板块资料> 音视频大合集,从初中高到面试应有尽有;让学习更贴近未来实战.已形成PDF版 八个模块内容如下: 1.音视频基础 2.FF ...

  5. 音视频 测试分享-基础工具篇

    在视频直播 方向的测试经验 想借个机会一起分享下,一起提高大家的测试技术 1.测试工具 ffmpeg-强大工具支撑 验证flv ,mp4 等多媒体信息的工具:ffmporb srs-bench:音视频 ...

  6. 音视频编码实战-------pcm+yuv数据转成MP4

    文章目录 1.编码流程图 2.相关模块及函数 2.1 编码器相关API 2.2 复用器相关API 2.3 重采样相关API 注意点 简单的编码流程相关代码 1.编码流程图 2.相关模块及函数 2.1 ...

  7. android视频剪辑处理第三方,Android 中通过 FFmpeg 命令对音视频编辑处理

    以下文章来源于DevYk ,作者DevYK 音视频编辑器 前言 有时候我们想对音视频进行加工处理,比如视频编辑.添加字幕.裁剪等功能处理,虽然 Github 上开源了一些比较不错的项目,但是如果我们想 ...

  8. Android 中通过 FFmpeg 命令对音视频编辑处理(已开源)

    视音频编辑器 前言 有时候我们想对音视频进行加工处理,比如视频编辑.添加字幕.裁剪等功能处理,虽然 Github 上开源了一些比较不错的项目,但是如果我们想在此项目上进行二次开发,比如我想拿到该项目的 ...

  9. 音视频数据处理入门:原始视频格式YUV,NV12,NV21,YV12,YU12(I420)

    我们知道,在Camera中设置Preview的回调函数onPreviewFrame时谷歌推荐我们使用NV21,YV12两种格式,因为这两种格式几乎在所有的设备里都通用.然而,视频的格式远远不止这俩种, ...

  10. webRTC(四):Webrtc音视频数据采集录制采集屏面数据

    WebRTC音视频数据采集 var constraints={video: true,audio: true,}navigator.mediaDevices.getUserMedia(constrai ...

最新文章

  1. pods install 无法安装库
  2. Java中的main()方法详解
  3. 蚂蚁金服张洁:基于深度学习的支付宝人脸识别技术解秘-1
  4. Android自定义Dialog及与Activity的交互
  5. docker查看容器并运行
  6. 基于Python的电子教室软件中远程关机功能的原理与实现
  7. vs code c语言json文件配置,解析VScode在Windows环境下c_cpp_properties.json文件配置问题(推荐)...
  8. nodejs首个框架开发(先只发个连接,有空再写)
  9. Wunderlist – 免费同步 Todo List
  10. 免费批量化音频切割软件 AutoVoiceCut
  11. 原神角色展示(HTML+CSS)
  12. 手把手教你怎么从微软官方下载 Windos10 正版镜像
  13. 【JS】446- 你不知道的 map
  14. c++的构造函数赋值函数重载运算符等
  15. 海康威视网络摄像头购买指南(焦距像素等参数)
  16. v-show和v-if有什么区别?使用场景分别是什么?
  17. 小傻蛋的妹妹跟着小甲鱼学习Python的第七节007
  18. 怪物农场2修改日志3 - 年轮
  19. html5几张图片怎么并排一行_html5 图片与文字中间对齐处于同一行、或者图片与按钮处于同一行...
  20. RT-Thread_rt_kprintf()打印浮点数(解决方法2:添加rt_vsnprintf_full)

热门文章

  1. 一个完整答题卡识别系统
  2. ISO27001认证步骤及证书年审
  3. qq一注销账号就服务器繁忙,qq熊熊怎样解除服务器繁忙的问题
  4. CSDN-markdown编辑器使用
  5. android 渠道商,【华为怒斥渠道商】
  6. 实现echarts中国地图迁徙图
  7. MSN 通信协议学习笔记(转)
  8. MP3免费音频文件下载
  9. NetSetMan IP快速切换
  10. 十大免费网络工具 瞬间提升业务效率