RGB、YUY2、YUYV、YVYU、UYVY與AYUV

  最近項目中用到了好多YUV格式相關的東西,在網上找了一些資料,整理如下:

計算機彩色顯示器顯示色彩的原理與彩色電視機一樣,都是採用R(Red)、G(Green)、B(Blue)相加混色的原理:通過發射出三種不同強度的電子束,使屏幕內側覆蓋的紅、綠、藍磷光材料發光而產生色彩。這種色彩的表示方法稱爲RGB色彩空間表示(它也是多媒體計算機技術中用得最多的一種色彩空間表示方法)。
根據三基色原理,任意一種色光F都可以用不同分量的R、G、B三色相加混合而成。

F = r [ R ] + g [ G ] + b [ B ]

其中,r、g、b分別爲三基色參與混合的係數。當三基色分量都爲0(最弱)時混合爲黑色光;而當三基色分量都爲k(最強)時混合爲白色光。調整r、g、b三個係數的值,可以混合出介於黑色光和白色光之間的各種各樣的色光。
那麼YUV又從何而來呢?在現代彩色電視系統中,通常採用三管彩色攝像機或彩色CCD攝像機進行攝像,然後把攝得的彩色圖像信號經分色、分別放大校正後得到RGB,再經過矩陣變換電路得到亮度信號Y和兩個色差信號R-Y(即U)、B-Y(即V),最後發送端將亮度和色差三個信號分別進行編碼,用同一信道發送出去。這種色彩的表示方法就是所謂的YUV色彩空間表示。
採用YUV色彩空間的重要性是它的亮度信號Y和色度信號U、V是分離的。如果只有Y信號分量而沒有U、V分量,那麼這樣表示的圖像就是黑白灰度圖像。彩色電視採用YUV空間正是爲了用亮度信號Y解決彩色電視機與黑白電視機的兼容問題,使黑白電視機也能接收彩色電視信號。
YUV與RGB相互轉換的公式如下(RGB取值範圍均爲0-255):

Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B

R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U

在DirectShow中,常見的RGB格式有RGB1、RGB4、RGB8、RGB565、RGB555、RGB24、RGB32、ARGB32等;常見的YUV格式有YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、 YUV411、YUV420等。作爲視頻媒體類型的輔助說明類型(Subtype),它們對應的GUID見表2.3。

表2.3 常見的RGB和YUV格式

GUID    格式描述
MEDIASUBTYPE_RGB1    2色,每個像素用1位表示,需要調色板
MEDIASUBTYPE_RGB4    16色,每個像素用4位表示,需要調色板
MEDIASUBTYPE_RGB8    256色,每個像素用8位表示,需要調色板
MEDIASUBTYPE_RGB565    每個像素用16位表示,RGB分量分別使用5位、6位、5位
MEDIASUBTYPE_RGB555    每個像素用16位表示,RGB分量都使用5位(剩下的1位不用)
MEDIASUBTYPE_RGB24    每個像素用24位表示,RGB分量各使用8位
MEDIASUBTYPE_RGB32    每個像素用32位表示,RGB分量各使用8位(剩下的8位不用)
MEDIASUBTYPE_ARGB32    每個像素用32位表示,RGB分量各使用8位(剩下的8位用於表示Alpha通道值)
MEDIASUBTYPE_YUY2    YUY2格式,以4:2:2方式打包
MEDIASUBTYPE_YUYV    YUYV格式(實際格式與YUY2相同)
MEDIASUBTYPE_YVYU    YVYU格式,以4:2:2方式打包
MEDIASUBTYPE_UYVY    UYVY格式,以4:2:2方式打包
MEDIASUBTYPE_AYUV    帶Alpha通道的4:4:4 YUV格式
MEDIASUBTYPE_Y41P    Y41P格式,以4:1:1方式打包
MEDIASUBTYPE_Y411    Y411格式(實際格式與Y41P相同)
MEDIASUBTYPE_Y211    Y211格式
MEDIASUBTYPE_IF09    IF09格式
MEDIASUBTYPE_IYUV    IYUV格式
MEDIASUBTYPE_YV12    YV12格式
MEDIASUBTYPE_YVU9    YVU9格式

下面分別介紹各種RGB格式。

¨RGB1、RGB4、RGB8都是調色板類型的RGB格式,在描述這些媒體類型的格式細節時,通常會在BITMAPINFOHEADER數據結構後面跟着一個調色板(定義一系列顏色)。它們的圖像數據並不是真正的顏色值,而是當前像素顏色值在調色板中的索引。以RGB1(2色位圖)爲例,比如它的調色板中定義的兩種顏色值依次爲0x000000(黑色)和0xFFFFFF(白色),那麼圖像數據001101010111…(每個像素用1位表示)表示對應各像素的顏色爲:黑黑白白黑白黑白黑白白白…。

¨ RGB565使用16位表示一個像素,這16位中的5位用於R,6位用於G,5位用於B。程序中通常使用一個字(WORD,一個字等於兩個字節)來操作一個像素。當讀出一個像素後,這個字的各個位意義如下:
高字節              低字節
R R R R R G G G     G G G B B B B B
可以組合使用屏蔽字和移位操作來得到RGB各分量的值:

#define RGB565_MASK_RED    0xF800
#define RGB565_MASK_GREEN  0x07E0
#define RGB565_MASK_BLUE   0x001F
R = (wPixel & RGB565_MASK_RED) >> 11;   // 取值範圍0-31
G = (wPixel & RGB565_MASK_GREEN) >> 5;  // 取值範圍0-63
B =  wPixel & RGB565_MASK_BLUE;         // 取值範圍0-31

¨ RGB555是另一種16位的RGB格式,RGB分量都用5位表示(剩下的1位不用)。使用一個字讀出一個像素後,這個字的各個位意義如下:
高字節             低字節
X R R R R G G       G G G B B B B B       (X表示不用,可以忽略)
可以組合使用屏蔽字和移位操作來得到RGB各分量的值:

#define RGB555_MASK_RED    0x7C00
#define RGB555_MASK_GREEN  0x03E0
#define RGB555_MASK_BLUE   0x001F
R = (wPixel & RGB555_MASK_RED) >> 10;   // 取值範圍0-31
G = (wPixel & RGB555_MASK_GREEN) >> 5;  // 取值範圍0-31
B =  wPixel & RGB555_MASK_BLUE;         // 取值範圍0-31

¨ RGB24使用24位來表示一個像素,RGB分量都用8位表示,取值範圍爲0-255。注意在內存中RGB各分量的排列順序爲:BGR BGR BGR…。通常可以使用RGBTRIPLE數據結構來操作一個像素,它的定義爲:

typedef struct tagRGBTRIPLE {
BYTE rgbtBlue;    // 藍色分量
BYTE rgbtGreen;   // 綠色分量
BYTE rgbtRed;     // 紅色分量
} RGBTRIPLE;

