0

I am pasting an image from the clipboard into my program. The bitmap gets put on a background memDC bitmap, which is then composited with another memDC before being drawn to the screen. The background bitmap is 8 bits per pixel. The problem is that the bitblt turns Black(0x00000000) into Almost-Black (0x00010101). If I paste the same thing into MSPaint, I get Black. If I copy Black from MSPaint, I get Almost Black. (Other colors are also mangled). If I change the background bitmap to 32bpp, I get the correct colors, but that isn't currently an option.

The following is some code that demonstrates the issue:

/*
 *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

Using GetPixel() and GetNearestColor(), it seems like I should get the results I'm looking for, but I don't. I guess I'm missing some sort of palette operation?

Update

The part I really have trouble with, and maybe I misunderstand the point of these APIs, is that I can query the pixel color, and then ask the context what color it will use for that, and it returns the correct color (Black), instead of the Almost Black that the BitBlt generates.

Other programs do not seem to put a palette on the clipboard - perhaps because they are putting 32bpp bitmaps that don't need the palette? They aren't even doing DIBs as near as I can tell from looking at what is available based on MSDN's clipboard translation table

MrPhilTX
  • 113
  • 2
  • 9
  • If you are copying from 32bpp to 8bpp, you are going to lose some colors. There is no way around it. Unless there are a limited number of colors in the source image. Then you could use an indexed palette in the destination image. – Steve Wellens Oct 16 '12 at 15:47
  • Source bitmap is all black. Black is in the palette, but BitBlt maps it to Almost Black. GetNearestColor() returns Black. – MrPhilTX Oct 16 '12 at 18:00
  • What is the color at index 0 of the palette of the background image? – Mark Ransom Oct 17 '12 at 15:18
  • Black. I tried the GetNearestPaletteIndex() function, and it returned index 0, which was Black. – MrPhilTX Oct 17 '12 at 16:07

1 Answers1

3

An 8 bit per pixel bitmap needs an associated palette to specify the colors, which is separate - you get it from the clipboard using CF_PALETTE. Once you have it you use SelectPalette and RealizePalette on the DC that the bitmap is selected into.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • `HPALETTE hPal = (HPALETTE)GetClipboardData(CF_PALETTE);` returns NULL. Perhaps because the bitmap on the clipboard is 32 bit? Looking at http://msdn.microsoft.com/en-us/library/windows/desktop/ms649013(v=vs.85).aspx#_win32_Synthesized_Clipboard_Formats and what formats are available, it appears the screen capture and paint both put bitmaps on the clipboard, as there is not a palette available. – MrPhilTX Oct 17 '12 at 14:24
  • @MrPhilTX, I'm sorry I think I read the question wrong. I thought the clipboard image was the 8 bit one. – Mark Ransom Oct 17 '12 at 14:58
  • No worries, thanks for trying! You helped me think of a few other things to try. – MrPhilTX Oct 17 '12 at 15:30
  • @Mark Ransom: The memDC passed into CreateCompatibleBitmap contains the background bitmap which is claimed to be 8bpp, so pasteBitmap will be 8bpp too. – Chris Becke May 14 '18 at 05:54
  • @ChrisBecke which is why it needs a palette. – Mark Ransom May 14 '18 at 13:19