音视频入门-08-RGB&YUV
YUV & RGB 相互转换公式
YCbCr 的 Y 与 YUV 中的 Y 含义一致,Cb 和 Cr 与 UV 同样都指色彩,Cb 指蓝色色度,Cr 指红色色度,在应用上很广泛,JPEG、MPEG、DVD、摄影机、数字电视等皆采此一格式。
因此一般俗称的 YUV 大多是指 YCbCr 。
- RGB to YUV(YCbCr)
RGB 范围 [0,255],Y 范围 [16,235] ,UV 范围 [16,239]。如果计算结果超过了取值范围要进行截取。
Y = 0.257*R + 0.504*G + 0.098*B + 16;
U = -0.148*R - 0.291*G + 0.439*B + 128;
V = 0.439*R - 0.368*G - 0.071*B + 128;
- YUV(YCbCr)to RGB
RGB 范围 [0,255],Y 范围 [16,235] ,UV 范围 [16,239]。如果计算结果超过了取值范围要进行截取。
R = 1.164*(Y - 16) + 1.596*(V - 128);
G = 1.164*(Y - 16) - 0.813*(V - 128) - 0.391*(U - 128);
B = 1.164*(Y - 16) + 2.018*(U - 128);
FFmpeg 工具的辅助
FFmpeg 将 之前生成的彩虹图 BMP 转成 YUV 格式的文件、RGB 格式的文件
ffmpeg -i rainbow.bmp -video_size 700x700 -pix_fmt yuv444p rainbow-yuv444p.yuv
ffmpeg -i rainbow.bmp -video_size 700x700 -pix_fmt rgb24 rainbow-rgb24.rgb
FFplay 查看生成的 YUV 格式的文件、RGB 格式的文件
ffplay -f rawvideo -pix_fmt yuv444p -video_size 700x700 rainbow-yuv444p.yuv
ffplay -f rawvideo -pix_fmt rgb24 -video_size 700x700 rainbow-rgb24.rgb
用代码实现 RGB & YUV 转换
RGB -> YUV
将 FFmpeg 生成的 RGB24 格式转换成 YUV444P 格式。
[rainbow-rgb24.rgb] -> [rainbow-rgb24-to-yuv444p.yuv]
#include <stdio.h>
#include <string.h>
#include <math.h>
// 彩虹的七种颜色
u_int32_t rainbowColors[] = {
0XFF0000, // 红
0XFFA500, // 橙
0XFFFF00, // 黄
0X00FF00, // 绿
0X007FFF, // 青
0X0000FF, // 蓝
0X8B00FF // 紫
};
u_int8_t bound(u_int8_t start, int value, u_int8_t end) {
if(value <= start) {
return start;
}
if(value >= end) {
return end;
}
return value;
}
void rgbToYuv(u_int8_t R, u_int8_t G, u_int8_t B, u_int8_t *Y, u_int8_t *U, u_int8_t *V) {
int y_val = (int)round(0.257*R + 0.504*G + 0.098*B + 16);
int u_val = (int)round(-0.148*R - 0.291*G + 0.439*B + 128);
int v_val = (int)round(0.439*R - 0.368*G - 0.071*B + 128);
*Y = bound(16, y_val, 235);
*U = bound(16, u_val, 239);
*V = bound(16, v_val, 239);
}
void rgb24ToYuv444p(const u_int8_t *rgb24Data, u_int8_t *yuv444pData, int width, int height) {
int8_t yuv_y[width*height];
int8_t yuv_u[width*height];
int8_t yuv_v[width*height];
for (int i = 0; i < width; ++i) {
for (int j = 0; j < height; ++j) {
u_int8_t Y, U, V;
u_int8_t R, G, B;
int currentRGBIndex = 3*(i*height+j);
R = rgb24Data[currentRGBIndex];
G = rgb24Data[currentRGBIndex+1];
B = rgb24Data[currentRGBIndex+2];
rgbToYuv(R, G, B, &Y, &U, &V);
int currentYUVIndex = i*height+j;
yuv_y[currentYUVIndex] = Y;
yuv_u[currentYUVIndex] = U;
yuv_v[currentYUVIndex] = V;
}
}
memcpy(yuv444pData, yuv_y, sizeof(yuv_y));
memcpy(yuv444pData + sizeof(yuv_y), yuv_u, sizeof(yuv_u));
memcpy(yuv444pData + sizeof(yuv_y) + sizeof(yuv_u), yuv_v, sizeof(yuv_v));
}
int main() {
int width = 700, height = 700;
u_int8_t yuv444pData[width*height*3];
u_int8_t rgb24Data[width*height*3];
FILE *rgb24File = fopen("/Users/staff/Desktop/rainbow-rgb24.rgb", "rb");
fread(rgb24Data, sizeof(rgb24Data), 1, rgb24File);
rgb24ToYuv444p(rgb24Data, yuv444pData, width, height);
FILE *yuv444pFile = fopen("/Users/ff/Desktop/rainbow-rgb24-to-yuv444p.yuv", "wb");
fwrite(yuv444pData, sizeof(yuv444pData), 1, yuv444pFile);
fclose(rgb24File);
fclose(yuv444pFile);
return 0;
}
ffplay -f rawvideo -pix_fmt rgb24 -video_size 700x700 rainbow-rgb24.rgb
ffplay -f rawvideo -pix_fmt yuv444p -video_size 700x700 rainbow-rgb24-to-yuv444p.yuv
YUV -> RGB
将 FFmpeg 生成的 YUV444P 格式转换成 RGB24 格式。
[rainbow-yuv444p.yuv] -> [rainbow-yuv444p-to-rgb24.rgb]
#include <stdio.h>
#include <math.h>
u_int8_t bound(u_int8_t start, int value, u_int8_t end) {
if(value <= start) {
return start;
}
if(value >= end) {
return end;
}
return value;
}
void yuv444pToRGB(u_int8_t *yuv444pData,u_int8_t *rgb24Data, int width, int height) {
u_int8_t *srcY = yuv444pData, *srcU = srcY + width * height, *srcV = srcU + width * height;
for(int i = 0 ; i < height ; i ++) {
for (int j = 0; j < width; j++) {
int currentYUVIndex = i * height + j;
u_int8_t Y = srcY[currentYUVIndex], U = srcU[currentYUVIndex], V = srcV[currentYUVIndex];
int r_val = (int)round(1.164*(Y-16)+1.596*(V-128));
int g_val = (int)round(1.164*(Y-16)-0.813*(V-128)-0.391*(U-128));
int b_val = (int)round(1.164*(Y-16)+2.018*(U-128));
int currentRGBIndex = 3*(i * width + j);
rgb24Data[currentRGBIndex] = bound(0, r_val, 255);
rgb24Data[currentRGBIndex+1] = bound(0, g_val, 255);
rgb24Data[currentRGBIndex+2] = bound(0, b_val, 255);
}
}
}
int main() {
int width = 700, height = 700;
u_int8_t yuv444pData[width*height*3];
u_int8_t rgb24Data[width*height*3];
FILE *yuv444pFile = fopen("/Users/staff/Desktop/rainbow-yuv444p.yuv", "rb");
fread(yuv444pData, sizeof(yuv444pData), 1, yuv444pFile);
yuv444pToRGB(yuv444pData, rgb24Data, width, height);
FILE *rgb24File = fopen("/Users/staff/Desktop/rainbow-yuv444p-to-rgb24.rgb", "wb");
fwrite(rgb24Data, sizeof(rgb24Data), 1, rgb24File);
fclose(yuv444pFile);
fclose(rgb24File);
return 0;
}
ffplay -f rawvideo -pix_fmt yuv444p -video_size 700x700 rainbow-yuv444p.yuv
ffplay -f rawvideo -pix_fmt rgb24 -video_size 700x700 rainbow-yuv444p-to-rgb24.rgb
使用色彩丰富的图片验证
准备一张手机拍摄的 Disney.png
ffmpeg -i Disney.png -video_size 700x700 -pix_fmt yuv444p Disney-yuv444p.yuv
ffmpeg -i Disney.png -video_size 700x700 -pix_fmt rgb24 Disney-rgb24.rgb
ffplay -f rawvideo -pix_fmt yuv444p -video_size 700x700 Disney-yuv444p.yuv
ffplay -f rawvideo -pix_fmt rgb24 -video_size 700x700 Disney-rgb24.rgb
使用上面的代码进行转换后得到 Disney-rgb24-to-yuv444p.yuv Disney-yuv444p-to-rgb24.rgb
Congratulations!
代码:
08-rgb-to-yuv
参考资料:
YUV格式学习:YUV420P、YV12、NV12、NV21格式转换成RGB24
YUV420与YUV444互转,YUV420与YUV444读取和保存,YUV的显示和播放功能
内容有误?联系作者:
音视频入门-08-RGB&YUV的更多相关文章
- 音视频入门-07-认识YUV
* 音视频入门文章目录 * YUV & YCbCr 简介 YUV,是一种颜色编码方法.常使用在各个视频处理组件中. YUV 在对照片或视频编码时,考虑到人类的感知能力,允许降低色度的带宽. Y ...
- 音视频入门-10-使用libyuv对YUV数据进行缩放、旋转、镜像、裁剪、混合
* 音视频入门文章目录 * libyuv libyuv 是 Google 开源的实现各种 YUV 与 RGB 之间相互转换.旋转.缩放等的库.它是跨平台的,可在 Windows.Linux.Mac.A ...
- 音视频入门-09-RGB&YUV互转-使用开源库
* 音视频入门文章目录 * 介绍开源库 使用第三方开源库来简化开发,屏蔽一些底层的复杂度,节省大量编写代码的时间. libyuv: Google 开源的实现各种 YUV 与 RGB 之间相互转换.旋转 ...
- 音视频入门-01-认识RGB
* 音视频入门文章目录 * RGB 简介 RGB 色彩模式是工业界的一种颜色标准,是通过对红(R).绿(G).蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB 即是代表红 ...
- 音视频入门-11-PNG文件格式详解
* 音视频入门文章目录 * PNG 文件格式解析 PNG 图像格式文件由一个 8 字节的 PNG 文件署名域和 3 个以上的后续数据块(IHDR.IDAT.IEND)组成. PNG 文件包括 8 字节 ...
- 音视频入门-12-手动生成一张PNG图片
* 音视频入门文章目录 * 预热 上一篇 [PNG文件格式详解]详细介绍了 PNG 文件的格式. PNG 图像格式文件由一个 8 字节的 PNG 文件署名域和 3 个以上的后续数据块(IHDR.IDA ...
- 音视频入门-14-JPEG文件格式详解
* 音视频入门文章目录 * JPEG 文件格式解析 JPEG 文件使用的数据存储方式有多种.最常用的格式称为 JPEG 文件交换格式(JPEG File Interchange Format,JFIF ...
- 音视频入门-13-使用开源库生成PNG图片
* 音视频入门文章目录 * RGB-to-PNG 回顾 上一篇 [手动生成一张PNG图片] 根据 [PNG文件格式详解] 一步一步地手动实现了将 RGB 数据生成了一张 PNG 图片. 有许多开源的 ...
- 音视频入门-05-RGB-TO-BMP使用开源库
* 音视频入门文章目录 * RGB-TO-BMP 回顾 将 RGB 数据转成 BMP 图片: 了解 BMP 文件格式 准备 BMP 文件头信息 准备 BMP 信息头 BMP 存储 RGB 的顺序是 B ...
随机推荐
- [转载]IBM公司发布了最新的power7服务器p750 p770 p780
[转载]IBM公司发布了最新的power7服务器p750 p770 p780 (2015-06-11 12:54:17) 转载▼ http://blog.sina.com.cn/s/blog_6f52 ...
- ubuntu18.04安装docker和开通对外2375端口(方便portainer管理)
date: 2019-08-03 21:39:37 author: headsen chen apt-get install apt-transport-https ca-certificates ...
- netty5拆包问题解决实例
基于之前的例子(参见netty5自定义私有协议实例),我们修改下客户端handler,让发送的数据超过1024字节: NettyClientHandler: /** * 构造PCM请求消息体 * * ...
- Qt编写气体安全管理系统1-项目框架
一.前言 说到项目框架,也叫代码框架,其实是非常重要的,随着编程经验的增加,相信每个程序员都会有一个自己的习惯的项目框架,这个东西跟建房子一样,先把架子搭好,然后挨个往里边填充内容,据说牛逼的架构师都 ...
- HDU 2089 不要62 数位DP模板题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 参考博客:https://www.cnblogs.com/HDUjackyan/p/914215 ...
- LODOP插件的IE浏览器的安全设置
LodopFuncs.js里的判断默认是混合部署,IE等支持np插件的浏览器会走lodop插件方式,但是IE的安全设置可能会阻挡lodop插件,可点击允许或修改IE浏览器的安全设置让Lodop每次都能 ...
- 随机图片大小在DIV中垂直居中对齐总结
老遇到这种样式 现在总结一下 <!DOCTYPE> <html> <head> <meta http-equiv="Content-Type&quo ...
- iOS 多线程的简单理解(4) 线程锁的简单使用
要用到多线程 ,就不得不考虑,线程之间的交互,线程是否安全 推荐一个原文链接 是关于 线程锁的基本使用的 http://blog.csdn.net/qq_30513483/article/detai ...
- CentOS 6和CentOS 7的系统服务管理
也许你配置过Windows开机启动的服务,其中有些服务在日常的管理工作中用不到,我们就要把它停止,一来可以节省资源,而来可以减少安全隐患.在Linux上同样也有相关的工具来管理系统的服务. chkco ...
- Vue + ElementUI的电商管理系统实例02 主页
1.打开Element网站,找到主页需要的布局格式 修改Home.vue: <template> <el-container class="home-container&q ...