gpt4 book ai didi

c++ - 在 C++ 中使用 Gdiplus 创建透明位图

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:05:16 26 4
gpt4 key购买 nike

在 C++ 中,我想用 Gdiplus 创建一个简单的透明图像并将其保存为 png。我有以下代码:

    // These variables are class members and got initialized and are used elsewhere
BITMAPINFO bmi;
HDC hdc;
void* pvBits;

ZeroMemory(&bmi, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = some_width;
bmi.bmiHeader.biHeight = some_height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = ((((bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) + 31) & ~31) >> 3) * bmi.bmiHeader.biHeight;

HBITMAP hBM = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0);
FillMemory(pvBits, bmi.bmiHeader.biSizeImage, 255);

HGDIOBJ oldObj = SelectObject(hDC, hBM);
ReleaseDC(NULL, hDC);

GdiFlush();

GdiPlusBitmap* bitmap = new Gdiplus::Bitmap(&bmi, pvBits);

当我将图像保存为 png 时,我可以看到有一个 alpha channel ,但它设置为 0,所以没有透明(RGB 已全部设置)。我也尝试将 255 更改为 0,但这只会给我一个没有透明度的黑色图像。为什么 Fillmemory 调用没有填充 alpha channel ,还是我遗漏了什么?

最佳答案

FillMemory(pvBits, bmi.bmiHeader.biSizeImage, 255) 将用纯白色填充内存。如果您使用 GDI 函数覆盖图像,alpha 值将保持不变。即使文件支持,您也看不到任何透明度。

要创建 32 位图像,您只需要 Gdiplus::Bitmap(w, h, PixelFormat32bppARGB)。不需要 BITMAPINFOCreateDIBSection

如果将 GDI+ 与 GDI 函数混合使用,您可能希望在使用 GDI 函数写入后重置 alpha。例如:

void test()
{
int w = 100;
int h = 100;
int bitcount = 32;

int size = ((((w * bitcount) + 31) & ~31) >> 3) * h;

BITMAPINFO bmi = { 0 };
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = w;
bmi.bmiHeader.biHeight = -h;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = bitcount;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = size;

HDC hdc = GetDC(0);
BYTE* pvBits = NULL;
HBITMAP hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS,
(void**)&pvBits, NULL, 0x0);
FillMemory(pvBits, size, 0);

auto memdc = CreateCompatibleDC(hdc);
auto oldbmp = SelectObject(memdc, hbitmap);
SetBkColor(memdc, RGB(255, 0, 0));
TextOut(memdc, 0, 0, L"123", 3);

//GDI cleanup, don't delete hbitmap yet
SelectObject(memdc, oldbmp);
DeleteDC(memdc);
ReleaseDC(0, hdc);

//make the non-zero colors transparent:
for(int i = 0; i < size; i += 4)
{
int n = *(int*)(pvBits + i);
if (n != 0)
pvBits[i + 3] = 255;
}

CLSID clsid_png;
CLSIDFromString(L"{557cf406-1a04-11d3-9a73-0000f81ef32e}", &clsid_png);

Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(w, h, PixelFormat32bppARGB);
Gdiplus::BitmapData data;
bitmap->LockBits(&Gdiplus::Rect(0, 0, w, h),
Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &data);
memcpy(data.Scan0, pvBits, size);
bitmap->UnlockBits(&data);

//safe to delete hbitmap
DeleteObject(hbitmap);

bitmap->Save(L"test.png", &clsid_png);

delete bitmap;
}

关于c++ - 在 C++ 中使用 Gdiplus 创建透明位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51555487/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com