¨ RGB32使用32位來表示一個像素,RGB分量各用去8位,剩下的8位用作Alpha通道或者不用。(ARGB32就是帶Alpha通道的 RGB32。)注意在內存中RGB各分量的排列順序爲:BGRA BGRABGRA…。通常可以使用RGBQUAD數據結構來操作一個像素,它的定義爲:

typedef struct tagRGBQUAD {
BYTE    rgbBlue;      // 藍色分量
BYTE    rgbGreen;     // 綠色分量
BYTE    rgbRed;       // 紅色分量
BYTE    rgbReserved;  // 保留字節(用作Alpha通道或忽略)
} RGBQUAD;

下面介紹各種YUV格式。YUV格式通常有兩大類:打包(packed)格式和平面(planar)格式。前者將YUV分量存放在同一個數組中,通常是幾個相鄰的像素組成一個宏像素(macro-pixel);而後者使用三個數組分開存放YUV三個分量,就像是一個三維平面一樣。表2.3中的YUY2到 Y211都是打包格式,而IF09到YVU9都是平面格式。(注意:在介紹各種具體格式時,YUV各分量都會帶有下標,如Y0、U0、V0表示第一個像素的YUV分量,Y1、U1、V1表示第二個像素的YUV分量,以此類推。)

¨ YUY2(和YUYV)格式爲每個像素保留Y分量,而UV分量在水平方向上每兩個像素採樣一次。一個宏像素爲4個字節,實際表示2個像素。(4:2:2的意思爲一個宏像素中有4個Y分量、2個U分量和2個V分量。)圖像數據中YUV分量排列順序如下:
Y0 U0 Y1 V0    Y2 U2 Y3 V2 …

¨ YVYU格式跟YUY2類似,只是圖像數據中YUV分量的排列順序有所不同:
Y0 V0 Y1 U0    Y2 V2 Y3 U2 …

¨ UYVY格式跟YUY2類似,只是圖像數據中YUV分量的排列順序有所不同:
U0 Y0 V0 Y1    U2 Y2 V2 Y3 …

¨ AYUV格式帶有一個Alpha通道,並且爲每個像素都提取YUV分量,圖像數據格式如下:
A0 Y0 U0 V0    A1 Y1 U1 V1 …

¨ Y41P(和Y411)格式爲每個像素保留Y分量,而UV分量在水平方向上每4個像素採樣一次。一個宏像素爲12個字節,實際表示8個像素。圖像數據中YUV分量排列順序如下:
U0 Y0 V0 Y1    U4 Y2 V4 Y3    Y4 Y5 Y6 Y8 …

¨ Y211格式在水平方向上Y分量每2個像素採樣一次,而UV分量每4個像素採樣一次。一個宏像素爲4個字節,實際表示4個像素。圖像數據中YUV分量排列順序如下:
Y0 U0 Y2 V0    Y4 U4 Y6 V4 …

¨ YVU9格式爲每個像素都提取Y分量,而在UV分量的提取時,首先將圖像分成若干個4 x 4的宏塊,然後每個宏塊提取一個U分量和一個V分量。圖像數據存儲時,首先是整幅圖像的Y分量數組,然後就跟着U分量數組,以及V分量數組。IF09格式與YVU9類似。

¨ IYUV格式爲每個像素都提取Y分量,而在UV分量的提取時,首先將圖像分成若干個2 x 2的宏塊,然後每個宏塊提取一個U分量和一個V分量。YV12格式與IYUV類似。

¨YUV411、YUV420格式多見於DV數據中,前者用於NTSC制,後者用於PAL制。YUV411爲每個像素都提取Y分量,而UV分量在水平方向上每4個像素採樣一次。YUV420並非V分量採樣爲0,而是跟YUV411相比,在水平方向上提高一倍色差採樣頻率,在垂直方向上以U/V間隔的方式減小一半色差採樣。

 

////////////////////////////////////////////////////////////////////////////////////////*******************************************************////////////////////////////////////////////////////////////////////////////////////

關於YUV格式的詳細介紹及內存排布方式如下:

YUV formats fall into two distinct groups, the packed formats where Y, U (Cb) and V (Cr) samples are packed together into macropixels which are stored in a single array, and the planar formats where each component is stored as a separate array, the final image being a fusing of the three separate planes.

In the diagrams below, the numerical suffix attached to each Y, U or V sample indicates the sampling position across the image line, so, for example, V0 indicates the leftmost V sample and Yn indicates the Y sample at the (n+1)th pixel from the left.

Subsampling intervals in the horizontal and vertical directions may merit some explanation. The horizontal subsampling interval describes how frequently across a line a sample of that component is taken while the vertical interval describes on which lines samples are taken. For example, UYVY format has a horizontal subsampling period of 2 for both the U and V components indicating that U and V samples are taken for every second pixel across a line. Their vertical subsampling period is 1 indicating that U and V samples are taken on each line of the image.

For YVU9, though, the vertical subsampling interval is 4. This indicates that U and V samples are only taken on every fourth line of the original image. Since the horizontal sampling period is also 4, a single U and a single V sample are taken for each square block of 16 image pixels.

Also, if you are interested in YCrCb to RGB conversion, you may find this page helpful.

People reading this page may be interested in a freeware codec from Drastic Technologies which allegedly handles the vast majority of YUV formats listed here. I've not tried it but you can find it here.

Packed YUV Formats

