音视频入门文章目录

libyuv

libyuv 是 Google 开源的实现各种 YUV 与 RGB 之间相互转换、旋转、缩放等的库。它是跨平台的,可在 Windows、Linux、Mac、Android 等操作系统,x86、x64、arm 架构上进行编译运行,支持 SSE、AVX、NEON 等 SIMD 指令加速。

准备工作

一张图片

下载 rainbow-700x700.bmp BMP 图片 或者 自己准备一张图片(知道分辨率,如:700x700)

FFmpeg 工具包

FFmpeg 工具下载

根据自己的系统,下载 FFmpeg Static 工具包。

得到所需的 yuv420p 文件

将上面准备的图片转换成 YUV420P 格式:

ffmpeg -i rainbow.bmp -video_size 700x700 -pix_fmt yuv420p rainbow-yuv420p.yuv

查看 YUV 文件

ffplay -f rawvideo -pixel_format yuv420p -video_size 700x700 rainbow-yuv420p.yuv

libyuv 操作 YUV

YUV 裁剪

[rainbow-yuv420p.yuv] -> [rainbow-yuv420p-clip-x-y.yuv]

#include <stdio.h>
#include <stdint.h>
#include "libyuv.h"void clip(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height, int cropX, int cropY, int cropWidth, int cropHeight) {ConvertToI420(srcYuvData,width*height*3/2,dstYuvData,cropWidth,dstYuvData cropWidth*cropHeight,(cropWidth 1)/2,dstYuvData cropWidth*cropHeight ((cropWidth 1)/2)*((cropHeight 1)/2),(cropWidth 1)/2,cropX,cropY,width,height,cropWidth,cropHeight,kRotate0,FOURCC_YU12);
}int main() {uint32_t width = 700, height = 700;uint32_t clipWidth = 200, clipHeight = 200;uint8_t YUV[width*height*3/2];uint8_t YUV_CLIP[clipWidth*clipHeight*3/2];FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p.yuv", "rb");fread(YUV, sizeof(YUV), 1, yuv420pFile);clip(YUV, YUV_CLIP, width, height, 0, 0, clipWidth, clipHeight);FILE *yuvClipFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-clip-0-0.yuv", "wb");fwrite(YUV_CLIP, sizeof(YUV_CLIP), 1, yuvClipFile);fclose(yuvClipFile);fclose(yuv420pFile);return 0;
}

YUV 缩放

[rainbow-yuv420p.yuv] -> [rainbow-yuv420p-scale-X.yuv]

#include <stdio.h>
#include <stdint.h>
#include "libyuv.h"void scale(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height, int dstWidth, int dstHeight) {I420Scale(srcYuvData,width,srcYuvData width*height,(width 1)/2,srcYuvData width*height ((width 1)/2)*((height 1)/2),(width 1)/2,width,height,dstYuvData,dstWidth,dstYuvData dstWidth*dstWidth,(dstWidth 1)/2,dstYuvData dstWidth*dstHeight ((dstWidth 1)/2)*((dstHeight 1)/2),(dstWidth 1)/2,dstWidth,dstHeight,kFilterNone);
}int main() {uint32_t width = 700, height = 700;uint32_t dstWidth = 100, dstHeight = 100;uint8_t YUV[width*height*3/2];uint8_t YUV_SCALE[dstWidth*dstHeight*3/2];FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p.yuv", "rb");fread(YUV, sizeof(YUV), 1, yuv420pFile);scale(YUV, YUV_SCALE, width, height, dstWidth, dstHeight);FILE *yuvScaleFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-scale-6.yuv", "wb");fwrite(YUV_SCALE, sizeof(YUV_SCALE), 1, yuvScaleFile);fclose(yuvScaleFile);fclose(yuv420pFile);return 0;
}

YUV 旋转

[rainbow-yuv420p.yuv] -> [rainbow-yuv420p-rotation-90.yuv]

