繁体   English   中英

C ++ GDI + SelectPalette

[英]C++ GDI+ SelectPalette

我正在玩GDI +。 尝试使用

pDC->SelectPalette(CPalette::FromHandle(hLogPal), FALSE);
pDC->RealizePalette();

代替

memcpy(newBitmapInfo + sizeof(BITMAPINFO), rgbquad, palettesize);

但是似乎可以与memcpy(newBitmapInfo + sizeof(BITMAPINFO), rgbquad, palettesize); 但是使用SelectPalette只能黑屏。

我认为可以从bitmapinfo或托盘使用有关颜色的信息。

所有代码:

void ConvertTo8BitImage(BYTE** pBitmapInfo, BYTE** imageData)
{
    Gdiplus::GdiplusStartupInput tmp;
    ULONG_PTR token;
    Gdiplus::GdiplusStartup(&token, &tmp, NULL);

    Gdiplus::Bitmap *source = Gdiplus::Bitmap::FromFile(L"D:/TestImage.bmp");
    Gdiplus::Bitmap *destination = source->Clone(0, 0, source->GetWidth(), source->GetHeight(),
        PixelFormat8bppIndexed);

    int width = source->GetWidth();
    int height = source->GetHeight();

    HBITMAP hBitmap;
    Gdiplus::Color color;
    destination->GetHBITMAP(color, &hBitmap);
    int palettesize = 256 * sizeof(RGBQUAD);

    CLSID clsid_bmp;
    CLSIDFromString(L"{557cf400-1a04-11d3-9a73-0000f81ef32e}", &clsid_bmp);
    *pBitmapInfo = new BYTE[(sizeof(BITMAPINFO) + palettesize)];

    BITMAPINFO* ptr = (BITMAPINFO*)*pBitmapInfo;
    ptr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    ptr->bmiHeader.biWidth = width;
    ptr->bmiHeader.biHeight = height;
    ptr->bmiHeader.biPlanes = 1;

    ptr->bmiHeader.biBitCount = 8;
    ptr->bmiHeader.biCompression = BI_RGB;
    ptr->bmiColors[0].rgbRed = 0;
    DWORD size = ((width * 8 + 31) / 32) * 4 * height;

    *imageData = new BYTE[size];

    HDC hdc = GetDC(0);
    GetDIBits(hdc, hBitmap, 0, height, *imageData, (BITMAPINFO*)*pBitmapInfo, DIB_PAL_COLORS);
    ReleaseDC(0, hdc);

    Gdiplus::GdiplusShutdown(token);
}

void CMFCApplicationColorsView::OnDraw(CDC* pDC)
{
    CMFCApplicationColorsDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    BYTE *bitmapInfo = NULL;
    BYTE *imageData = NULL;

    ConvertTo8BitImage(&bitmapInfo, &imageData);

    int palettesize = 256 * sizeof(RGBQUAD);
    BYTE *newBitmapInfo = new BYTE[(sizeof(BITMAPINFO) + palettesize)];
    ZeroMemory(newBitmapInfo, (sizeof(BITMAPINFO) + palettesize));

    BITMAPINFO *ptr = (BITMAPINFO*)newBitmapInfo;
    ptr->bmiHeader.biBitCount = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biBitCount;
    ptr->bmiHeader.biClrImportant = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biClrImportant;
    ptr->bmiHeader.biClrUsed = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biClrUsed;
    ptr->bmiHeader.biCompression = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biCompression;
    ptr->bmiHeader.biHeight = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biHeight;
    ptr->bmiHeader.biPlanes = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biPlanes;
    ptr->bmiHeader.biSize = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biSize;
    ptr->bmiHeader.biSizeImage = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biSizeImage;
    ptr->bmiHeader.biWidth = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biWidth;
    ptr->bmiHeader.biXPelsPerMeter = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biXPelsPerMeter;
    ptr->bmiHeader.biYPelsPerMeter = ((BITMAPINFO*)bitmapInfo)->bmiHeader.biYPelsPerMeter;
    ptr->bmiColors[0] = ((BITMAPINFO*)bitmapInfo)->bmiColors[0];

    RGBQUAD rgbquad[256];
    memcpy(rgbquad, bitmapInfo + sizeof(BITMAPINFO), palettesize);
    //memcpy(newBitmapInfo + sizeof(BITMAPINFO), rgbquad, palettesize);

    NPLOGPALETTE pPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED,
        (sizeof(LOGPALETTE) +
        (sizeof(PALETTEENTRY) * (palettesize))));

    pPal->palVersion = 0x300;
    pPal->palNumEntries = 256;
    for (int i = 0; i < 256; i++)
    {
        pPal->palPalEntry[i].peRed = rgbquad[i].rgbRed;
        pPal->palPalEntry[i].peGreen = rgbquad[i].rgbGreen;
        pPal->palPalEntry[i].peBlue = rgbquad[i].rgbBlue;
        pPal->palPalEntry[i].peFlags = 0;
    }

    HPALETTE hLogPal = CreatePalette((LPLOGPALETTE)pPal);

    pDC->SelectPalette(CPalette::FromHandle(hLogPal), FALSE);
    pDC->RealizePalette();

    StretchDIBits(pDC->GetSafeHdc(), 0, 0, 1920, 1080, 0, 0, 1920, 1080,
        imageData, ptr, DIB_PAL_COLORS, SRCCOPY);


    delete[] bitmapInfo;
    delete[] imageData;
}
 HBITMAP hBitmap; Gdiplus::Color color; destination->GetHBITMAP(color, &hBitmap); 

