基於DirectDraw的Gamma calibrator機制之探討 (轉)
基於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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【轉】關於oracle中Move機制的一點探討Oracle
- 基於Kubernetes服務發現機制的探討Non Service
- Sql Server深入的探討鎖機制SQLServer
- SQL Server之旅(14):深入的探討鎖機制SQLServer
- 關於 DDoS 攻擊事件的探討(轉)事件
- 探討代理模式與Java反射機制的應用模式Java反射
- 關於 Roguelike 的探討,及基於 Roguelike 的新框架框架
- 分享交換機 VLAN 配置基礎及例項探討(轉)
- Sql Server之旅——第十四站 深入的探討鎖機制SQLServer
- 深入探討微服務架構中的同步通訊機制微服務架構
- 關於.Net中屬性的使用探討(一) (轉)
- 關於.Net中屬性的使用探討(二) (轉)
- 跟著辛星深入探討一下PHP的反射機制PHP反射
- 探討電子遊戲應如何設定簡單的成就機制遊戲
- 關於 js 物件 轉 字串 和 深拷貝 的 探討JS物件字串
- 關於多型實現Singleton模式的探討 (轉)多型模式
- 關於mongo原子操作的探討Go
- 關於identity列的探討IDE
- 我的理解——關於“ERP過時論”的探討(轉)
- IsPostBack深入探討(轉轉轉轉轉)
- 【轉】基於Token的WEB後臺認證機制Web
- 訂單系統中併發問題和鎖機制的探討
- SEO關於探討URL的知識!
- 程寅:關於支付流程的探討
- 關於rman中set newname的探討
- 基於物件導向(OO)的資料庫設計模式探討物件資料庫設計模式
- 探討基於資訊系統的專案型生產管理
- oracle 雙機部署模式探討Oracle模式
- Java執行緒的深入探討 (轉)Java執行緒
- 基於ReAct機制的AI AgentReactAI
- 從《雲頂之弈》探討競技遊戲中的隨機因素遊戲隨機
- 關於 performSelector 的一些小探討performSelector
- 關於python中slicing的探討Python
- 關於 Xmind 用例線上管理的探討
- 深入探討程式間通訊的重要性:理解不同的通訊機制(下)
- 深入探討程式間通訊的重要性:理解不同的通訊機制(上)
- 對軟體專案管理的探討 (轉)專案管理
- 對軟體專案管理的探討(轉)專案管理