LabelFOURCC in HexBits per pixelDescription
AYUV0x5655594132Combined YUV and alpha
CLJR0x524A4C438Cirrus Logic format with 4 pixels packed into a u_int32. A form of YUV 4:1:1 wiht less than 8 bits per Y, U and V sample.
cyuv0x7675796316Essentially a copy of UYVY except that the sense of the height is reversed - the image is upside down with respect to the UYVY version.
GREY0x594552478Apparently a duplicate of Y800 (and also, presumably, "Y8  ")
IRAW0x57615349?Intel uncompressed YUV. I have no information on this format - can you help?
IUYV0x5659554916Interlaced version of UYVY (line order 0, 2, 4,....,1, 3, 5....) registered by Silviu Brinzei of LEAD Technologies.
IY410x3134594912Interlaced version of Y41P (line order 0, 2, 4,....,1, 3, 5....) registered by Silviu Brinzei of LEAD Technologies.
IYU10x315559491212 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec. This is equivalent to Y411
IYU20x325559492424 bit format used in mode 0 of the IEEE 1394 Digital Camera 1.04 spec
HDYC0x4359444816YUV 4:2:2 (Y sample at every pixel, U and V sampled at every second pixel horizontally on each line). A macropixel contains 2 pixels in 1 u_int32. This is a suplicate of UYVY except that the color components use the BT709 color space (as used in HD video).
UYNV0x564E595516A direct copy of UYVY registered by NVidia to work around problems in some old codecs which did not like hardware which offered more than 2 UYVY surfaces.
UYVP0x5056595524?YCbCr 4:2:2 extended precision 10-bits per component in U0Y0V0Y1 order. Registered by Rich Ehlers of Evans & Sutherland. (Awaiting confirmation of component packing structure)
UYVY0x5956595516YUV 4:2:2 (Y sample at every pixel, U and V sampled at every second pixel horizontally on each line). A macropixel contains 2 pixels in 1 u_int32.
V2100x303132563210-bit 4:2:2 YCrCb equivalent to the Quicktime format of the same name.
V4220x3232345616I am told that this is an upside down version of UYVY.
V6550x3535365616?16 bit YUV 4:2:2 format registered by Vitec Multimedia. I have no information on the component ordering or packing.
VYUY0x59555956?ATI Packed YUV Data (format unknown but you can get hold of a codec supporting it here)
Y4220x3232345916Direct copy of UYVY as used by ADS Technologies Pyro WebCam firewire camera.
YUY20x3259555916YUV 4:2:2 as for UYVY but with different component ordering within the u_int32 macropixel.
YUYV0x5659555916Duplicate of YUY2
YUNV0x564E555916A direct copy of YUY2 registered by NVidia to work around problems in some old codecs which did not like hardware which offered more than 2 YUY2 surfaces.
YVYU0x5559565916YUV 4:2:2 as for UYVY but with different component ordering within the u_int32 macropixel.
Y41P0x5031345912YUV 4:1:1 (Y sample at every pixel, U and V sampled at every fourth pixel horizontally on each line). A macropixel contains 8 pixels in 3 u_int32s.
Y4110x3131345912YUV 4:1:1 with a packed, 6 byte/4 pixel macroblock structure.
Y2110x313132598Packed YUV format with Y sampled at every second pixel across each line and U and V sampled at every fourth pixel.
Y41T0x5431345912Format as for Y41P but the lsb of each Y component is used to signal pixel transparency .
Y42T0x5432345916Format as for UYVY but the lsb of each Y component is used to signal pixel transparency .
YUVP0x5056555924?YCbCr 4:2:2 extended precision 10-bits per component in Y0U0Y1V0 order. Registered by Rich Ehlers of Evans & Sutherland.
Y8000x303038598Simple, single Y plane for monochrome images.
Y80x202038598Duplicate of Y800 as far as I can see.
Y160x203631591616-bit uncompressed greyscale image.

AYUV

This is a 4:4:4 YUV format with 8 bit samples for each component along with an 8 bit alpha blend value per pixel. Component ordering is A Y U V (as the name suggests).

UYVY (and Y422 and UYNV and HDYC)

UYVY is probably the most popular of the various YUV 4:2:2 formats. It is output as the format of choice by the Radius Cinepak codec and is often the second choice of software MPEG codecs after YV12.

Y422 and UYNV appear to be direct equivalents to the original UYVY.

HDYC is equivalent in layout but pixels are described using the BT709 color space as used in HD video systems rather than the BT470 SD video color space typically used. Apparently there is a description in the DeckLink DirectShow SDK documentation at http://blackmagic-design.com/support/software/archive/, find DeckLink SDK 5.6.2 for Windows XP and download http://blackmagic-design.com/support/software/register.asp?softID=108, set product to None, serial no is not required), see "Video Formats" section.

 HorizontalVertical
Y Sample Period11
V Sample Period21
U Sample Period21

Effective bits per pixel : 16

Positive biHeight implies top-down imge (top line first)

IUYV

IUYV is basically the same as UYVY with the exception that the data is interlaced. Lines are ordered 0,2,4,....,1,3,5.... instead of 0,1,2,3,4,5,....

cyuv

This FOURCC, allegedly registered by Creative Labs, is essentially a duplicate of UYVY. The only difference is that the image is flipped vertically, the first u_int16 in the buffer representing the bottom line of the viewed image. Note that the FOURCC is comprised of lower case characters (so much for the upper case convention !)

 HorizontalVertical
Y Sample Period11
V Sample Period21
U Sample Period21

Effective bits per pixel : 16

Positive biHeight implies bottom-up image (botton line first)

YUY2 (and YUNV and V422 and YUYV)

YUY2 is another in the family of YUV 4:2:2 formats and appears to be used by all the same codecs as UYVY.

 HorizontalVertical
Y Sample Period11
V Sample Period21
U Sample Period21

Effective bits per pixel : 16

Positive biHeight implies top-down image (top line first)

There is a help page here which contains information on playing AVIs which include video stored in YUY2 format.

YVYU

Despite being a simple byte ordering change from YUY2 or UYVY, YVYU seems to be seen somewhat less often than the other two formats defined above.

 HorizontalVertical
Y Sample Period11
V Sample Period21
U Sample Period21

Effective bits per pixel : 16

Positive biHeight implies top-down image (top line first)

Y41P

This YUV 4:1:1 format is registered as a PCI standard format. Mediamatics MPEG 1 engine is the only codec (other than a Brooktree internal one) that I know of that can generate it.

 HorizontalVertical
Y Sample Period11
V Sample Period41
U Sample Period41

Effective bits per pixel : 12

Positive biHeight implies top-down image (top line first)

Y411

I was originally told that this was a duplicate of Y41P however it seems that this is not the case after all. Y411 is a packed YUV 4:1:1 format with a 6 pixel macroblock structure containing 4 pixels. Component packing order is:

U2 Y0 Y1 V2 Y2 Y3

I have not been able to find 100% confirmation of the position for the U and V samples. I suspect that the chroma samples are probably both taken at the position of Y2 but this is a guess just now.

I have recently been informed that this format is identical to IYU1.

 HorizontalVertical
Y Sample Period11
V Sample Period41
U Sample Period41

Effective bits per pixel : 12

Positive biHeight implies top-down image (top line first)

IY41

IY41 is basically the same as Y41P with the exception that the data is interlaced. Lines are ordered 0,2,4,....,1,3,5.... instead of 0,1,2,3,4,5,....

Y211

I have yet to find anything that will output Y211 ! The format looks very much like the missing YUV 4:2:2 ordering but Y samples are only taken on every second pixel. Think of it as a half width 4:2:2 image and double the width on display.

 HorizontalVertical
Y Sample Period21
V Sample Period41
U Sample Period41

Effective bits per pixel : 8

Positive biHeight implies top-down image (top line first)

Y41T

This format is identical to Y41P except for the fact that the least significant bit of each Y component forms a chromakey channel. If this bit is set, the YUV image pixel is displayed, if cleared, the pixel is transparent (and the underlying graphics pixel is shown).

Positive biHeight implies top-down image (top line first)

Y42T

This format is identical to UYVY except for the fact that the least significant bit of each Y component forms a chromakey channel. If this bit is set, the YUV image pixel is displayed, if cleared, the pixel is transparent (and the underlying graphics pixel is shown).

Positive biHeight implies top-down image (top line first)

CLJR