您确实已转换为8位位图,但是GetHBITMAP将返回与您的视频卡兼容的位图句柄(可能是32位)。 GDI +已经处理了调色板,并返回了一个位图句柄,该句柄被转回了32位。 HBITMAP句柄可以直接绘制,例如使用CreateCompatibleDCBitBlt 因此,无需获取调色板并将其传递给GDI,也无需进行8位转换。

如果出于某种原因这是必要的,则可以从32位位图中获取位和调色板,将其放入8位位图中,并使用StretchDIBits绘制

您的代码中的主要问题是它应该对GetDIBits/StretchDIBits使用DIB_RGB_COLORS标志,因为设备上下文很可能是32位的。 也不需要SelectPalette/RealizePalette (除非它是30年前的8位显示器)

如下面的示例所示,使用LockBits直接从GDI +获取位,并使用GetPalette直接获取调色板更有意义。

另外,在退出之前必须删除sourcedestination

void draw(HDC hdc)
{
    Gdiplus::Bitmap *source = Gdiplus::Bitmap::FromFile(L"D:/TestImage.bmp");
    if(!source)
        return;
    int width = source->GetWidth();
    int height = source->GetHeight();

    Gdiplus::Bitmap *destination = source->Clone(0, 0, width, height,
        PixelFormat8bppIndexed);

    //get bitmap bits from GDI+
    Gdiplus::BitmapData data;
    Gdiplus::Rect rect(0, 0, width, height);
    destination->LockBits(&rect, Gdiplus::ImageLockModeRead,
        destination->GetPixelFormat(), &data);
    int bufsize = data.Stride * data.Height;
    BYTE *buf = new BYTE[bufsize];
    memcpy(buf, data.Scan0, bufsize);
    destination->UnlockBits(&data);

    //setup BITMAPINFO
    int bmpinfo_size = sizeof(BITMAPINFO) + 256 * 4;
    BITMAPINFO* bmpinfo = (BITMAPINFO*)new BYTE[bmpinfo_size];
    memset(bmpinfo, 0, bmpinfo_size);
    bmpinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpinfo->bmiHeader.biWidth = width;
    bmpinfo->bmiHeader.biHeight = -height;
    bmpinfo->bmiHeader.biPlanes = 1;
    bmpinfo->bmiHeader.biBitCount = 8;
    bmpinfo->bmiHeader.biCompression = BI_RGB;
    bmpinfo->bmiHeader.biSizeImage = bufsize;

    //get palette from GDI+
    int palsize = destination->GetPaletteSize();
    Gdiplus::ColorPalette *palette = (Gdiplus::ColorPalette*)new BYTE[palsize];
    destination->GetPalette(palette, palsize);

    //set palette for BITMAPINFO
    memset(&bmpinfo->bmiColors[0], 0, 256 * 4);
    for(int i = 0; i < palette->Count; i++)
    {
        auto clr = Gdiplus::Color(palette->Entries[i]);
        bmpinfo->bmiColors[i].rgbRed = clr.GetR();
        bmpinfo->bmiColors[i].rgbGreen = clr.GetG();
        bmpinfo->bmiColors[i].rgbBlue = clr.GetB();
        bmpinfo->bmiColors[i].rgbReserved = 0;      
    }

    StretchDIBits(hdc, 0, 0, width, height, 0, 0, width, height,
        buf, bmpinfo, DIB_RGB_COLORS, SRCCOPY);

    delete[] buf;
    delete[] bmpinfo;
    delete[] palette;
    delete destination;
    delete source;
}

void CMFCApplicationColorsView::OnDraw(CDC* pDC)
{
    CMFCApplicationColorsDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    Gdiplus::GdiplusStartupInput tmp;
    ULONG_PTR token;
    Gdiplus::GdiplusStartup(&token, &tmp, NULL);

    draw(pDC->GetSafeHdc());

    Gdiplus::GdiplusShutdown(token);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM