* 音视频入门文章目录 *

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 格式与 RGB 格式的相互转换公式及C++ 代码

Color Conversion

videolan-YUV

博客目录-技术-视频处理

YUV格式学习:YUV420P、YV12、NV12、NV21格式转换成RGB24

图像RGB2YUV与YUV2RGB格式互转介绍

YUV转RGB的优化算法

YUV 格式与 RGB 格式的相互转换公式及C++ 代码

YUV420与YUV444互转,YUV420与YUV444读取和保存,YUV的显示和播放功能

YCbCr与YUV的区别

维基百科-YUV

维基百科-YCbCr

内容有误?联系作者:


最新文章

  1. Eclipse中JAR System library 没有怎么添加?
  2. jQuery学习笔记--JqGrid相关操作 方法列表(上)
  3. js常用方法
  4. QQ5.0左侧滑动显示效果
  5. hive的内部表与外部表创建
  6. 21SpringMvc_异步发送表单数据到Bean,并响应JSON文本返回(这篇可能是最重要的一篇了)
  7. 洛谷P2736 “破锣摇滚”乐队 Raucous Rockers
  8. CentOS 5.5 下安装Countly Web Server过程记录
  9. 跨平台 c 开发库 tbox v1.6.0,支持跨平台协程
  10. 《锋利的jQuery》心得笔记--One Sections
  11. Javascript 绝对定位和相对定位
  12. mysql备份工具 :mysqldump mydumper Xtrabackup 原理
  13. Python 自动化脚本学习(三)
  14. Unix环境下PS1变量的设置
  15. HTML元素的ID和Name属性的区别
  16. History of program
  17. Hdoj 1159.Common Subsequence 题解
  18. JQ替换标签与内容
  19. Guava的SetMultimap
  20. 腾讯云服务器 安装fastdfs文件服务器

热门文章

  1. HmacSHA256摘要算法
  2. nginx高级玩法之根据来源ip分流
  3. eclipse中导入spring-boot框架的jar包方法
  4. Android平台云端打包证书使用说明
  5. 泡泡一分钟:Fast and Robust Initialization for Visual-Inertial SLAM
  6. Spring cloud微服务安全实战-5-3后端服务改造
  7. Python初级 4 数据的类型
  8. Django Model 定义语法
  9. Python - Django - ORM 自定义 char 类型字段
  10. 常见的SQL注入检测语句(转载)