Cirrus Logic's format packs 4 pixel samples into a single u_int32 by sacrificing precision on each sample. Y samples are truncated to 5 bits each, U and V have 6 bits per sample.

 HorizontalVertical
Y Sample Period11
V Sample Period41
U Sample Period41

Effective bits per pixel : 8

Positive biHeight implies top-down image (top line first)

IYU1

The IYU1 format is a 12 bit format used in mode 2 of the IEEE 1394 Digital Camera 1.04 spec ("1394-based Digital Camera Specification, Version 1.04, August 9, 1996", page 14.). The format, a duplicate of Y411, is YUV (4:1:1) according to the following pattern:

Byte012345
SampleU(K+0)Y(K+0)Y(K+1)V(K+0)Y(K+2)Y(K+3)

 

 HorizontalVertical
Y Sample Period11
V Sample Period41
U Sample Period41

IYU2

The IYU2 format is a 24 bit format used in mode 0 of the IEEE 1394 Digital Camera 1.04 spec (ibid.) The format is YUV (4:4:4) according to the following pattern:

Byte012345
SampleU(K+0)Y(K+0)V(K+0)U(K+1)Y(K+1)V(K+1)

 HorizontalVertical
Y Sample Period11
V Sample Period11
U Sample Period11

YUVP

This is another format similar to YUY2 and it's aliases. The difference here is that each Y, U and V samples is 10 bits rather than 8. I am still waiting to hear how the samples are packed - is a macropixel just 5 bytes long with all the samples packed together or is there more to it than this?

V210

AJA Video Systems have implemented this Quicktime format for Windows. It is a 10 bit per component, YCrCb 4:2:2 format in which samples for 5 pixels are packed into 4 4-byte little endian words. Rather than repeat the details here, I suggest looking at the original definition on the Quicktime web site.

