0
votes

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

1
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
Source bitmap is all black. Black is in the palette, but BitBlt maps it to Almost Black. GetNearestColor() returns Black.MrPhilTX
What is the color at index 0 of the palette of the background image?Mark Ransom
Black. I tried the GetNearestPaletteIndex() function, and it returned index 0, which was Black.MrPhilTX

1 Answers

3
votes

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.