首页 > 解决方案 > 有没有办法从具有透明度 GDI+ 的位图中保存 PNG

问题描述

我试图从和exe中获取图标并将其保存为具有透明度的png。我已经能够使用 gdi+ 从中获取位图并使用正确的 alpha 通道保存 .bmp(在 Photoshop 中检查)。但现在的问题是,当我想将其保存为 .png 时,透明度不会传输到文件(透明区域为黑色)这是我的代码:

using namespace Gdiplus;

SHFILEINFO sfi;
IImageList* piml;
HICON hicon;

// Getting the largest icon from FILEPATH(*.exe)
SHGetFileInfo(FILEPATH, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX);
SHGetImageList(SHIL_JUMBO, IID_IImageList, (void**)&piml);
piml->GetIcon(sfi.iIcon, 0x00000001, &hicon);

// Getting the HBITMAP from it
ICONINFO iconinfo;
GetIconInfo(hicon, &iconinfo);

//GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

//Creating nessecery palettes for gdi, so i can use Bitmap::FromHBITMAP
PALETTEENTRY pat = { 255,255,255,0 };
LOGPALETTE logpalt = { 0, 1, pat };
HPALETTE hand = CreatePalette(&logpalt);

Bitmap* h = Bitmap::FromHBITMAP(iconinfo.hbmColor, hand);

//Getting image encoders for saving
UINT num, sz;
GetImageEncodersSize(&num, &sz);
ImageCodecInfo* inf = new ImageCodecInfo[sz];
GetImageEncoders(num, sz, inf);
//4 -> png ; 0 -> bitmap
CLSID encoderClsid = inf[4].Clsid;
h->Save(L"PATH_TO_SAVE", &encoderClsid, NULL);
GdiplusShutdown(gdiplusToken);

标签: c++gdi+

解决方案


因此,显然 alpha 通道包含所需的所有数据,但由于某种原因,它在保存时忽略了 alpha 通道,而解决方法是从以前的位图创建新的位图。

现在生成的 PNG 具有透明度。

这是固定代码。

using namespace Gdiplus;

SHFILEINFO sfi;
IImageList* piml;
HICON hicon;

// Getting the largest icon from FILEPATH(*.exe)
SHGetFileInfo(FILEPATH, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX);
SHGetImageList(SHIL_JUMBO, IID_IImageList, (void**)&piml);
piml->GetIcon(sfi.iIcon, 0x00000001, &hicon);

// Getting the HBITMAP from it
ICONINFO iconinfo;
GetIconInfo(hicon, &iconinfo);

//GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

//Creating nessecery palettes for gdi, so i can use Bitmap::FromHBITMAP
PALETTEENTRY pat = { 255,255,255,0 };
LOGPALETTE logpalt = { 0, 1, pat };
HPALETTE hand = CreatePalette(&logpalt);

Bitmap* h = Bitmap::FromHBITMAP(iconinfo.hbmColor, hand);

//Getting data from the bitmap and creating new bitmap from it
Rect rect(0, 0, h->GetWidth(), h->GetHeight());
BitmapData bd;
h->LockBits(&rect, ImageLockModeRead, h->GetPixelFormat(), &bd);
Bitmap* newBitmapWithAplha = new Bitmap(bd.Width, bd.Height, bd.Stride, PixelFormat32bppARGB, (BYTE*)bd.Scan0);
h->UnlockBits(&bd);

//Getting image encoders for saving
UINT num, sz;
GetImageEncodersSize(&num, &sz);
ImageCodecInfo* inf = new ImageCodecInfo[sz];
GetImageEncoders(num, sz, inf);
//4 -> png ; 0 -> bitmap
CLSID encoderClsid = inf[4].Clsid;
//Saving the new Bitmap
newBitmapWithAplha->Save(L"PATH_TO_SAVE", &encoderClsid, NULL);
GdiplusShutdown(gdiplusToken);

推荐阅读