Supposedly there are images described as "YUV10" that are formatted similarly to this aside from the bit ordering (the correspondent mentioned having to run ntoh on the pixel data to reformat from YUV10 to V210. Despite 20 years of C, I've not heard of ntoh but I suspect it performs big-endian to little-endian conversion).

Planar YUV Formats

LabelFOURCC in HexBits per pixel

Description

YVU90x3955565998 bit Y plane followed by 8 bit 4x4 subsampled V and U planes. Registered by Intel.
YUV90x395655599?Registered by Intel., this is the format used internally by Indeo video code
IF090x393046499.5As YVU9 but an additional 4x4 subsampled plane is appended containing delta information relative to the last frame. (Bpp is reported as 9)
YV160x36315659168 bit Y plane followed by 8 bit 2x1 subsampled V and U planes.
YV120x32315659128 bit Y plane followed by 8 bit 2x2 subsampled V and U planes.
I4200x30323449128 bit Y plane followed by 8 bit 2x2 subsampled U and V planes.
IYUV0x5655594912Duplicate FOURCC, identical to I420.
NV120x3231564E128-bit Y plane followed by an interleaved U/V plane with 2x2 subsampling
NV210x3132564E12As NV12 with U and V reversed in the interleaved plane
IMC10x31434D4912As YV12 except the U and V planes each have the same stride as the Y plane
IMC20x32434D4912Similar to IMC1 except that the U and V lines are interleaved at half stride boundaries
IMC30x33434D4912As IMC1 except that U and V are swapped
IMC40x34434D4912As IMC2 except that U and V are swapped
CLPL0x4C504C4312Format similar to YV12 but including a level of indirection.
Y41B0x4231345912?Weitek format listed as "YUV 4:1:1 planar". I have no other information on this format.
Y42B0x4232345916?Weitek format listed as "YUV 4:2:2 planar". I have no other information on this format.
Y8000x303038598Simple, single Y plane for monochrome images.
Y80x202038598Duplicate of Y800 as far as I can see.
CXY10x3159584312Awaiting clarification of format.
CXY20x3259584216Awaiting clarification of format.

YVU9

This format dates back to the days of the ActionMedia II adapter and comprises an NxN plane of Y samples, 8 bits each, followed by (N/4)x(N/4) V and U planes.

 HorizontalVertical
Y Sample Period11
V Sample Period44
U Sample Period44

Positive biHeight implies top-down image (top line first)

ATI has a codec supporting this format that you can download from here.

YUV9

Intel's web site states that YUV9 is "the color encoding scheme used in Indeo video technology. The YUV9 format stores information in 4x4 pixel blocks. Sixteen bytes of luminance are stored for every 1 byte of chrominance. For example, a 640x480 image will have 307,200 bytes of luminance and 19,200 bytes of chrominance." This sounds exactly the same as YVU9 to me. Anyone know if there is any difference?

IF09

A derivative of YVU9, IF09 contains the basic 3 planes for Y, V and U followed by an additional (N/4)x(N/4) plane of "skip blocks". This final plane forms a basic delta encoding scheme which can be used by a displayer to decide which pixels in the image are unchanged from the previous displayed frame. The strange number of bits per pixel listed for the format results from the fact that an NxN image is described using N2+3(N/4)2 bytes.

This format is generated by Intel's Indeo codecs though users should beware - the original 32 bit Indeo 3.2 shipped with Windows 95 and the beta levels of Indeo 4.1 contain bugs which cause them to generate protection faults when using IF09. Fixed versions of these codecs are available from Intel.

 HorizontalVertical
Y Sample Period11
V Sample Period44
U Sample Period44

Positive biHeight implies top-down image (top line first)

Delta plane definition

To be completed...

YV12

This is the format of choice for many software MPEG codecs. It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes.

 HorizontalVertical
Y Sample Period11
V Sample Period22
U Sample Period22

 

Positive biHeight implies top-down image (top line first)

ATI says they have a download which contains this codec but I can't find it on their site. If you would like something similar for Quicktime, try here.

YV16

This format is basically a version of YV12 with higher chroma resolution. It comprises an NxM Y plane followed by (N/2)xM U and V planes.

 HorizontalVertical
Y Sample Period11
V Sample Period21
U Sample Period21

IYUV and I420

These formats are identical to YV12 except that the U and V plane order is reversed. They comprise an NxN Y plane followed by (N/2)x(N/2) U and V planes. Full marks to Intel for registering the same format twice and full marks to Microsoft for not picking up on this and rejecting the second registration.

(Note: There is some confusion over these formats thanks to the definitions on Microsoft's site which tend to suggest that the two FOURCCs are different. One is described as a 4:2:0 format while the other is described as 4:1:1. Later, however, the same page states that YV12 is the same as both of these with the U and V plane order reversed. I would consider 4:2:0 to imply 1 chroma sample for every 2x2 luma block and 4:1:1 to imply 1 chroma sample for every 4x1 luma block but it seems as if the Microsoft writer may have been using the terms interchangeably. If you know these formats, please could you let me know whether the definition here is correct or whether I need to update one or other?)

 HorizontalVertical
Y Sample Period11
V Sample Period22
U Sample Period22

Positive biHeight implies top-down image (top line first)

CLPL

This format introduces an extra level of indirection in the process of accessing YUV pixels in the surface. Locking the DirectDraw or DCI CLPL surface returns a pointer which itself points to three other pointers. These pointers respectively point to an NxN Y plane, an (N/2)x(N/2) U plane and an (N/2)x(N/2) V plane. The Y plane pointer retrieved is (allegedly) valid even when the surface is subsequently unlocked but the U and V pointers can only be used with a lock held (as you should be doing anyway if adhereing to the DirectDraw/DCI spec).

 HorizontalVertical
Y Sample Period11
V Sample Period22
U Sample Period22

Positive biHeight implies top-down image (top line first)

Y800

This format contains only a single, 8 bit Y plane for monochrome images. Apparent duplicate FOURCCs are "Y8" and "GREY".

 HorizontalVertical
Y Sample Period11
V Sample PeriodN/AN/A
U Sample PeriodN/AN/A

  

Y16

This format contains only a single, 16 bit Y plane for monochrome images. Each pixel is represented by a 16 bit, little endian luminance sample.

 HorizontalVertical
Y Sample Period11
V Sample PeriodN/AN/A
U Sample PeriodN/AN/A

  

NV12

YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved U/V plane containing 8 bit 2x2 subsampled colour difference samples.

 HorizontalVertical
Y Sample Period11
V (Cr) Sample Period22
U (Cb) Sample Period22

Microsoft defines this format as follows:

 "A format in which all Y samples are found first in memory as an array of unsigned char with an even number of lines (possibly with a larger stride for memory alignment), followed immediately by an array of unsigned char containing interleaved Cb and Cr samples (such that if addressed as a little-endian WORD type, Cb would be in the LSBs and Cr would be in the MSBs) with the same total stride as the Y samples. This is the preferred 4:2:0 pixel format."

NV21

YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved V/U plane containing 8 bit 2x2 subsampled chroma samples. The same as NV12 except the interleave order of U and V is reversed.

 HorizontalVertical
Y Sample Period11
V (Cr) Sample Period22
U (Cb) Sample Period22

Microsoft defines this format as follows:

 "The same as NV12, except that Cb and Cr samples are swapped so that the chroma array of unsigned char would have Cr followed by Cb for each sample (such that if addressed as a little-endian WORD type, Cr would be in the LSBs and Cb would be in the MSBs)."

IMC1

IMC1 layoutSimilar to YV12, this format comprises an NxN Y plane followed by (N/2)x(N/2) U and V planes. The U and V planes have the same stride as the Y plane and are restricted to start on 16 line boundaries.

 HorizontalVertical
Y Sample Period11
V (Cr) Sample Period22
U (Cb) Sample Period22

Microsoft defines this format as follows:

 "The same as YV12, except that the stride of the Cb and Cr planes is the same as the stride in the Y plane. The Cb and Cr planes are also restricted to fall on memory boundaries that are a multiple of 16 lines (a restriction that has no effect on usage for the standard formats, since the standards all use 16×16 macroblocks)."

IMC2

IMC2 layoutSimilar to YV12, this format comprises an NxN Y plane followed by "rectangularly adjacent" (N/2)x(N/2) U and V planes. Lines of U and V pixels are interleaved at half stride boundaries below the Y plane.

 HorizontalVertical
Y Sample Period11
V (Cr) Sample Period22
U (Cb) Sample Period22

Microsoft defines this format as follows:

 "The same as IMC1, except that Cb and Cr lines are interleaved at half-stride boundaries. In other words, each full-stride line in the chrominance area starts with a line of Cr, followed by a line of Cb that starts at the next half-stride boundary. (This is a more address-space-efficient format than IMC1, cutting the chrominance address space in half, and thus cutting the total address space by 25%.) This runs a close second in preference relative to NV12, but NV12 appears to be more popular."

IMC3

The same as IMC1 except for swapping the U and V order.

IMC4

The same as IMC2 except for swapping the U and V order.

CXY1

Planar YUV 4:1:1 format registered by Conexant. Awaiting clarification of pixel component ordering.

CXY2

Planar YUV 4:2:2 format registered by Conexant. Awaiting clarification of pixel component ordering.

 

////////////////////////////////////////////////////////////////////////////////////////*******************************************************////////////////////////////////////////////////////////////////////////////////////

 

 下面給出了一個例子:

YUY2(YUV) 與 RGB 格式圖片的相互轉換 以及 基於YUY2(YUV)的blending

YUY2經常用於電視制式以及許多攝像頭的輸出格式.而我們在處理時經常需要將其轉化爲RGB進行處理,這裏簡單介紹下YUY2(YUV)與RGB之間相互轉化的關係:

http://msdn2.microsoft.com/en-us/library/ms893078.aspx

 

YUY2(YUV) To RGB:

C = Y - 16

D = U - 128

E = V - 128

R = clip(( 298 * C           + 409 * E + 128) >> 8)
G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
B = clip(( 298 * C + 516 * D           + 128) >> 8)

其中 clip()爲限制函數,將其取值限制在0-255之間.

 

RGB To YUY2(YUV):

Y = ( (  66 * R + 129 * G +  25 * B + 128) >> 8) +  16
U = ( ( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128
V = ( ( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128

上述兩個公式在代碼中的
int YUV2RGB(void* pYUV, void* pRGB, int width, int height, bool alphaYUV, bool alphaRGB);
int RGB2YUV(void* pRGB, void* pYUVX, int width, int height, bool alphaYUV, bool alphaRGB);
函數中轉換。

在諸如攝像頭的數據獲取中,我們往往需要直接在YUY2(YUV)空間上進行一些圖象處理,我們希望能夠在YUY2
(YUV)進行一些RGB上可以做到的處理。這裏已blending爲例,將兩張帶有透明度的YUY2(YUV)圖片進行疊加,
以達到在RGB空間進行圖像合成的效果。

RGB空間進行圖像疊加,通常背景(BG)是不透明的,而前景(FG)是帶有透明度的。在RGB空間,可以簡單表示爲:
Rdest = Rfg*alpha + Rbg*(1-alpha);
Gdest = Gfg*alpha + Gbg*(1-alpha);
Bdest = Bfg*alpha + Bbg*(1-alpha);
// Rdest、Gdest、Bdest 爲最終合成後的像素值

考慮到
Y = ( (  66 * R + 129 * G +  25 * B + 128) >> 8) +  16
U = ( ( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128
V = ( ( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128
我們可以推導出

(Ydest-16)<<8 = ((Yfg-16)<<8)*alpha + ((Ybg-16)<<8)*(1-alpha);
(Udest-128)<<8 = ((Ufg-128)<<8)*alpha + ((Ubg-128)<<8)*(1-alpha);
(Vdest-128)<<8 = ((Vfg-128)<<8)*alpha + ((Vbg-128)<<8)*(1-alpha);

從而可以得到
Ydest = (Yfg-16)*alpha + (Ybg-16)*(1-alpha) + 16;
Udest = (Ufg-128)*alpha + (Ubg-128)*(1-alpha) + 128;
Vdest = (Vfg-128)*alpha + (Vbg-128)*(1-alpha) + 128;

這個疊加過程在函數
int YUVBlending(void* pBGYUV, void* pFGYUV, int width, int height, bool alphaBG, bool alphaFG)
中實現。

由於本文針對攝像頭採集所得的數據進行處理,因此數據爲YUY2格式,即4個字節來表示兩個像素點的YUV信息,
排列爲Y1 U1 Y2 V2, 對於像素點1爲(Y1, U1, V1),像素點2爲(Y2, U1, V1)。即兩個像素點共用U、V信息。

這裏假設帶有alpha透明度的YUV格式用6個字節來表示兩個像素點的YUV以及alpha信息,排列爲 Y1 U1 Y2 V1 alpha1 alpha2
其中像素點1爲(Y1, U1, V1, alpha1),像素點2爲(Y2, U1, V1, alpha2)。其中alpha爲對應點的透明度信息。

而帶有alpha透明度RGB格式的圖片,假設爲32bits的BMP圖片,每個像素點用4bytes來表示,分別爲B G R alpha信息。

上述函數的具體實現爲:
//////////////////////////////////////////////////////////////////////////
// YUV2RGB
// pYUV			point to the YUV data
// pRGB			point to the RGB data
// width		width of the picture
// height		height of the picture
// alphaYUV		is there an alpha channel in YUV
// alphaRGB		is there an alpha channel in RGB
//////////////////////////////////////////////////////////////////////////
int YUV2RGB(void* pYUV, void* pRGB, int width, int height, bool alphaYUV, bool alphaRGB)
{
	if (NULL == pYUV)
	{
		return -1;
	}
	unsigned char* pYUVData = (unsigned char *)pYUV;
	unsigned char* pRGBData = (unsigned char *)pRGB;
	if (NULL == pRGBData)
	{
		if (alphaRGB)
		{
			pRGBData = new unsigned char[width*height*4];
		}
		else
			pRGBData = new unsigned char[width*height*3];
	}
	int Y1, U1, V1, Y2, alpha1, alpha2, R1, G1, B1, R2, G2, B2;
	int C1, D1, E1, C2;
	if (alphaRGB)
	{
		if (alphaYUV)
		{
			for (int i=0; i<height; ++i)
			{
				for (int j=0; j<width/2; ++j)
				{
					Y1 = *(pYUVData+i*width*3+j*6);    //i*width*3 = i*(width/2)*6
					U1 = *(pYUVData+i*width*3+j*6+1);
					Y2 = *(pYUVData+i*width*3+j*6+2);
					V1 = *(pYUVData+i*width*3+j*6+3);
					alpha1 = *(pYUVData+i*width*3+j*6+4);
					alpha2 = *(pYUVData+i*width*3+j*6+5);
					C1 = Y1-16;
					C2 = Y2-16;
					D1 = U1-128;
					E1 = V1-128;
					R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8);
					G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8);	
					B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8);	
					R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8);
					G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8);
					B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8);	
					*(pRGBData+(height-i-1)*width*4+j*8+2) = R1<0 ? 0 : R1;
					*(pRGBData+(height-i-1)*width*4+j*8+1) = G1<0 ? 0 : G1;
					*(pRGBData+(height-i-1)*width*4+j*8) = B1<0 ? 0 : B1;
					*(pRGBData+(height-i-1)*width*4+j*8+3) = alpha1;	
					*(pRGBData+(height-i-1)*width*4+j*8+6) = R2<0 ? 0 : R2;
					*(pRGBData+(height-i-1)*width*4+j*8+5) = G2<0 ? 0 : G2;
					*(pRGBData+(height-i-1)*width*4+j*8+4) = B2<0 ? 0 : B2;
					*(pRGBData+(height-i-1)*width*4+j*8+7) = alpha2;	
				}
			}	
		}
		else
		{
			int alpha = 255;
			for (int i=0; i<height; ++i)
			{
				for (int j=0; j<width/2; ++j)
				{
					Y1 = *(pYUVData+i*width*2+j*4);
					U1 = *(pYUVData+i*width*2+j*4+1);
					Y2 = *(pYUVData+i*width*2+j*4+2);
					V1 = *(pYUVData+i*width*2+j*4+3);
					C1 = Y1-16;
					C2 = Y2-16;
					D1 = U1-128;
					E1 = V1-128;
					R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8);
					G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8);	
					B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8);	
					R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8);
					G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8);
					B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8);	
					*(pRGBData+(height-i-1)*width*4+j*8+2) = R1<0 ? 0 : R1;
					*(pRGBData+(height-i-1)*width*4+j*8+1) = G1<0 ? 0 : G1;
					*(pRGBData+(height-i-1)*width*4+j*8) = B1<0 ? 0 : B1;
					*(pRGBData+(height-i-1)*width*4+j*8+3) = alpha;	
					*(pRGBData+(height-i-1)*width*4+j*8+6) = R2<0 ? 0 : R2;
					*(pRGBData+(height-i-1)*width*4+j*8+5) = G2<0 ? 0 : G2;
					*(pRGBData+(height-i-1)*width*4+j*8+4) = B2<0 ? 0 : B2;
					*(pRGBData+(height-i-1)*width*4+j*8+7) = alpha;	
				}
			}	
		}
	}
	else
	{
		if (alphaYUV)
		{
			for (int i=0; i<height; ++i)
			{
				for (int j=0; j<width/2; ++j)
				{
					Y1 = *(pYUVData+i*width*3+j*4);
					U1 = *(pYUVData+i*width*3+j*4+1);
					Y2 = *(pYUVData+i*width*3+j*4+2);
					V1 = *(pYUVData+i*width*3+j*4+3);
					C1 = Y1-16;
					C2 = Y2-16;
					D1 = U1-128;
					E1 = V1-128;
					R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8);
					G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8);	
					B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8);	
					R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8);
					G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8);
					B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8);	
					*(pRGBData+(height-i-1)*width*3+j*6+2) = R1<0 ? 0 : R1;
					*(pRGBData+(height-i-1)*width*3+j*6+1) = G1<0 ? 0 : G1;
					*(pRGBData+(height-i-1)*width*3+j*6) = B1<0 ? 0 : B1;
					*(pRGBData+(height-i-1)*width*3+j*6+5) = R2<0 ? 0 : R2;
					*(pRGBData+(height-i-1)*width*3+j*6+4) = G2<0 ? 0 : G2;
					*(pRGBData+(height-i-1)*width*3+j*6+3) = B2<0 ? 0 : B2;
				}
			}
		}
		else
		{
			for (int i=0; i<height; ++i)
			{
				for (int j=0; j<width/2; ++j)
				{
					Y1 = *(pYUVData+i*width*2+j*4);
					U1 = *(pYUVData+i*width*2+j*4+1);
					Y2 = *(pYUVData+i*width*2+j*4+2);
					V1 = *(pYUVData+i*width*2+j*4+3);
					C1 = Y1-16;
					C2 = Y2-16;
					D1 = U1-128;
					E1 = V1-128;
					R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8);
					G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8);	
					B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8);	
					R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8);
					G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8);
					B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8);	
					*(pRGBData+(height-i-1)*width*3+j*6+2) = R1<0 ? 0 : R1;
					*(pRGBData+(height-i-1)*width*3+j*6+1) = G1<0 ? 0 : G1;
					*(pRGBData+(height-i-1)*width*3+j*6) = B1<0 ? 0 : B1;
					*(pRGBData+(height-i-1)*width*3+j*6+5) = R2<0 ? 0 : R2;
					*(pRGBData+(height-i-1)*width*3+j*6+4) = G2<0 ? 0 : G2;
					*(pRGBData+(height-i-1)*width*3+j*6+3) = B2<0 ? 0 : B2;
				}
			}	
		}
	}
	return 0;
}