#include <stdio.h>
#include <stdint.h>
#include "libyuv.h"void rotation(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height) {I420Rotate(srcYuvData,width,srcYuvData width*height,(width 1)/2,srcYuvData width*height ((width 1)/2)*((height 1)/2),(width 1)/2,dstYuvData,width,dstYuvData width*height,(width 1)/2,dstYuvData width*height ((width 1)/2)*((height 1)/2),(width 1)/2,width,height,kRotate90);
}int main() {uint32_t width = 700, height = 700;uint8_t YUV[width*height*3/2];uint8_t YUV_ROTATION[width*height*3/2];FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p.yuv", "rb");fread(YUV, sizeof(YUV), 1, yuv420pFile);rotation(YUV, YUV_ROTATION, width, height);FILE *yuvRotationFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-rotation-90.yuv", "wb");fwrite(YUV_ROTATION, sizeof(YUV_ROTATION), 1, yuvRotationFile);fclose(yuvRotationFile);fclose(yuv420pFile);return 0;
}

YUV 镜像

[rainbow-yuv420p-rotation-90.yuv] -> [rainbow-yuv420p-rotation-90-mirror.yuv]

#include <stdio.h>
#include <stdint.h>
#include "libyuv.h"void mirror(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height) {I420Mirror(srcYuvData,width,srcYuvData width*height,(width 1)/2,srcYuvData width*height ((width 1)/2)*((height 1)/2),(width 1)/2,dstYuvData,width,dstYuvData width*height,(width 1)/2,dstYuvData width*height ((width 1)/2)*((height 1)/2),(width 1)/2,width,height);
}int main() {uint32_t width = 700, height = 700;uint8_t YUV[width*height*3/2];uint8_t YUV_MIRROR[width*height*3/2];FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-rotation-90.yuv", "rb");fread(YUV, sizeof(YUV), 1, yuv420pFile);mirror(YUV, YUV_MIRROR, width, height);FILE *yuvMirrorFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-rotation-90-mirror.yuv", "wb");fwrite(YUV_MIRROR, sizeof(YUV_MIRROR), 1, yuvMirrorFile);fclose(yuvMirrorFile);fclose(yuv420pFile);return 0;
}

YUV 混合

[rainbow-yuv420p.yuv] -> [rainbow-yuv420p-blend.yuv]

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "libyuv.h"void blend(uint8_t *srcYuvData, uint8_t *dstYuvData, int width, int height) {uint8_t YUV_ROTATION[width*height*3/2];I420Rotate(srcYuvData,width,srcYuvData width*height,(width 1)/2,srcYuvData width*height ((width 1)/2)*((height 1)/2),(width 1)/2,YUV_ROTATION,width,YUV_ROTATION width*height,(width 1)/2,YUV_ROTATION width*height ((width 1)/2)*((height 1)/2),(width 1)/2,width,height,kRotate90);// 透明度uint8_t alpha[width*height];memset(alpha, 0X88, width*height);I420Blend(srcYuvData,width,srcYuvData width*height,(width 1)/2,srcYuvData width*height ((width 1)/2)*((height 1)/2),(width 1)/2,YUV_ROTATION,width,YUV_ROTATION width*height,(width 1)/2,YUV_ROTATION width*height ((width 1)/2)*((height 1)/2),(width 1)/2,alpha,width,dstYuvData,width,dstYuvData width*height,(width 1)/2,dstYuvData width*height ((width 1)/2)*((height 1)/2),(width 1)/2,width,height);
}int main() {uint32_t width = 700, height = 700;uint8_t YUV[width*height*3/2];uint8_t YUV_BLEND[width*height*3/2];FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p.yuv", "rb");fread(YUV, sizeof(YUV), 1, yuv420pFile);blend(YUV, YUV_BLEND, width, height);FILE *yuvBlendFile = fopen("/Users/staff/Desktop/rainbow-yuv420p-blend.yuv", "wb");fwrite(YUV_BLEND, sizeof(YUV_BLEND), 1, yuvBlendFile);fclose(yuvBlendFile);fclose(yuv420pFile);return 0;
}

代码:10-yuv-conversion-libyuv

参考资料:

libyuv/libyuv

内容有误?联系作者:

