像素格式(pixel format)像素色彩按分量的大小和排列。這種格式以每個像素所使用的總位數以及用於存儲像素色彩的紅、綠、藍和 alpha 分量的位數指定。
基本介紹
- 中文名:像素格式
- 外文名:pixel format
- 方法:像素色彩按分量的大小和排列
- 作用:描述了像素數據存儲所用的格式
像素格式,顏色通道,全部格式,格式管,調色板,表示與轉換,生成算法,格式設定,格式屬性,格式筆記,WPF格式,視窗渲染,
像素格式
像素格式描述了像素數據存儲所用的格式。定義了像素在記憶體中的編碼方式。下面的像素格式 (PF_*) 類型定義了:
本地格式 (PF_A8R8G8B8 以及其他大量的不同的類型)
這意味著在記憶體中使用了本地儲存方式(big endian或者little endian,包括16,24,32位)的整形數據。同時意味著可以把PF_A8R8G8B8格式的圖片看作一個32位的整形數組,在16進制表現為0xAARRGGBB。這些字母的意義我們在稍後會提供。
位組格式Byte formats(PF_BYTE_*)
在這種格式下每個通道對應一個byte,通道在記憶體里的組織方式和格式名稱定義的相同。例如PF_BYTE_RGBA格式的像素包含了四個byte,一個對應紅色,一個綠色,一個藍色,以及一個alpha通道。
Short格式(PF_SHORT_*)
在這種格式下每個通道對應一個unsigned short數據(16 bit整型),通道在記憶體里的組織方式和格式名稱定義的相同。例如PF_BYTE_RGBA格式的像素包含了四個unsigned short數據,一個對應紅色,一個綠色,一個藍色,以及一個alpha通道。
Float16 格式(PF_FLOAT16_*)
在這種格式下每個通道對應一個16 bit浮點數,通道在記憶體里的組織方式和格式名稱定義的相同。例如PF_BYTE_RGBA格式的像素包含了四個16 bit浮點數數據,一個對應紅色,一個綠色,一個藍色,以及一個alpha通道。16 bit浮點數也被稱為半浮點(half float),非常類似於IEEE 對32bit單精度浮點數標準,只不過它只有5個exponent位和10個mantissa位而已。值得注意,這並不是一個標準的C++數據,CPU對其支持也不夠好,不過GPU卻能如同處理32bit浮點數一樣高效的處理它。
Float32格式(PF_FLOAT32_*)
在這種格式下每個通道對應一個32 bit浮點數,通道在記憶體里的組織方式和格式名稱定義的相同。例如PF_BYTE_RGBA格式的像素包含了四個32 bit浮點數數據,一個對應紅色,一個綠色,一個藍色,以及一個alpha通道。在C++中,這個數據就是普通的float。just “float”。
壓縮格式formats (PF_DXT[1-5])
S3TC壓縮紋理格式。
顏色通道
顏色通道中R,G,B,A,L 以及 X 的意義是:
R
紅色成分,通常範圍從0.0(沒有紅色)到1.0(全部的紅色)。
G
綠色成分,通常範圍從0.0(沒有綠色)到1.0(全部的綠色)。
B
藍色成分,通常範圍從0.0(沒有藍色)到1.0(全部的藍色)。
A
alpha(不透明度)成分,通常範圍從0.0(完全透明)到1.0(不透明)。
L
亮度成分,通常範圍從0.0(黑暗)到1.0(全白)。最終這個成分會被分散到RGB每箇中完成最終的圖像效果。
X
這個是被系統忽略的成分。
對於RGBL通道來說,默認的情況下設定為0。而Alpha通道卻不同,在默認的情況下被設定為1,代表不透明。
全部格式
當前版本的Ogre支持下列像素格式:
位組格式
PF_BYTE_RGB, PF_BYTE_BGR, PF_BYTE_BGRA, PF_BYTE_RGBA, PF_BYTE_L, PF_BYTE_LA, PF_BYTE_A
Short格式
PF_SHORT_RGBA
Float16格式
PF_FLOAT16_R, PF_FLOAT16_RGB, PF_FLOAT16_RGBA
Float32格式
PF_FLOAT32_R, PF_FLOAT32_RGB, PF_FLOAT32_RGBA
bit本地格式1
PF_L8, PF_A8, PF_A4L4, PF_R3G3B2
bit本地格式2
PF_L16, PF_R5G6B5, PF_B5G6R5, PF_A4R4G4B4, PF_A1R5G5B5
bit本地格式3
PF_R8G8B8, PF_B8G8R8
bit本地格式4
PF_A8R8G8B8, PF_A8B8G8R8, PF_B8G8R8A8, PF_R8G8B8A8, PF_X8R8G8B8, PF_X8B8G8R8, PF_A2R10G10B10 PF_A2B10G10R10
壓縮格式
PF_DXT1, PF_DXT2, PF_DXT3, PF_DXT4, PF_DXT5
格式管
調色板
Windows下的調色板:OpenGL可以使用16色、256色、64K和16M真彩色。真彩模式下不需要調色板,而在16色模式下根本不可能得到較為滿意的效果,因此對OpenGL而言,調色板只有在256色模式下才有意義。
我們知道,Windows把調色板分為系統調色板和邏輯調色板。每個應用程式都擁有一套自己的邏輯調色板(或使用預設調色板),當該應用程式擁有鍵盤輸入焦點時可以最多使用從16M種色彩中選取的256種顏色(20種系統保留顏色和236種自由選取的顏色),而失去焦點的應用程式可能會有某些顏色顯示不正常。系統調色板由Windows核心來管理,它是由系統保留的20種顏色和經仲裁後各個應用程式設定的顏色組成,並與硬體的256個調色板相對應。應用程式的邏輯調色板與硬體的調色板沒有直接的對應關係,而是按照最小誤差的原則映射到系統調色板中,因此即使應用程式自由選取256種不同顏色構成自己的邏輯調色板,也有可能某些顏色顯示到螢幕上時是一樣的。
當應用程式的視窗接收到鍵盤輸入焦點時,Windows會向它傳送一條WM_QUERYNEWPALETTE訊息,讓它設定自己的邏輯調色板,此時Windows會在系統調色板中儘量多地加入該應用程式需要的顏色,並生成相應的映射關係。接著Windows會向系統中所有的覆蓋型視窗和頂級視窗(包括擁有鍵盤輸入焦點的視窗)傳送一條WM_PALETTECHANGED訊息,讓它們設定邏輯調色板和重繪客戶區,以便能更充分地利用系統調色板,已擁有鍵盤輸入焦點的視窗不應再處理這條訊息,以避免出現死循環。
表示與轉換
OpenGL的顏色表示與轉換:
OpenGL內部用浮點數來表示和處理顏色,紅綠藍和Alpha值這四種成份每種的最大值為1.0,最小值為0.0。在256色模式下,OpenGL把一個像素顏色的內部值按線性關係轉換為8比特(Bit)來輸出到螢幕上,其中紅色占最低位的3比特,綠色占中間的3比特,藍色占最高位的2比特,Windows將這個8比特值看作邏輯調色板的索引值。例如OpenGL的顏色值(1.0,0.14,0.6667)經過轉換後二進制值為10001111(紅色為111,綠色為001,藍色為10),即第143號調色板,該調色板指定的顏色的RGB值應與(1.0,0.14,0.6667)有相同的比率,為(255,36,170),如果不是該值,那么顯示出來的顏色就會有誤差。
生成算法
調色板的生成算法:
很明顯,OpenGL輸出的8比特值中直接表明了顏色的組成,為了使圖形顯示正常,我們應以線性關係來設定邏輯調色板,使其索引值直接表明顏色的組成。因此生成調色板時,把索引值從低位到高位分成3-3-2共三個部分,將每一部分映射到0-255中去,這樣3比特映射為{0,36,73,109,146,182,219,255},2比特映射為{0,85,170,255},最後把三部分組合起來成為一種顏色。
經過上面的處理後,256種顏色均勻分布在顏色空間中,並沒有完全包含系統保留的20種顏色(只包含了7種),這意味著將會有數種顏色顯示成一樣,從而影響效果。一個較好的解決辦法是按照最小均方誤差的原則把13種系統顏色納入到邏輯調色板中。
從原理上來說,並非一定要使用線性映射,還可以用其它一些映射關係,如加入Gamma校正以便更能符合人眼的視覺特性,不過這些映射關係套用得並不廣泛,在此不再討論。
格式設定
像素格式是OpenGL視窗的重要屬性,它包括是否使用雙緩衝,顏色位數和類型以及深度位數等。像素格式可由Windows系統定義的所謂像素格式描述子結構來定義(PIXELFORMATDESCRIPTOR),該結構定義在windows.h中。
在該結構中包含有26個屬性信息,其形式為:
typedef struct tagPIXELFORMATDESCRIPTOR
{
WORD nSize;
WORD nVersion;
DWORD dwFlags;
BYTE iPixelType;
BYTE cColorBits;
BYTE cRedBits;
BYTE cRedShift;
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE cAccumBits;
BYTE cAccumRedBits;
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits;
BYTE cStencilBits;
BYTE cAuxBuffers;
BYTE iLayerType;
BYTE bReserved;
DWORD dwLayerMask;
DWORD dwVisibleMask;
DWORD dwDamageMask;
} PIXELFORMATDESCRIPTOR;
各變數的含義如下:
nSize:該結構所占記憶體空間。
nVersion:版本號,當前為1。
dwFlags:指定像素格式屬性,可選參量如表1.1所示。
格式屬性
標識符解釋
PFD_DRAW_TO_BITMAP 支持記憶體中繪製點陣圖
PFD_DRAW_TO_WINDOW 支持螢幕繪圖
PFD_DOUBLEBUFFER 支持雙緩衝
PFD_GENERIC_FORMAT 指定選擇GDI支持的像素格式
PFD_NEED_PALETTE 指定需要邏輯調色板
PFD_NEED_SYSTEM_PALETTE 指定需要硬體調色板
PFD_STEREO NT不支持
PFD_SUPPORT_OPENGL 支持OpenGL
PFD_SUPPORT_GDI 支持GDI,此時不可使用PFD_DOUBLEBUFFER
cColorBits:指定顏色的位數。
cRedBits:採用RGBA模式時,紅色組分占用位數。
cRedShift:採用RGBA模式時,紅色組分偏移量。
cGreenBits:採用RGBA模式時,綠色組分占用位數。
cGreenShift:採用RGBA模式時,綠色組分偏移量。
cBlueBits:採用RGBA模式時,藍色組分占用位數。
cBlueShift: 採用RGBA模式時,藍色組分偏移量。
cAlphaBits:採用RGBA模式時,Alpha組分占用位數。
cAlphaShift:採用RGBA模式時,Alpha組分偏移量。
cAccumBits:指定累積緩衝區表示一個像素所用位數。
cAccumRedBits:指定累積緩衝區表示紅色組分占用位數。
cAccumGreenBits:指定累積緩衝區表示綠色組分占用位數。
cAccumBlueBits:指定累積緩衝區表示藍色組分占用位數。
cAccumAlphaBits:指定累積緩衝區表示Alpha組分占用位數。
cDepthBits:指定深度緩衝區表示一個像素所用位數。
cStencilBits:指定模板緩衝區表示一個像素所用位數。
cAuxBuffers:指定輔助緩衝區,Windows9x、NT不支持。
iLayerType:Windows9x、NT下只能是PFD_MAIN_PLANE。
bReserved:=0。
dwLayerMask:指定覆蓋層的禁止,Windows9x、NT不支持。
dwVisibleMask:Windows9x、NT不支持。
dwDamageMask:Windows9x、NT不支持。
Windows提供了四個像素格式管理函式,分別介紹如下:
(1) int ChoosePixelFormat(HDC hdc,
PIXELFORMATDESCRIPTOR *ppdf)
該函式比較傳過來的像素格式描述和OpenGL支持的像素格式,返回一個最佳匹配的像素格式索引。該索引值可傳給SetPixelFormat為DC設定像素格式。返回值為0表示失敗。
在比較像素格式時,匹配優先權順序為像素格式描述子結構中的下述各域:
dwFlags->cColorBits->cAlphaBits->cAccumBits
->cDepthBits->cStencilBits->cAuxBuffers->iLayerType
硬體支持的像素格式優先。
(2) int DescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes,
LPPIXELFORMATDESCRIPTOR *ppfd)
該函式用格式索引iPixelFormat說明的像素格式來填寫由ppfd所指向的像素格式描述子結構,利用該函式可以枚舉像素格式。
(3) int GetPixelFormat(HDC hdc)
該函式用於獲取hdc的格式索引。
(4) BOOL SetPixelFormat(HDC hdc, int iPixelFormat,
LPPIXELFORMATDESCRIPTOR *ppfd)
該函式用格式索引iPixelFormat來設定hdc的像素格式。在使用該函式之前應該調用ChoosePixelFormat來獲取像素格式索引。另外,OpenGL視窗風格必須包含WS_CLIPCHILDREN和WS_CLIPSIBLINGS類型,否則設定失敗。
應該注意的是ChoosePixelFormat函式並不一定返回一個最佳的像素格式值,可以利用DescribePixelFormat來枚舉系統所支持的所有像素格式。OpenGL的通常支持24種不同的像素格式,如果系統安裝了OpenGL硬體加速器,它可能會支持其它的像素格式。
格式筆記
NUKE:
nuke的圖像數據保存在channel中,我們只需要用到其中的r,g,b三個channel。這三個channel是相互獨立的,可以分別從中讀取數據,每一次可以讀取圖像的一行像素。這樣看來,最合理的線性存儲方式就是每個channel的數據作為一組來保存,即:RRRR...RRRRGGGG...GGGGBBBB...BBBB的形式。
FFMPEG:
ffmpeg支持的編碼比較多,如果按照像素格式來分,主要有兩類,一類是是RGB,另一類是YUV。對於影像類編碼,比如xvid/mpeg4之類,顏色模式只能是YUV,甚至僅僅支持yuv420p這一種。因為要考慮到與nuke相結合,這裡只看rgb像素格式中的rgb24。rgb24的線性格式為:RRRR...RRRRGGGG...GGGGBBBB...BBBB,可以很方便的和nuke中的channel數據結合。
ffmpeg提供了一個函式可以在各種像素格式之間轉換。yuv420p的Cr和Cb分量只有Y分量大小的一半,因此需要的空間只有rgb24的2/3。
libquicktime:
libquicktime中沒有與上面RGB24一致的原始rgb格式,有一種rgb888格式。其線性格式為:RGBRGBRGB...。libquicktime在保存幀的時候也要先將rgb轉換為yuv,不過這個過程是自動完成的。
從rgb24到rgb888的轉換:
pFrameBufferLinear[y*w*3+3*x] = pFrameRGB_r[Y*w+i]; //R
pFrameBufferLinear[y*w*3+3*x+1] = pFrameRGB_g[Y*w+i]; //G
pFrameBufferLinear[y*w*3+3*x+2] = pFrameRGB_b[Y*w+i]; //B
WPF格式
在WPF中,圖像的像素格式較之於GDI+中有不少變化。比如新增了CMYK印刷通道的支持,對灰度圖片的灰階支持也有長足的進步,在顏色空間方面,新增了scRGB顏色空間,使圖像的色彩處理能力有很大的提高。
為了方便加深了解,我將它們按格式性質和色彩空間大致進行了分類。比如將Gray類的放在一起....
(1) BlackWhite:用於顯示黑白兩種色值的像素格式(非黑即白)。
(2) Gray2:2BPP(Bits Per Pixel,位/像素)的灰色通道。允許四種灰階。
(4) Gray8:顯示8BPP的灰度通道,允許256種灰階值表示灰色。
(5) Gray16:16BPP的灰色通道,最多允許65536種灰階值表示灰色。這種格式的Gamma是1.0。
(6) Gray32Float:32BPP的灰度通道,允許超過40億灰階。此格式的Gamma值是1.0。
(7) Indexed1:指定2種顏色作為調色板的像素格式。
(8) Indexed2:指定4種顏色作為調色板的像素格式。
(9) Indexed4:指定16種顏色作為調色板的像素格式。
(10) Indexed8:指定256種顏色作為調色板的像素格式。
(12) Bgra32:Bgra32像素格式是一種32BPP的sRGB格式。每個顏色通道(藍色blue, 綠色green, 紅色red)各占8BPP(位/像素),與Bgr24不同的是,它還有用於表現不透明度的alpha通道(8BPP)。
(14) Bgr32:Bgr32像素格式是一種採用32BPP(位/像素)的sRGB格式。與Bgr101010格式不同的是,它的每個顏色通道(藍色blue, 綠色green, 紅色red)各占8BPP(位/像素)。
(15) Bgr555:Bgr555也是一種sRGB格式,它採用16BPP(位/像素). 它的每個顏色通道(藍色blue, 綠色green, 紅色red)各占5BPP(位/像素)。
(16) Bgr565:Bgr565像素格式是一種16BPP(位/像素)的sRGB格式。它的每個顏色通道(藍色blue, 綠色green, 紅色red)分別占5BPP,6BPP,5BPP(位/像素)。
(17) Pbgra32:採用32BPP的一種基於sRGB的像素格式。每個顏色通道(藍色blue, 綠色green, 紅色red,Alpha通道)各占8BPP(位/像素)。每種顏色通道是經過與Alpha值預處理之後的。
(18) Prgba64:是一種基於sRGB格式,採用64BPP。每個顏色通道(藍色blue, 綠色green,紅色red,Alpha通道)各占32BPP(位/像素)。每種顏色通道是經過與Alpha值預處理之後的。這種格式的Gamma是1.0。
(19) Rgb24:是一種基於sRGB格式,採用24BPP。每個顏色通道(藍色blue, 綠色green, 紅色red)各占8BPP(位/像素)。
(20) Rgb48:是一種基於sRGB格式,採用48BPP。每個顏色通道(藍色blue, 綠色green, 紅色red)各占16BPP(位/像素)。這種格式的Gamma是1.0。
(21) Rgba64:是一種基於sRGB格式,採用64BPP。每個顏色通道(藍色blue, 綠色green, 紅色red,Alpha通道)各占16BPP(位/像素)。這種格式的Gamma是1.0。
(22) Rgb128Float:是一種基於ScRGB格式,採用128BPP。每個顏色通道各占32BPP(位/像素)。這種格式的Gamma是1.0。
(23) Rgba128Float:是一種基於ScRGB格式,採用128BPP。每個顏色通道(藍色blue, 綠色green, 紅色red,Alpha通道)各占32BPP(位/像素)。這種格式的Gamma是1.0。
(24) Prgba128Float:是一種基於ScRGB格式,採用128BPP。每個顏色通道(藍色blue, 綠色green,紅色red,Alpha通道)各占32BPP(位/像素)。每種顏色通道是經過與Alpha值預處理之後的。這種格式的Gamma是1.0。
(25) Cmyk32:用於表現印刷色格式,採用32BPP,共四個顏色通道即C、M、Y、K(青色Cyan, 品紅Magenta, 黃色Yellow和黑色blacK),各占8PP。
視窗渲染
表述像素格式:PIXELFORMATDESCRIPTOR
在OpenGL對視窗渲染之前,必須根據渲染需要對視窗進行配置。
需要硬體渲染還是軟體渲染?
渲染使用單緩衝還是雙緩衝?
是否需要深度緩衝區?
是否需要模板、目標Alpha或積累緩衝區?
當為視窗設定這些參數之後,就無法對它們進行修改。為了從一個只有深度緩衝和顏色緩衝區的視窗切換到一個帶有模板緩衝區的視窗,必須首先銷毀第一個視窗,然後根據需要重新創建一個視窗。
說明:
在OpenGL對視窗渲染之前,必須根據渲染需要對視窗進行配置。
需要硬體渲染還是軟體渲染?
渲染使用單緩衝還是雙緩衝?
是否需要深度緩衝區?
是否需要模板、目標Alpha或積累緩衝區?
當為視窗設定這些參數之後,就無法對它們進行修改。為了從一個只有深度緩衝和顏色緩衝區的視窗切換到一個帶有模板緩衝區的視窗,必須首先銷毀第一個視窗,然後根據需要重新創建一個視窗。
[ OpenGL]
PIXELFORMATDESCRIPTOR
The PIXELFORMATDESCRIPTOR structure describes the pixel format of a drawing surface.
typedef struct tagPIXELFORMATDESCRIPTOR
{ // pfd
WORD nSize; //結構大小: sizeof(PIXELFORMATDISCRIPTOR)
WORD nVersion; //版本:總設定為1
DWORD dwFlags; //像素緩衝區的屬性標記
BYTE iPixelType; //像素數據的類型
BYTE cColorBits; //顏色緩衝區中位平面的數量
BYTE cRedBits; //用多少位表示紅色
BYTE cRedShift; //紅色位的移位計數
BYTE cGreenBits; //
BYTE cGreenShift; //
BYTE cBlueBits; //
BYTE cBlueShift; //
BYTE cAlphaBits; //
BYTE cAlphaShift; //
BYTE cAccumBits; //積累緩衝區位數
BYTE cAccumRedBits; //積累緩衝區中紅色的位數
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits; //深度緩衝區位數
BYTE cStencilBits; //模板緩衝區位數
BYTE cAuxBuffers; //多少個輔助緩衝區
BYTE iLayerType; //過時或忽略
BYTE bReserved; //上層或下層平面的數量
DWORD dwLayerMask; //過時或忽略
DWORD dwVisibleMask; //下平面的透明顏色
DWORD dwDamageMask; //過時或忽略
} PIXELFORMATDESCRIPTOR;
//************************************************************************
//設定視窗像素格式
//************************************************************************
GLuint PixelFormat; // Holds The Results After Searching For A Match
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
32, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
1, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
if (!PixelFormat=ChoosePixelFormat(m_hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
MessageBox("Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!SetPixelFormat(m_hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
MessageBox("Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}