//////////////////////////////////////////////////////////////////////////
// RGB2YUV
// pRGB			point to the RGB data
// pYUV			point to the YUV data
// width		width of the picture
// height		height of the picture
// alphaYUV		is there an alpha channel in YUV
// alphaRGB		is there an alpha channel in RGB
//////////////////////////////////////////////////////////////////////////
int RGB2YUV(void* pRGB, void* pYUV, int width, int height, bool alphaYUV, bool alphaRGB)
{
	if (NULL == pRGB)
	{
		return -1;
	}
	unsigned char* pRGBData = (unsigned char *)pRGB;
	unsigned char* pYUVData = (unsigned char *)pYUV;
	if (NULL == pYUVData)
	{
		if (alphaYUV)
		{
			pYUVData = new unsigned char[width*height*3];
		}
		else
			pYUVData = new unsigned char[width*height*2];
	}
	int R1, G1, B1, R2, G2, B2, Y1, U1, Y2, V1;
	int alpha1, alpha2;
	if (alphaYUV)
	{
		if (alphaRGB)
		{
			for (int i=0; i<height; ++i)
			{
				for (int j=0; j<width/2; ++j)
				{
					B1 = *(pRGBData+(height-i-1)*width*4+j*8);
					G1 = *(pRGBData+(height-i-1)*width*4+j*8+1);
					R1 = *(pRGBData+(height-i-1)*width*4+j*8+2);
					alpha1 = *(pRGBData+(height-i-1)*width*4+j*8+3);
					B2 = *(pRGBData+(height-i-1)*width*4+j*8+4);
					G2 = *(pRGBData+(height-i-1)*width*4+j*8+5);
					R2 = *(pRGBData+(height-i-1)*width*4+j*8+6);
					alpha2 = *(pRGBData+(height-i-1)*width*4+j*8+7);
					Y1 = (((66*R1+129*G1+25*B1+128)>>8) + 16) > 255 ? 255 : (((66*R1+129*G1+25*B1+128)>>8) + 16);
					U1 = ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128)>255 ? 255 : ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128);
					Y2 = (((66*R2+129*G2+25*B2+128)>>8) + 16)>255 ? 255 : ((66*R2+129*G2+25*B2+128)>>8) + 16;
					V1 = ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128)>255 ? 255 : ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128);
					*(pYUVData+i*width*3+j*6) = Y1;
					*(pYUVData+i*width*3+j*6+1) = U1;
					*(pYUVData+i*width*3+j*6+2) = Y2;
					*(pYUVData+i*width*3+j*6+3) = V1;
					*(pYUVData+i*width*3+j*6+4) = alpha1;
					*(pYUVData+i*width*3+j*6+5) = alpha2;
				}
			}	
		}
		else
		{
			unsigned char alpha = 255;
			for (int i=0; i<height; ++i)
			{
				for (int j=0; j<width/2; ++j)
				{
					B1 = *(pRGBData+(height-i-1)*width*3+j*6);
					G1 = *(pRGBData+(height-i-1)*width*3+j*6+1);
					R1 = *(pRGBData+(height-i-1)*width*3+j*6+2);
					B2 = *(pRGBData+(height-i-1)*width*3+j*6+3);
					G2 = *(pRGBData+(height-i-1)*width*3+j*6+4);
					R2 = *(pRGBData+(height-i-1)*width*3+j*6+5);
					Y1 = ((66*R1+129*G1+25*B1+128)>>8) + 16;
					U1 = ((-38*R1-74*G1+112*B1+128)>>8+(-38*R2-74*G2+112*B2+128)>>8)/2 + 128;
					Y2 = ((66*R2+129*G2+25*B2+128)>>8) + 16;
					V1 = ((112*R1-94*G1-18*B1+128)>>8 + (112*R2-94*G2-18*B2+128)>>8)/2 + 128;
					Y1 = (((66*R1+129*G1+25*B1+128)>>8) + 16) > 255 ? 255 : (((66*R1+129*G1+25*B1+128)>>8) + 16);
					U1 = ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128)>255 ? 255 : ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128);
					Y2 = (((66*R2+129*G2+25*B2+128)>>8) + 16)>255 ? 255 : ((66*R2+129*G2+25*B2+128)>>8) + 16;
					V1 = ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128)>255 ? 255 : ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128);
					*(pYUVData+i*width*3+j*6) = Y1;
					*(pYUVData+i*width*3+j*6+1) = U1;
					*(pYUVData+i*width*3+j*6+2) = Y2;
					*(pYUVData+i*width*3+j*6+3) = V1;
					*(pYUVData+i*width*3+j*6+4) = alpha;
					*(pYUVData+i*width*3+j*6+5) = alpha;
				}
			}	
		}
	}
	else
	{
		if (alphaRGB)
		{
			for (int i=0; i<height; ++i)
			{
				for (int j=0; j<width/2; ++j)
				{
					B1 = *(pRGBData+(height-i-1)*width*4+j*8);
					G1 = *(pRGBData+(height-i-1)*width*4+j*8+1);
					R1 = *(pRGBData+(height-i-1)*width*4+j*8+2);
					B2 = *(pRGBData+(height-i-1)*width*4+j*8+4);
					G2 = *(pRGBData+(height-i-1)*width*4+j*8+5);
					R2 = *(pRGBData+(height-i-1)*width*4+j*8+6);
					Y1 = (((66*R1+129*G1+25*B1+128)>>8) + 16) > 255 ? 255 : (((66*R1+129*G1+25*B1+128)>>8) + 16);
					U1 = ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128)>255 ? 255 : ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128);
					Y2 = (((66*R2+129*G2+25*B2+128)>>8) + 16)>255 ? 255 : ((66*R2+129*G2+25*B2+128)>>8) + 16;
					V1 = ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128)>255 ? 255 : ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128);
					*(pYUVData+i*width*2+j*4) = Y1;
					*(pYUVData+i*width*2+j*4+1) = U1;
					*(pYUVData+i*width*2+j*4+2) = Y2;
					*(pYUVData+i*width*2+j*4+3) = V1;
				}
			}	
		}
		else
		{
			for (int i=0; i<height; ++i)
			{
				for (int j=0; j<width/2; ++j)
				{
					B1 = *(pRGBData+(height-i-1)*width*3+j*6);
					G1 = *(pRGBData+(height-i-1)*width*3+j*6+1);
					R1 = *(pRGBData+(height-i-1)*width*3+j*6+2);
					B2 = *(pRGBData+(height-i-1)*width*3+j*6+3);
					G2 = *(pRGBData+(height-i-1)*width*3+j*6+4);
					R2 = *(pRGBData+(height-i-1)*width*3+j*6+5);
					Y1 = (((66*R1+129*G1+25*B1+128)>>8) + 16) > 255 ? 255 : (((66*R1+129*G1+25*B1+128)>>8) + 16);
					U1 = ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128)>255 ? 255 : ((((-38*R1-74*G1+112*B1+128)>>8)+((-38*R2-74*G2+112*B2+128)>>8))/2 + 128);
					Y2 = (((66*R2+129*G2+25*B2+128)>>8) + 16)>255 ? 255 : ((66*R2+129*G2+25*B2+128)>>8) + 16;
					V1 = ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128)>255 ? 255 : ((((112*R1-94*G1-18*B1+128)>>8) + ((112*R2-94*G2-18*B2+128)>>8))/2 + 128);
					*(pYUVData+i*width*2+j*4) = Y1;
					*(pYUVData+i*width*2+j*4+1) = U1;
					*(pYUVData+i*width*2+j*4+2) = Y2;
					*(pYUVData+i*width*2+j*4+3) = V1;
				}
			}	
		}
	}
	return 0;
}

