基於DirectDraw的Gamma calibrator機制之探討 (轉)

worldblog發表於2007-12-09
基於DirectDraw的Gamma calibrator機制之探討 (轉)[@more@]

基於DirectDraw的Gamma calibrator機制之探討


一.問題的提出

Gamma calibrator基於動態gamma ramp技術。為提供動態gamma ramp支援,基於以下應用的需要:
1. 遊戲的設計者可以為提供一致的視覺效果,而不論使用者使用什麼系統。
2. 隨著電子商務的迅猛發展,商家和使用者都迫切需要在Inte上看到貨物樣品的真實色彩。
3. 誰都希望,顯示器上影像的色彩儘可能地和輸出的色彩相近。

基於以上需要,具有 Logo的產品都需要提供動態gamma ramp支援(參見"Adapter supports able RAC entries for image color matching",網址: www.microsoft.com/hwdev/xpapers/pc98/14grfx98.htm)。只要顯示卡及其程式支援動態gamma ramp,buffer frame中所有象素的RGB值就可以被校正值取代。

為了在Windows95, Windows98和中支援動態gamma ramp,DirectDraw中提供了IDirectDrawGammaControl介面。此介面允許者處理gamma ramp,使得象素的RGB值在被送到DAC顯示之前得到校正。

本來, 中有兩個(即SetDeviceGammaRamp/GetDeviceGammaRamp)可以用來獲取和設定gamma ramp。但它們較之DirectDraw介面有以下侷限:
1. SetDeviceGammaRamp不允許設定所有可能的gamma ramp值。它會檢查gamma ramp,如果太複雜會拒絕。
2. SetDeviceGammaRamp目前不支援gamma calibrator。
3. SetDeviceGammaRamp的程式關閉後不會自動進行清理操作,除非將gamma ramp恢復到設定前的值。

與以上第二點相反,除了可以獲取和設定gamma ramp外,DirectDraw介面允許gamma ramp被校正(calibrated),這就需要一個gamma calibrator。


二.分析

據我所知,到目前為止,DirectDraw註冊和使用Gamma calibrator的機制尚未最終確定,只有一個過渡方案。此方案只用短短一句話進行了描述:calibrator在系統登錄檔中的某個key中註冊自身;當應用程式需要校正gamma ramp的時候,DirectDraw呼叫這個calibrator。

至於具體實現細節,到目前我沒發現任何文件。

基於此,我對DirectDraw呼叫calibrator的機制進行了分析和猜測,發現如下:

1)Calibrator中必須實現一個名為CalibrateGammaRamp的輸出函式,Gamma calibration的操作即在此函式中實現。
2)Calibrator必須將自身所在的安裝路徑註冊在系統登錄檔的如下key中:
  HKEY_LOCAL_MACHINESOFTWAREMicrosoftDirectDrawGammaClibrator
3)客戶程式透過呼叫IDirectDrawGammaControl::SetGammaRamp來間接觸發calibrator。
SetGammaRamp的原型為:
  HRESULT SetGammaRamp(D dwFlags, LPGAMMARAMP lpRampData)
DwFlag表示是否需要進行gamma calibration。若這個引數設為DDSGR_CALIBRATE,系統將會請求calibrator來調整gamma ramp,從而達到校正顯示效果的目的。若不需要校正,將這個引數設為0。LpRampData是DDGAMMARAMP結構的地址,此結構包含R,G,B三色素的gamma ramp值。
設定dwFlags引數為DDSGR_CALIBRATE並呼叫SetGammaRamp後,DirectDraw會自動根據calibrator的註冊資訊找到calibrator的路徑,並呼叫calibrator的CalibrateGammaRamp輸出函式,從而實現gamma calibration。

三.實現

我寫了兩段測試程式來檢驗Gamma calibrator的實現機制。calibrator.cpp編譯連結後生成calibrator.dll, 即gamma calibrator程式;test.cpp則生成test.exe,即客戶程式,它呼叫calibrator。

