网页功能: 加入收藏 设为首页 网站搜索  
基于DirectDraw的Gamma calibrator机制之探讨
发表日期:2006-08-20作者:[转贴] 出处:  

一.问题的提出

Gamma calibrator基于动态gamma ramp技术。为系统提供动态gamma ramp支持,基于以下应用的需要:
1. 游戏程序的设计者可以为用户提供一致的视觉效果,而不论用户使用什么系统。
2. 随着电子商务的迅猛发展,商家和用户都迫切需要在Internet上看到货物样品的真实色彩。
3. 谁都希望,显示器上图像的色彩尽可能地和输出的色彩相近。

基于以上需要,具有Microsoft Windows Logo的硬件产品都需要提供动态gamma ramp支持(参见"Adapter supports downloadable RAMDAC entries for image color matching",网址: www.microsoft.com/hwdev/xpapers/pc98/14grfx98.htm)。只要显示卡及其驱动程序支持动态gamma ramp,buffer frame中所有象素的RGB值就可以被校正值取代。

为了在Windows95, Windows98和Windows2000中支持动态gamma ramp,DirectDraw中提供了IDirectDrawGammaControl接口。此接口允许程序设计者处理gamma ramp,使得象素的RGB值在被送到DAC显示之前得到校正。

本来,Win32 API中有两个函数(即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(DWORD 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程序调用。这两个函数的实现和COM DLL中的写法一致,这里不再赘述。注意信息要注册到HKEY_LOCAL_MACHINESOFTWAREMicrosoftDirectDrawGammaClibrator键之下。


2. 客户程序

客户程序必须支持DirectDraw,才能调用calibrator。
1)首先,创建一个Direct3D object:
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,但终究只是猜测,不知尚有多少规范没有实现。而且,在win2000下,DirectDraw对gamma calibration的支持似乎不够。再者,M$声称,目前DirectDraw和gamma calibrator的通信机制以及calibrator注册自身的方法只是一个过渡方案,将来会改变。鉴于以上原因,特写此文,以请对gamma calibration有研究者不吝赐教。

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 基于DirectDraw的Gamma calibrator机制之探讨
本类热点文章
  在DirectX 8 中进行2D渲染
  DirectDraw打造极速图形引擎(一)
  用窗口模式运行游戏
  DirectDraw编程基础
  Windows的位图alpha混合技术
  再谈GDI模式作图
  终极优化你的游戏——使用脏矩形技术
  D3D8里面的2D图形编程
  全屏模式
  对2D游戏引擎设计的一些思考
  DirectX8中的二维图形高级技巧
  使用标准GDI实现游戏品质的动画系统
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.0043