目录:
显示器图像显示概述
电视图像显示概述
RGB介绍
YUV介绍
隔行读取BMP
RGB转YUV
YUV转RGB
结束语
显示器图像显示概述:
我们知道普通彩色CRT显示器内部有三支电子枪,电子枪去激活显示器屏幕的荧光粉,三种荧光粉发射出的光生成一个像素位置的颜色点,这就是我们人眼能看到的一个像素。每个像素对应红、绿、蓝(R、G、B)三个强度等级,每个像素占用24位,可以显示近1700 万种颜色,这就是我们所说的真彩色。
普通彩色CRT显示器是基于电视技术的光栅扫描,电子束一次扫描一行,从顶到底依次扫描,整个屏幕扫描一次(我们称它为1帧),电子束扫描完一帧后回到最初位置进行下一次扫描。
电视图像显示概述:
电视显示原理与CRT相似,不过采用的是隔行扫描,我国的广播电视采用的是625行隔行扫描方式。隔行扫描是将一帧图像分两次(场)扫描。第一场先扫出1、3、5、7…等奇数行光栅,第二场扫出2、4、6、8…等偶数行光栅。通常将扫奇数行的场叫奇数场(也称上场),扫偶数行的场叫偶数场(也称下场)。为什么电视会选择隔行扫描,这是因为会使显示运动图像更平滑。下面两图为一帧图像的上场和下场的扫描过程。
(图1 上场扫描)
(图2 下场扫描)
常见的电视的制式有三种:NTSC、PAL、SECAM,我国的广播电视采用PAL制式,我国电视制式的帧频只有50HZ和我们日常使用的电流频率一样,PAL帧频为25fps,在文章后面我会以一张720x576的图像转换为720x 576 PAL隔行扫描的电视场视频格式作详细描述。
RGB介绍:
在记录计算机图像时,最常见的是采用RGB(红、绿,蓝)颜色分量来保存颜色信息,例如非压缩的24位的BMP图像就采用RGB空间来保存图像。一个像素24位,每8位保存一种颜色强度(0-255),例如红色保存为 0xFF0000。
YUV介绍:
YUV是被欧洲电视系统所采用的一种颜色编码方法,我国广播电视也普遍采用这类方法。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V”表示的则是色度(Chrominance或Chroma)。彩色电视采用YUV空间正是为了用亮度信号Y解决彩色电视机与黑白电视机的兼容问题,使黑白电视机也能接收彩色电视信号。
隔行读取BMP:
下面我说明如何隔行读取BMP图像,为什么我以BMP图像来作演示,因为BMP可以说是最简单的一种图像格式,最容易用它说明原理,那公为什么要用BMP来演示隔行读取呢,因为要实现RGB转电视场制图像,首先就要知识如何隔行读取。
BMP图像颜色信息的保存顺序是由左到右,由下往上,您可以执行一下附带程序的 (功能菜单->读取RGB) 看到图像的读取和显示过程。代码首先依次显示奇数行像素,如(1,3,5,7,9….行),完成后再依次显示偶数行像素,代码实现如下:
RGB转YUV
在整个视频行业中,定义了很多 YUV 格式,我以UYVY格式标准来说明,4:2:2 格式UYVY每像素占16 位,UYVY字节顺序如下图:
(图3 UYVY字节顺序)
其中第一个字节为U0,每二个字节为Y0,依次排列如下:
[U0,Y0,U1,Y1] [U1,Y2,V1,Y3] [U2,Y4,V2,Y5] ……
经过仔细分析,我们要实现RGB转YUV格式的话,一个像素的RGB占用三个节,而UYVY每像素占用两个字节,我演示直接把UYVY字节信息保存到*.pal格式中(这是我自己写来测试用的^_^),*.pal格式中,先保存上场像素,接着保存下场像素,如果是720x576的一张图像转换为YUV格式并保存的话,文件大小应该是829,440字节(720*576*2)。您可以执行本文附带的程序 (功能菜单->转换并写入YUV两场) 查看转换过程。
RGB转UYVY公式如下:
公式:(RGB => YCbCr)
Y = 0.257R′ + 0.504G′ + 0.098B′ + 16
Cb = -0.148R′ - 0.291G′ + 0.439B′ + 128
Cr = 0.439R′ - 0.368G′ - 0.071B′ + 128
代码实现:
像素转换实现:
YUV转RGB
关于YUV转换为RGB公式,我直接使用一篇文章提供的公式,经过思考,我发觉要想实现准确无误的把YUV转换为原有的RGB图像很难实现,因为我从UYVY的字节顺序来分析没有找到反变换的方法(您找到了记得告诉我哟: [email protected] ),例如我做了一个简单的测试:假设有六个像素的UYVY格式,要把这12个字节的UYVY要转换回18个字节的RGB,分析如下:
12个字节的UYVY排列方式:
[U0 Y0 V0 Y1] [U1 Y2 V1 Y3] [U2 Y4 V2 Y5]
完全转换为18个字节的RGB所需的UYVY字节排列如下:
[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3] [Y4 U4 V4] [Y5 U5 V5]
我们可以看到,12个字节的UYVY无法实现,缺少U3 V3 U4 V4。于是我抛开准确无误地把UYVY转换回RGB的想法,直接使用最近的UV来执行转换,结果发觉转换回来的RGB图像用肉眼根本分辩不出原有RGB图像与反变换回来的RGB图像差别,您可以执行本文附带的程序 (功能菜单->读取YUV并显示) 查看效果,下面是反变换公式和代码的实现:
代码实现:
结束语:
通过阅读本文,希望能让您理解一些RGB及YUV转换的细节,其实在一些开发包里已经提供了一些函数实现转换,本文只在于说明转换原理,没有对代码做优化,也没有对读取和写入格式做一些异常处理,希望您能体凉。YUV的格式非常多且复杂,本文只以UYVY为例,希望能起到抛砖引玉的作用。写本文之前笔者阅读了不少相关的文章不能一一列出,在此对他们无私的把自己的知识拿出来共享表示感谢。本文所带源码您可以直接到我的个人网站下载http://www.cgsir.com 。另外本人专门写了一个AVI转换为YUV视频格式的工具,如果您有需要,可以直接到我个人网站下载或直接与我联系。
参考文章:
Video Rendering with 8-Bit YUV Formats
关于YUV和RGB图像格式的问题
….
编程环境:Visual C++6.0 & MFC
关于作者:李英江目前就职于 湖南三辰卡通集团,是一名普通的程序员,可以通过以下方式与我取得联系。
QQ:15385155 MAIL: [email protected]
个人网站:http://www.cgsir.com