音视频入门-10-使用libyuv对YUV数据进行缩放、旋转、镜像、裁剪、混合相关推荐

  1. 安卓音视频入门难,老司机分享音视频开发学习技巧与痛点

    最近在写文章的时候,发现很多读者给我私信提问,想了解安卓音视频这块, 很多同学也对音视频开发有点浓厚的兴趣,但奈何没有系统的学习知识,仅靠自己苦苦钻研确实力不从心,今天就借这个机会分享一下我学习音视频 ...

  2. 堪称教科书级别的Android音视频入门进阶学习手册,开源分享

    概述 随着整个互联网的崛起,数据传递的形式也在不断升级变化,总的流行趋势如下: 纯文本的短信,QQ -> 空间,微博,朋友圈的图片文字结合 -> 微信语音 -> 各大直播软件 -&g ...

  3. 音视频入门-02-RGB拼图

    音视频入门文章目录 图片 & 像素点 & RGB 平时浏览的图片看不出像素点: 图片放大时,可以看出图片是一个个像素点组成的: 每个像素点的颜色可以用 RGB 表示: RGB 拼图 既 ...

  4. 音视频入门之如何绘制一张图片

    Android 的音视频入门学习,首先了解一下绘制图片.在 Android 平台绘制一张图片,使用至少 3 种不同的 API,ImageView,SurfaceView,自定义 View作绘制图片.下 ...

  5. 音视频入门系列-视频封装格式篇(MP4)

    接上文,本篇介绍下MP4的封装格式. 1.MP4(MPEG-4) ◆ MP4是一套用于音频.视频信息的压缩编码标准,由国际标准化组织(ISO)和国际电工委员会(IEC)下属的"动态图像专家组 ...

  6. Android 音视频入门之音频采集、编码、播放

    今天我们学习音频的采集.编码.生成文件.转码等操作,我们生成三种格式的文件格式,pcm.wav.aac 三种格式,并且我们用 AudioStack 来播放音频,最后我们播放这个音频. 本篇文章你将学到 ...

  7. 音视频入门-17-GIF文件格式详解

    * 音视频入门文章目录 * GIF 文件格式解析 图像互换格式主要分为两个版本,即图像互换格式 87a 和图像互换格式 89a. 图像互换格式 87a:是在 1987 年制定的版本. 图像互换格式 8 ...

  8. 音视频入门系列-音视频基础知识篇(录播、点播、直播)

    在学习音视频技术前,笔者还是希望可以分享给小伙伴们一些音视频方便的基本概念,掌握这些概念,有助于大家对于音视频有一个更直观和清晰的了解. 话不多说,今天笔者给大家分享下:录播.点播和直播. 录播:录播 ...

  9. 音视频入门 (iOS上fdk-aac的交叉编译)

    前篇音视频入门记录了我对音视频的一些基础理解.现在将我在交叉编译ffmpeg之前的一些准备工作记录一下. 本文记录fdk-aac的交叉编译,首先需要说明几个问题: 基本概念 交叉编译:有过移动开发经验 ...

最新文章

  1. 《Android App开发入门:使用Android Studio 2.X开发环境》——1-3 Android Studio 快速上手...
  2. 从0到1演示用 Git Rerere 自动解决冲突
  3. 广告行业中常说的 CPC,CPM,CPD,CPT,CPA,CPS 等词的意思是什么?
  4. 协方差矩阵, 相关系数矩阵
  5. Java工作笔记-Nginx配置IPHash(单点登录)
  6. ndk中杀线程的办法
  7. C++ --对象和类
  8. 微信好友只有昵称没有微信号_没微信号能找到人吗 只有微信昵称怎么找人
  9. Python鸡兔同笼
  10. 银耳椰椰——Alpha冲刺Day09
  11. 春节后面试别人的经历总结之一,好岗位分享给还在找工作中的软件开发爱好者们
  12. mysql扫盲篇_MySQL小白扫盲(一)
  13. 书评与摘抄《经济学原理》
  14. 哐筹甍颚往往能够用它实现
  15. 数据结构之有效的括号
  16. Apache Spark RDD 论文(中文翻译)
  17. poj 1718 River Crossing
  18. 文档集数据处理 gensim corpora.Dictionary
  19. Homography estimation(旋转估计)
  20. 物联网与大数据(四)大数据技术 物联网操作系统

热门文章

  1. 谈下这几天sybase数据库获取行号遇到的坑
  2. Linux-Samba的使用
  3. C语言定积分 tan(x) e^x
  4. “还完花呗,再也不用吃土!”是真的吗?
  5. 小米手机 开发app python_python之小米应用商店搜索
  6. 深入浅出Git教程(转载)
  7. How to modify comment and attribute ClearCase
  8. 双系统之下更改Windows硬盘启动方式为AHCI(不用重装系统)
  9. HDU 4466 Triangle(12年成都)
  10. nodejs之cordova 跨平台开发