c++ - 有没有办法从具有透明度 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);
解决方案
因此,显然 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);
推荐阅读
- amazon-web-services - AWS“DX”和“FsX”的缩写含义
- c# - Unity 在线多人游戏错误:连接已被对等方关闭,尝试协商集合点超时
- javascript - Mapbox 彩色地图,多边形除外
- python - 如何在 Django 3.2 中进行多对一字段引用?
- php - 使用快速导出方式时默认选择的编码是什么?
- python - Python - [Subprocess Popen Communicate] 挂起执行
- c++ - 更正我的二进制搜索索引和超出范围的数组
- typescript - 多对多关系的 TypeORM 重复键值
- python - 气流中的日期格式
- python - Pandas - 如何基于另一行应用计算(在计算过程中可能会改变......)