2010-05-18 110 views
1

我刚刚开始使用win32 GDI编程,并且很难找到很好的参考。我有一个简单的应用程序,通过执行以下捕获屏幕:win32 - 如何将画面捕捉为8位或16位位图?

UINT32 x,y; 
x = GetSystemMetrics(SM_CXSCREEN); 
y = GetSystemMetrics(SM_CYSCREEN); 

HDC hdc = GetDC(NULL); 
HDC hdcScreen = CreateCompatibleDC(hdc); 

HBITMAP hbmp = CreateCompatibleBitmap(hdc, x, y); 

SelectObject(hdcScreen, hbmp); 

BitBlt(hdcScreen, 0, 0, x, y, hdc, 0, 0, SRCCOPY) 

ReleaseDC(NULL, hdc); 

我捕捉兼容的位图,其中我的机器上是32位的。使用相同/相似的呼叫,我将如何捕捉8位的屏幕?那么16位呢?

回答

2

使用CreateDIBSection来创建一个8bpp位图,并BitBlt到那。


填充BITMAPINFO结构将是有趣的。您不能使用普通的BITMAPINFO结构,因为它只为单个调色板条目分配空间,而对于8bpp图像,您将需要全部256个条目。

如果您想作弊一点,可以使用匿名联合来为其调色板声明一个具有足够空间的BITMAPINFO。

union 
{ 
    BITMAPINFO bmi; 
    struct { 
    BITMAPINFOHEADER bmih; 
    RGBQUAD extra[256]; 
    } dummy; 
}; 

bmi.bmiHeader.biSize = sizeof (bmi.bmiHeader); 
bmi.biBitCount = 8; 
// and so on. 

至于颜色表初始化值...我想不出一个简单的方法来从GDI获得一个默认8bpp的调色板时,其不8bpp的模式。我怀疑CreateHalftonePalette不会在非调色板设备上执行任何操作。

+0

那么转换为16位呢?这会改变什么? – Jon 2010-05-18 19:01:55

+1

使用> 8位,您不需要为颜色表分配空间。因此,请忽略--- – 2010-05-18 19:08:14

+0

以下的所有内容,谢谢Chris,这非常有帮助! – Jon 2010-05-18 19:10:18

1

我敢肯定,你必须捕捉一个32位的位图,然后将其自己转换为8位。 8位转换通常会丢失相当数量的数据,并且有多少不同的算法可用于如何执行此操作。除非你真的有没有的选择,否则我会重新考虑这样做。这是一个时间,因为大多数人有很多理由弄乱8位位图 - 他们一团糟。

8位位图(至少是典型的位图)有一个“调色板”,它指定位图文件中要使用的每个(最多)256种颜色的24位值。通常情况下,您希望选取与原始位图中最接近的颜色。发明了算法的批次这样做。谷歌搜索类似于“减少颜色算法”应该会产生不少的点击量,关于如何做这些点的变化有很多,从执行速度,内存使用情况等等来衡量。我甚至无法猜测哪种方法最适合为了您的特定目的。

正如我刚才所说的,我的第一个想法是花一些时间和精力来简单地消除这个要求。从32位减少到24位甚至16位是非常容易的,并且保留了原始质量的批次。去8位是相当困难失去了很多的质量。