【问题标题】:Saving pixels from screen HDC从屏幕 HDC 保存像素
【发布时间】:2019-08-25 11:58:18
【问题描述】:

许多论坛提供以下代码,说明如何将屏幕像素的副本放入数组:

char* Pixels = NULL;
HDC MemDC = CreateCompatibleDC(Context);
HBITMAP Section = CreateDIBSection(Context, &Info, DIB_RGB_COLORS, (void**)&Pixels, 0, 0);
DeleteObject(SelectObject(MemDC, Section));
BitBlt(MemDC, 0, 0, Width, Height, Context, Area.left, Area.top, SRCCOPY);
DeleteDC(MemDC);
std::fstream hFile(FilePath, std::ios::out | std::ios::binary);
if (hFile.is_open())
{
    hFile.write((char*)&Header, sizeof(Header));
    hFile.write((char*)&Info.bmiHeader, sizeof(Info.bmiHeader));
    hFile.write(Pixels, (((BitsPerPixel * Width + 31) & ~31) / 8) * Height);
    hFile.close();
    DeleteObject(Section);
    return true;
}

(Link)

但这实际上涉及将像素“内存”区域从屏幕 HDC 复制到内存中。为什么不这样:

char* Pixels = NULL;
HBITMAP Section = CreateDIBSection(Context, &Info, DIB_RGB_COLORS, (void**)&Pixels, 0, 0);
SelectObject(Context, Section);

上下文 HDC 已包含所有数据。为什么我不能读呢?

我认为位图必须选择到 HDC 中,并且 HDC 实际上携带数据。那么为什么CreateDIBSection 会返回一个指针,尽管位图还没有被选择到任何 HDC 中呢? (如果它提供了一个指向作为参数传递的 HDC 内存的指针,则该数组已经包含屏幕的像素值,但情况并非如此,因为仍然需要 BitBlt。)

我得出这个结论是因为 BitBlt 接受 HDC 参数,而不是位图。这可能意味着它将数据复制到关联的 HDC。

【问题讨论】:

    标签: c++ bitblt gdi createdibsection


    【解决方案1】:

    视频内存可以存储在多个位置,包括主系统内存 (RAM)、视频卡上的专用内存、外部显示设备,甚至这些位置的某种组合。对该内存的访问可能缓慢,并且进程可能无法访问该内存(至少需要将其映射到进程的地址空间)。

    存储在硬件中的视频数据在传递到您的应用程序之前可能需要转换为不同的格式。并且该硬件可能能够利用其他方法来复制不直接涉及 CPU 的数据(如直接内存访问或 DMA)。由于该复制确实需要一些时间,因此您需要的部分可能会先复制到视频适配器上视频内存的另一部分(这可能是一个非常快速的过程),然后再复制到主内存(一个慢得多的过程)。

    视频显示也是共享资源:系统上的所有进程都可能需要访问它。如果你有一个指向视频内存的指针,你读到的可能不是可见的(如果它被更新为不同的内容),或者如果你写它可能会损坏屏幕。

    【讨论】:

    • 那么createDIBSection返回的指针指向什么?收到的唯一参数是屏幕 hdc,它绝对不是指向其数据的指针。
    • 而且它也没有绑定到memDC。 (因为即使我们选择了memDC上的section后,指针仍然保持不变。这意味着这个指针不是HDC的函数,它是独立于它的。那么它是什么?
    • 它看起来好像是一个独立的内存区域。我选择位图的 HDC 可以是完整的并且包含它想要的任何内容,但是如果我不将某些内容 BitBlt 到该 hdc 上,那么部分内存将不会改变。对吗?
    • @sergiureznicencu CreateDIBSection 返回一个应用程序可以直接写入的指针。它可能驻留在主系统 RAM 中。
    • 当我在 hdc 中选择一个部分时,究竟会发生什么? HDC 代表一些具有图形内存的设备,该部分还包含其自己的内存区域。我理解速度参数和损坏问题(可能这就是为什么我必须使用 BitBlt :拍摄该内存的“快照”)但为什么我必须“选择”该部分?为什么我不能给 BitBlt CreateDIBSection 返回的指针?
    猜你喜欢
    • 2013-06-11
    • 2014-03-18
    • 2013-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多