检测屏幕分辨率和颜色深度
全球纺织采购供应链色彩解决方案商——天友利,近几年来,越来越多的顶尖零售商和服装品牌厂家选择天友利作为自己的优选或共选色彩技术提供商。产品涉及行业:塑料、 涂料、 纺织、 汽车、 化妆品、 数码影像、 印前 、印刷、 油墨、 色觉测试、 包装等。
---- Windows API函数GetDeviceCaps()可提供广泛的关于设备背景的信息,其中包括屏幕分辨率和颜色深度。GUI程序设计允许将图形元素作为抽象的对象,不管硬件设备的情况及用户设置的选择。这对大多数情况,比如典型的窗口画面和设备无关位图操作都能满足。但是在某些特殊情况下将受到限制,程序员需要其它方法来获得相关设备的实际情况信息。本文就介绍一获取屏幕分辨率和颜色深度的应用程序。
---- 一、GetDeviceCaps()的功能
---- API函数GetDeviceCaps()可用来获取设备的很多信息,它也就成为应用和设备驱动程序的网关。下列为它在wingdi.h中的原型:int GetDeviceCaps(HDC hdc,int nIndex);
---- 第一项参数是与检测设备有关的设备背景,第二个参数表示检测值。函数的具体功能在Win32SDK文件中有详细介绍,本文集中介绍二个与显示设备最相关的特性:分辨率(水平和垂直)和能显示的不同颜色数。这些值能分别由HORZRES,VERTRES和BITSPIXEL返回给 GetDeviceCaps()的第二个参数。BITSPIXEL返回描述一个像素颜色需要的位数,要确定实际颜色数只要计算以2作为幂的返回值的指数。
---- 下列给出的C代码就是检测屏幕分辨率和颜色深度:
屏幕dc初始化
HDC screenDC;
int colorBits, xRes, yRes;
screenDC = CreateDC(DISPLAY, NULL, NULL, NULL);
检索设备
colorBits = GetDeviceCaps(screenDC, BITSPIXEL);
xRes = GetDeviceCaps(screenDC, HORZRES);
yRes = GetDeviceCaps(screenDC, VERTRES);
清除
DeleteDC(dc);
---- 从上述代码看好象很简单,而且这在大多数情况下是可行的,但当在32K彩色模式时就不行了,在这种情况下GetDeviceCaps()返回16而不是期望的15(2^15是32,768)。另外,32K和64K颜色之间的区别(两者也作为高-颜色方式)不大,当用15bit设备显示64K颜色位图时 Windows应用抖动算法实现。那么,怎么能检测32K颜色情况和将它与64K情况区别开
---- 二、开发SetPixel()函数功能
---- API函数比SetPixel(),以指定RGB颜色设置像素在设备背景上,还返回RGB值,而如果匹配不好的话,此返回的可能不是我们需要的颜色值。虽然,这一特性看上去没什么用处,但你可用它解决GetDeviceCaps()对15位颜色模式返回16位问题。如果用提供的RGB值设置一像素的颜色,并比较其返回的COLORREF,就能确定设备是否支持那种颜色。将上述算法放入一循环中,使RGB组合不断改变,设备既是视频卡,计算比较值为真的次数有多少。
---- 显然,用上述方法要对SetPixel()调用2^24次在时间上是不合理的,其实并不需要在所有可能的值之中重复,分别比较每个颜色组合(先红色,然后绿色,然后蓝色)也可产生相同的结果,并且迭代次数可减少到255次。
---- GetScrResolution()仅仅是对GetDeviceCaps(HORZRES)和GetDeviceCaps(VERTRES)的接连处理:
BOOL GetScrResolution(WORD pWidth, WORD pHeight)
{
HDC screenDC;
screenDC = CreateDC(DISPLAY, NULL, NULL, NULL);
if (!screenDC)
return FALSE;
pWidth = GetDeviceCaps(screenDC, HORZRES);
pHeight = GetDeviceCaps(screenDC, VERTRES);
DeleteDC(screenDC);
return TRUE;
}
---- GetScrColorDepth()调用GetDeviceCaps(BITSPIXEL),但是,当API返回16时,它使用 GetScrRGBBitsPerPixel()来依次计算红色、绿色和蓝色组合。如果他们都等于32,API返回代码16显然是不正确的,而实际上因是 15。
BYTE GetScrColorDepth()
{
HDC screenDC;
BYTE numOfBits;
screenDC = CreateDC(DISPLAY, NULL, NULL, NULL);
if (!screenDC)
return 0;
numOfBits = GetDeviceCaps(screenDC, BITSPIXEL);
DeleteDC(screenDC);
if (numOfBits == 16)
{
是否为64K色,或32K
WORD red, green, blue;
GetScrRGBBitsPerPixel(&red, &green, &blue);
if (red == 32 && green == 32 && blue == 32)
323232 = 2^15 色
numOfBits = 15;
}
return numOfBits;
}
GetScrRGBBitsPerPixel()通过255次循环测
试设备支持的红、绿色和蓝色值。
BOOL GetScrRGBBitsPerPixel(WORD pRedBits,
WORD pGreenBits,
WORD pBlueBits)
{
BOOL isError = FALSE;
HDC screenDC, memDC;
HBITMAP bmp = NULL;
HBITMAP bmpOld = NULL;
pRedBits = pGreenBits = pBlueBits = 1;
screenDC = CreateDC(DISPLAY, NULL,
NULL, NULL);
memDC = CreateCompatibleDC(NULL);
bmp = CreateCompatibleBitmap(screenDC, 1, 1);
isError = screenDC && memDC && bmp;
if (!isError)
goto CleanUp;
有时goto语句是处理出错的一种很简便的方法
bmpOld = (HBITMAP)SelectObject(memDC, bmp);
{
COLORREF oldColor;
COLORREF curColor = RGB(255, 255, 255);
int n;
for (n = 255; n = 0; --n)
{
oldColor = curColor;
curColor = SetPixel(memDC,
0, 0, RGB(n, n, n));
isError = curColor;
if (isError == CLR_INVALID)
{
isError = TRUE;
goto CleanUp;
}
计算红、绿和蓝匹配情况
if (GetRvalue(curColor)
GetRvalue(oldColor))
++(pRedBits);
if (GetGvalue(curColor)
GetGvalue(oldColor))
++(pGreenBits);
if (GetBvalue(curColor)
GetBvalue(oldColor))
++(pBlueBits);
}
}
CleanUp
if (bmpOld)
DeleteObject(bmpOld);
if (bmp)
DeleteObject(bmp);
if (isError)
pRedBits = pGreenBits
= pBlueBits = 0;
if (screenDC)
DeleteDC(screenDC);
if (memDC)
DeleteDC(memDC);
return !isError;
}
---- 可见GetScrRGBBitsPerPixel()不仅是解决本问题的核心,而且还可得到正使用的红色、绿色和蓝色各自的位数。例如,当有16位颜色时,哪一个颜色获得6位,而不是另二个的5位,你可通过测试发现,一般绿色成分多一些。
深圳市天友利标准光源有限公司主营产品:标准光源对色灯箱、英国-美国标准光源箱、汽车检测光源、镜头摄像头测试用标准光源、印刷行业用标准光源、电脑测色仪、分光密度仪、色卡、分辨率卡、色温照度计等光学仪器。