//////////////////////////////////////////////////////////////////////////
// pGBYUV			point to the background YUV data
// pFGYUV			point to the foreground YUV data
// width			width of the picture
// height			height of the picture
// alphaBG			is there an alpha channel in background YUV data
// alphaFG			is there an alpha channel in fourground YUV data
//////////////////////////////////////////////////////////////////////////
int YUVBlending(void* pBGYUV, void* pFGYUV, int width, int height, bool alphaBG, bool alphaFG)
{
	if (NULL == pBGYUV || NULL == pFGYUV)
	{
		return -1;
	}
	unsigned char* pBGData = (unsigned char*)pBGYUV;
	unsigned char* pFGData = (unsigned char*)pFGYUV;
	if (!alphaFG)
	{
		if (!alphaBG)
		{
			memcpy(pBGData, pFGData, width*height*2);
		}
		else
		{
			for (int i=0; i<height; ++i)
			{
				for (int j=0; j<width/2; ++j)
				{
					*(pBGData+i*width*2+j*4) = *(pFGData+i*width*2+j*4);
					*(pBGData+i*width*2+j*4+1) = *(pFGData+i*width*2+j*4+1);
					*(pBGData+i*width*2+j*4+2) = *(pFGData+i*width*2+j*4+2);
					*(pBGData+i*width*2+j*4+3) = *(pFGData+i*width*2+j*4+3);
				}
			}
		}
	}
	int Y11, U11, V11, Y12, Y21, U21, V21, Y22;
	int alpha1, alpha2;
	if (!alphaBG)
	{
		for (int i=0; i<height; ++i)
		{
			for (int j=0; j<width/2; ++j)
			{
				Y11 = *(pBGData+i*width*2+j*4);
				U11 = *(pBGData+i*width*2+j*4+1);
				Y12 = *(pBGData+i*width*2+j*4+2);
				V11 = *(pBGData+i*width*2+j*4+3);

				Y21 = *(pFGData+i*width*3+j*6);
				U21 = *(pFGData+i*width*3+j*6+1);
				Y22 = *(pFGData+i*width*3+j*6+2);
				V21 = *(pFGData+i*width*3+j*6+3);
				alpha1 = *(pFGData+i*width*3+j*6+4);
				alpha2 = *(pFGData+i*width*3+j*6+5);

				*(pBGData+i*width*2+j*4) = (Y21-16)*alpha1/255+(Y11-16)*(255-alpha1)/255+16;
				*(pBGData+i*width*2+j*4+1) = ((U21-128)*alpha1/255+(U11-128)*(255-alpha1)/255 + (U21-128)*alpha2/255+(U11-128)*(255-alpha2)/255)/2+128;
				*(pBGData+i*width*2+j*4+3) = ((V21-128)*alpha1/255+(V11-128)*(255-alpha1)/255 + (V21-128)*alpha2/255+(V11-128)*(255-alpha2)/255)/2+128;
				*(pBGData+i*width*2+j*4+2) = (Y22-16)*alpha2/255+(Y12-16)*(255-alpha2)/255+16;
			}
		}
	}
	else
	{
		for (int i=0; i<height; ++i)
		{
			for (int j=0; j<width/2; ++j)
			{
				Y11 = *(pBGData+i*width*3+j*6);
				U11 = *(pBGData+i*width*3+j*6+1);
				Y12 = *(pBGData+i*width*3+j*6+2);
				V11 = *(pBGData+i*width*3+j*6+3);

				Y21 = *(pFGData+i*width*3+j*6);
				U21 = *(pFGData+i*width*3+j*6+1);
				Y22 = *(pFGData+i*width*3+j*6+2);
				V21 = *(pFGData+i*width*3+j*6+3);
				alpha1 = *(pFGData+i*width*3+j*6+4);
				alpha2 = *(pFGData+i*width*3+j*6+5);

				*(pBGData+i*width*3+j*6) = (Y21-16)*alpha1/255+(Y11-16)*(255-alpha1)/255+16;
				*(pBGData+i*width*3+j*6+1) = ((U21-128)*alpha1/255+(U11-128)*(255-alpha1)/255 + (U21-128)*alpha2/255+(U11-128)*(255-alpha2)/255)/2+128;
				*(pBGData+i*width*3+j*6+3) = ((V21-128)*alpha1/255+(V11-128)*(255-alpha1)/255 + (V21-128)*alpha2/255+(V11-128)*(255-alpha2)/255)/2+128;
				*(pBGData+i*width*3+j*6+2) = (Y22-16)*alpha2/255+(Y12-16)*(255-alpha2)/255+16;
			}
		}
	}
	return 0;
}


 參考網址:

http://www.cppblog.com/bangle/archive/2009/07/07/89475.html

http://www.fourcc.org/yuv.php

http://blog.csdn.net/jtujtujtu/article/details/3874621

發佈了162 篇原創文章 · 獲贊 19 · 訪問量 86萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章