【问题标题】:BitBlt Copy Bitmap from ClipBoard gives wrong colorsBitBlt 从剪贴板复制位图给出错误的颜色
【发布时间】:2012-10-17 23:09:14
【问题描述】:

我正在将剪贴板中的图像粘贴到我的程序中。位图放在背景 memDC 位图上,然后在绘制到屏幕之前与另一个 memDC 合成。背景位图是每像素 8 位。问题是 bitblt 将黑色(0x00000000)变成了几乎黑色(0x00010101)。如果我将相同的东西粘贴到 MSPaint 中,我会得到黑色。如果我从 MSPaint 复制黑色,我会得到几乎黑色。 (其他颜色也被破坏)。如果我将背景位图更改为 32bpp,我会得到正确的颜色,但目前这不是一个选项。

以下是一些演示该问题的代码:

/*
 *HWND hWnd; // main window handle
 *HDC hDC; // main window DC (set elsewhere)
 *HDC memDC; // background DC (set elsewhere)
 */
HBITMAP hClipBitmap=NULL;
OpenClipboard(hWnd);

hClipBitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
if (hClipBitmap!=NULL)
{
    // I now want to make a copy of the bitmap
    BITMAP bm;
    HDC hSrcDC,hDestDC;
    HANDLE OldObject1, OldObject2;
    DWORD sz = GetObject(hClipBitmap, sizeof(BITMAP), &bm);
    if(sz == sizeof(BITMAP))
    {
            // make a bitmap to allow positioning before actual pasting
        hPasteBitmap = ::CreateCompatibleBitmap(memDC, bm.bmWidth, bm.bmHeight); 
        if (hPasteBitmap==NULL)
            FATAL_ERROR;
        hSrcDC = CreateCompatibleDC(hDC);
        hDestDC = CreateCompatibleDC(hDC);
        OldObject1 = SelectObject(hSrcDC, hClipBitmap); // bpp is 32
        OldObject2 = SelectObject(hDestDC, hPasteBitmap); // bpp is 8
        BitBlt(hDestDC, 0, 0, bm.bmWidth, bm.bmHeight, hSrcDC, 0, 0, SRCCOPY);
        COLORREF color2 = ::GetPixel(hSrcDC, 1, 1); // color2 is 0x00000000
        COLORREF color3 = ::GetPixel(hDestDC, 1, 1);// color2 is 0x00010101
        COLORREF color4 = ::GetNearestColor(hSrcDC, color2); //  0x00000000
        COLORREF color5 = ::GetNearestColor(hDestDC, color2);//  0x00000000
        // hPasteBitmap now contains the clipboard data
    }
}
// other cleanup snipped for clarity

使用 GetPixel() 和 GetNearestColor(),似乎我应该得到我正在寻找的结果,但我没有。我想我错过了某种调色板操作?

更新

我真正遇到问题的部分,也许我误解了这些 API 的重点,是我可以查询像素颜色,然后询问上下文它将使用什么颜色,它会返回正确的颜色 (黑色),而不是 BitBlt 生成的几乎黑色。

其他程序似乎没有在剪贴板上放置调色板 - 可能是因为它们放置了不需要调色板的 32bpp 位图?他们甚至没有像我从MSDN's clipboard translation table查看可用的内容所知道的那样接近DIB

【问题讨论】:

  • 如果你从 32bpp 复制到 8bpp,你会失去一些颜色。没有其他办法了。除非源图像中的颜色数量有限。然后您可以在目标图像中使用索引调色板。
  • 源位图全黑。黑色在调色板中,但 BitBlt 将其映射到几乎黑色。 GetNearestColor() 返回黑色。
  • 背景图片调色板索引0处的颜色是什么?
  • 黑色。我尝试了 GetNearestPaletteIndex() 函数,它返回索引 0,即黑色。

标签: c++ winapi palette bitblt


【解决方案1】:

每像素 8 位的位图需要一个关联的调色板来指定颜色,这是独立的 - 您可以使用 CF_PALETTE 从剪贴板中获取它。拥有它后,您可以在位图被选择到的 DC 上使用 SelectPaletteRealizePalette

【讨论】:

  • HPALETTE hPal = (HPALETTE)GetClipboardData(CF_PALETTE); 返回 NULL。也许是因为剪贴板上的位图是 32 位的?查看msdn.microsoft.com/en-us/library/windows/desktop/… 以及可用的格式,似乎屏幕捕获和绘制都将位图放在剪贴板上,因为没有可用的调色板。
  • @MrPhilTX,很抱歉,我认为我读错了问题。我认为剪贴板图像是 8 位的。
  • 不用担心,感谢您的尝试!你帮我想到了其他一些可以尝试的事情。
  • @Mark Ransom:传给 CreateCompatibleBitmap 的 memDC 包含背景位图,声称是 8bpp,所以 pasteBitmap 也是 8bpp。
  • @ChrisBecke 这就是它需要调色板的原因。
猜你喜欢
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
  • 2015-08-08
  • 1970-01-01
相关资源
最近更新 更多