gpt4 book ai didi

c++ - 将 HICON 另存为 png

转载 作者:太空狗 更新时间:2023-10-29 23:48:16 26 4
gpt4 key购买 nike

我正在使用 IShellItemImageFactory 来提取文件的图标。我能够成功提取它并在对话框中使用SendDlgItemMessage(hDlg,IDC_STATIC2, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hicon);

查看输出:click here

问题是当我使用 GDI+ 将其保存为文件(PNG 格式)时,渐变不保留校正。在下面找到我正在使用的代码。

GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);Bitmap *h = new Bitmap(256, 256, PixelFormat32bppARGB);Graphics* g = Graphics::FromImage(copy);HDC copyHdc = g->GetHDC();DrawIconEx(copyHdc, 0, 0, hicon, 256, 256, 0, NULL, DI_NORMAL);g->ReleaseHDC(copyHdc);;CLSID   encoderClsid;GetEncoderClsid(L"image/png", &encoderClsid);h->Save(L"D:\\mynew.png", &encoderClsid, NULL);GdiplusShutdown(gdiplusToken);

提取文本文件后得到的输出:click here

谁能帮我解决这个问题?

问候,马诺杰

最佳答案

这个主题比较老,但我遇到了同样的问题,并且花了很多时间来寻找一种可以保留 PNG 文件透明度的解决方案。

既然问题可以用Java轻松解决...

    sun.awt.shell.ShellFolder sf = sun.awt.shell.ShellFolder.getShellFolder(file);
ImageIcon icon = new ImageIcon(sf.getIcon(true));
FileOutputStream bos = new FileOutputStream("d:\\icons\\icon.png");
ImageIO.write((BufferedImage)icon.getImage(), "PNG", bos);

... 我看了一下JDK源代码。在函数“Java_sun_awt_shell_Win32ShellFolder2_getIconBits”的文件“\jdk\src\windows\native\sun\windows\ShellFolder2.cpp”中,我找到了我需要的有值(value)的提示。

此函数从 HICON 中检索颜色位图并调用 GetDIBits 获取图像数据。绘制图标不是必需的 - 无论如何透明度都会丢失。

非常感谢 JDK 开发人员。

这是我最终得到的代码:

static CLSID g_pngClsid = GUID_NULL;

// http://msdn.microsoft.com/en-us/library/windows/desktop/ms533843(v=vs.85).aspx
extern int GetEncoderClsid(const WCHAR* format, CLSID* pClsid);

static HICON getShellIconByIndex(int shilsize, int iImage)
{
IImageListPtr spiml;
SHGetImageList(shilsize, IID_PPV_ARGS(&spiml));

HICON hico;
spiml->GetIcon(iImage, ILD_TRANSPARENT, &hico);
return hico;
}

static HICON getShellIcon(int shilsize, const std::wstring& fname) {
UINT flags = SHGFI_SYSICONINDEX;
SHFILEINFO fi = {0};
HICON hIcon = NULL;

if (SHGetFileInfo(fname.c_str(), 0, &fi, sizeof(fi), flags) != 0) {
hIcon = getShellIconByIndex(shilsize, fi.iIcon);
}

return hIcon;
}

struct BITMAP_AND_BYTES {
Gdiplus::Bitmap* bmp;
int32_t* bytes;
};

static BITMAP_AND_BYTES createAlphaChannelBitmapFromIcon(HICON hIcon) {

// Get the icon info
ICONINFO iconInfo = {0};
GetIconInfo(hIcon, &iconInfo);

// Get the screen DC
HDC dc = GetDC(NULL);

// Get icon size info
BITMAP bm = {0};
GetObject( iconInfo.hbmColor, sizeof( BITMAP ), &bm );

// Set up BITMAPINFO
BITMAPINFO bmi = {0};
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = bm.bmWidth;
bmi.bmiHeader.biHeight = -bm.bmHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;

// Extract the color bitmap
int nBits = bm.bmWidth * bm.bmHeight;
int32_t* colorBits = new int32_t[nBits];
GetDIBits(dc, iconInfo.hbmColor, 0, bm.bmHeight, colorBits, &bmi, DIB_RGB_COLORS);

// Check whether the color bitmap has an alpha channel.
// (On my Windows 7, all file icons I tried have an alpha channel.)
BOOL hasAlpha = FALSE;
for (int i = 0; i < nBits; i++) {
if ((colorBits[i] & 0xff000000) != 0) {
hasAlpha = TRUE;
break;
}
}

// If no alpha values available, apply the mask bitmap
if (!hasAlpha) {
// Extract the mask bitmap
int32_t* maskBits = new int32_t[nBits];
GetDIBits(dc, iconInfo.hbmMask, 0, bm.bmHeight, maskBits, &bmi, DIB_RGB_COLORS);
// Copy the mask alphas into the color bits
for (int i = 0; i < nBits; i++) {
if (maskBits[i] == 0) {
colorBits[i] |= 0xff000000;
}
}
delete[] maskBits;
}

// Release DC and GDI bitmaps
ReleaseDC(NULL, dc);
::DeleteObject(iconInfo.hbmColor);
::DeleteObject(iconInfo.hbmMask);

// Create GDI+ Bitmap
Gdiplus::Bitmap* bmp = new Gdiplus::Bitmap(bm.bmWidth, bm.bmHeight, bm.bmWidth*4, PixelFormat32bppARGB, (BYTE*)colorBits);
BITMAP_AND_BYTES ret = {bmp, colorBits};

return ret;
}

static void saveFileIconAsPng(int shilsize, const std::wstring& fname, const std::wstring& pngFile) {
HICON hIcon = getShellIcon(shilsize, fname);
BITMAP_AND_BYTES bbs = createAlphaChannelBitmapFromIcon(hIcon);

IStream* fstrm = NULL;
SHCreateStreamOnFile(pngFile.c_str(), STGM_WRITE|STGM_CREATE, &fstrm);
bbs.bmp->Save(fstrm, &g_pngClsid, NULL);
fstrm->Release();

delete bbs.bmp;
delete[] bbs.bytes;
DestroyIcon(hIcon);
}

调用示例:

GdiplusStartup(...);
GetEncoderClsid(L"image/png", &g_pngClsid);

wstring fname = L"d:\\index.html";
wstring pngFile = L"d:\\icons\\index.html.png";
saveFileIconAsPng(SHIL_JUMBO, fname, pngFile);

GdiplusShutdown(...);

关于c++ - 将 HICON 另存为 png,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1818990/

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