C win32-如何将屏幕捕获为8位或16位位图?

C win32-如何将屏幕捕获为8位或16位位图?,c,winapi,bitmap,C,Winapi,Bitmap,我刚开始使用win32 GDI编程,很难找到好的参考资料。我有一个简单的应用程序,通过执行以下操作来捕获屏幕: UINT32 x,y; x = GetSystemMetrics(SM_CXSCREEN); y = GetSystemMetrics(SM_CYSCREEN); HDC hdc = GetDC(NULL); HDC hdcScreen = CreateCompatibleDC(hdc); HBITMAP hbmp = CreateCompatibleBitmap(hdc, x,

我刚开始使用win32 GDI编程,很难找到好的参考资料。我有一个简单的应用程序,通过执行以下操作来捕获屏幕:

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位怎么样?

用于创建一个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模式下时,我想不出一个简单的方法从GDI获得默认的8bpp调色板。我怀疑这在非调色板设备上不会起任何作用。

我很确定您必须捕获32位位图,然后自己将其转换为8位。8位转换通常会丢失相当数量的数据,对于如何实现这一点,有很多不同的算法。除非你真的别无选择,否则我会重新考虑这样做。很长一段时间以来,大多数人都没有足够的理由去搞乱8位位图——它们真是一团糟

8位位图(至少是典型位图)有一个“调色板”,指定位图文件中要使用的256种颜色中每种颜色的24位值。通常,您希望选择与原始位图中颜色最接近的颜色。已经有很多算法被发明来实现这一点。在谷歌上搜索“颜色还原算法”之类的东西应该会产生相当多的点击率,在如何操作上会有相当多的变化,权衡执行速度、内存使用等。我甚至无法猜测哪一个最适合您的特定用途


正如我前面所说,我的第一个倾向是投入一些时间和精力来简单地消除这个需求。从32位减少到24位甚至16位是相当容易的,并且保留了许多原始质量。转换为8位要困难得多,而且会损失很多质量。

转换为16位怎么样?这将如何改变情况?使用>8位,您无需为颜色表分配空间。所以忽略下面的所有内容---谢谢Chris,这非常有帮助!