1. calibrator
calibrator本身的結構很簡單,它只需要實現三個函式(甚至一個,即CalibrateGammaRamp,其它兩個可以在安裝程式中或手工實現)。
1)CalibrateGammaRamp輸出函式。其宣告如下:
 extern "C" __declspec(dllexport) HRESULT CalibrateGammaRamp(D3DGAMMARAMP* pRamp)
其中輸入引數pRamp為當前的gamma ramp值(也即,客戶程式呼叫SetGammaRamp時設定的值)。出於測試的目的,在我的calibrator中沒有利用這個初始值,而是重新設定了gamma ramp,並誇張地將所有的R(Red)值設定為0,以方便地看到測試效果。

 HDC hDC = ::GetDC(NULL);
 if (!hDC)
 return E_FAIL;

 WORD RamdacTable[3*256];

 GetDeviceGammaRamp(hDC, RamdacTable);

 for (int i = 0; i < 3; ++i)
 for (int j = 0; j < 256; ++j)
 if ( i == 0)
 RamdacTable[i] = 0;
 else
 RamdacTable[i*256+j] = j*256;

 if(!SetDeviceGammaRamp( hDC, RamdacTable))
 {
 BOOL bReason = GetLastError();
 ::MessageBox(NULL, "SetDeviceGampRamp failed!", "Error", NULL);
 }

 ::ReleaseDC(NULL, hDC);

2)為了讓DLL可以register和unregister自己的安裝路徑,輸出兩個函式DllRegisterServer和DllUnregisterServer,以供regsvr32程式呼叫。這兩個函式的實現和DLL中的寫法一致,這裡不再贅述。注意資訊要註冊到HKEY_LOCAL_MACHINESOFTWAREMicrosoftDirectDrawGammaClibrator鍵之下。


2. 客戶程式

客戶程式必須支援DirectDraw,才能呼叫calibrator。
1)首先,建立一個Direct3D :
   LPDIRECT3D8 g_pD3D;
 g_pD3D = ::Direct3DCreate8(D3D_SDK_VERSION)
2)獲得當前顯示:
 D3DDISPLAYMODE d3ddm;
 g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)
3)建立Direct3D device:
 LPDIRECT3DDEVICE8  g_pd3dDevice = NULL;
 g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
 D3DDEVTYPE_HAL,
 hWnd,
 D3DCREATE_SOFTWARE_VERTEXPROCESSING,
 &d3dpp,
 &g_pd3dDevice )
4)檢測裝置是否支援gamma calibration:
 D3DCAPS8 d3dcap;
 if( FAILED( g_pd3dDevice->GetDeviceCaps( &d3dcap ) ) )
 {
 ::MessageBox(NULL, "GetDeviceCaps", "Failed", NULL); 
 return E_FAIL;
 }
 if( !( d3dcap.Caps2 & D3DCAPS2_CANCALIBRATEGAMMA ) )
 {
 ::MessageBox(NULL, "Your machine doesn't support gamma Calibrator", "Warnning", NULL);
 return E_FAIL;
 }
5)設定gamma ramp:
 D3DGAMMARAMP d3dgamaramp;
 ... // 初始化d3dgamaramp

 // 設定gamma ramp,同時請求calibration
 g_pd3dDevice->SetGammaRamp( D3DSGR_CALIBRATE , &d3dgamaramp);


四.結論
由於沒看到M$關於gamma calibration的正式文件,以上機制純屬自己的猜測。測試程式雖能work,但終究只是猜測,不知尚有多少規範沒有實現。而且,在下,DirectDraw對gamma calibration的支援似乎不夠。再者,M$聲稱,目前DirectDraw和gamma calibrator的通訊機制以及calibrator註冊自身的方法只是一個過渡方案,將來會改變。鑑於以上原因,特寫此文,以請對gamma calibration有研究者不吝賜教。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990318/,如需轉載,請註明出處,否則將追究法律責任。

相關文章