How can I save HICON to an .ico file

refer:http://*.com/questions/2289894/how-can-i-save-hicon-to-an-ico-file

answer1:

 #include "stdafx.h"
#include <windows.h>
#include <olectl.h>
#pragma comment(lib, "oleaut32.lib") HRESULT SaveIcon(HICON hIcon, const wchar_t* path) {
// Create the IPicture intrface
PICTDESC desc = { sizeof(PICTDESC) };
desc.picType = PICTYPE_ICON;
desc.icon.hicon = hIcon;
IPicture* pPicture = ;
HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)&pPicture);
if (FAILED(hr)) return hr; // Create a stream and save the image
IStream* pStream = ;
CreateStreamOnHGlobal(, TRUE, &pStream);
LONG cbSize = ;
hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize); // Write the stream content to the file
if (!FAILED(hr)) {
HGLOBAL hBuf = ;
GetHGlobalFromStream(pStream, &hBuf);
void* buffer = GlobalLock(hBuf);
HANDLE hFile = CreateFile(path, GENERIC_WRITE, , , CREATE_ALWAYS, , );
if (!hFile) hr = HRESULT_FROM_WIN32(GetLastError());
else {
DWORD written = ;
WriteFile(hFile, buffer, cbSize, &written, );
CloseHandle(hFile);
}
GlobalUnlock(buffer);
}
// Cleanup
pStream->Release();
pPicture->Release();
return hr; }
int _tmain(int argc, _TCHAR* argv[])
{
HICON hIcon = (HICON)LoadImage(, L"c:\\windows\\system32\\perfcentercpl.ico", IMAGE_ICON, , , LR_LOADFROMFILE);
if (!hIcon) return GetLastError();
HRESULT hr = SaveIcon(hIcon, L"c:\\temp\\test.ico");
return hr;
}

answer2:

 #include <afx.h>
#include <afxwin.h>
#include <atlbase.h> struct ICONDIRENTRY
{
UCHAR nWidth;
UCHAR nHeight;
UCHAR nNumColorsInPalette; // 0 if no palette
UCHAR nReserved; // should be 0
WORD nNumColorPlanes; // 0 or 1
WORD nBitsPerPixel;
ULONG nDataLength; // length in bytes
ULONG nOffset; // offset of BMP or PNG data from beginning of file
}; // Helper class to release GDI object handle when scope ends:
class CGdiHandle
{
public:
CGdiHandle(HGDIOBJ handle) : m_handle(handle) {};
~CGdiHandle(){DeleteObject(m_handle);};
private:
HGDIOBJ m_handle;
}; // Save icon referenced by handle 'hIcon' as file with name 'szPath'.
// The generated ICO file has the color depth specified in 'nColorBits'.
//
bool SaveIcon(HICON hIcon, int nColorBits, const TCHAR* szPath)
{
ASSERT(nColorBits == || nColorBits == || nColorBits == || nColorBits == ); if (offsetof(ICONDIRENTRY, nOffset) != )
{
return false;
} CDC dc;
dc.Attach(::GetDC(NULL)); // ensure that DC is released when function ends // Open file for writing:
CFile file;
if (!file.Open(szPath, CFile::modeWrite | CFile::modeCreate))
{
return false;
} // Write header:
UCHAR icoHeader[] = {, , , , , }; // ICO file with 1 image
file.Write(icoHeader, sizeof(icoHeader)); // Get information about icon:
ICONINFO iconInfo;
GetIconInfo(hIcon, &iconInfo);
CGdiHandle handle1(iconInfo.hbmColor), handle2(iconInfo.hbmMask); // free bitmaps when function ends
BITMAPINFO bmInfo = {};
bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biBitCount = ; // don't get the color table
if (!GetDIBits(dc, iconInfo.hbmColor, , , NULL, &bmInfo, DIB_RGB_COLORS))
{
return false;
} // Allocate size of bitmap info header plus space for color table:
int nBmInfoSize = sizeof(BITMAPINFOHEADER);
if (nColorBits < )
{
nBmInfoSize += sizeof(RGBQUAD) * (int)( << nColorBits);
} CAutoVectorPtr<UCHAR> bitmapInfo;
bitmapInfo.Allocate(nBmInfoSize);
BITMAPINFO* pBmInfo = (BITMAPINFO*)(UCHAR*)bitmapInfo;
memcpy(pBmInfo, &bmInfo, sizeof(BITMAPINFOHEADER)); // Get bitmap data:
ASSERT(bmInfo.bmiHeader.biSizeImage != );
CAutoVectorPtr<UCHAR> bits;
bits.Allocate(bmInfo.bmiHeader.biSizeImage);
pBmInfo->bmiHeader.biBitCount = nColorBits;
pBmInfo->bmiHeader.biCompression = BI_RGB;
if (!GetDIBits(dc, iconInfo.hbmColor, , bmInfo.bmiHeader.biHeight, (UCHAR*)bits, pBmInfo, DIB_RGB_COLORS))
{
return false;
} // Get mask data:
BITMAPINFO maskInfo = {};
maskInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
maskInfo.bmiHeader.biBitCount = ; // don't get the color table
if (!GetDIBits(dc, iconInfo.hbmMask, , , NULL, &maskInfo, DIB_RGB_COLORS))
{
return false;
}
ASSERT(maskInfo.bmiHeader.biBitCount == );
CAutoVectorPtr<UCHAR> maskBits;
maskBits.Allocate(maskInfo.bmiHeader.biSizeImage);
CAutoVectorPtr<UCHAR> maskInfoBytes;
maskInfoBytes.Allocate(sizeof(BITMAPINFO) + * sizeof(RGBQUAD));
BITMAPINFO* pMaskInfo = (BITMAPINFO*)(UCHAR*)maskInfoBytes;
memcpy(pMaskInfo, &maskInfo, sizeof(maskInfo));
if (!GetDIBits(dc, iconInfo.hbmMask, , maskInfo.bmiHeader.biHeight, (UCHAR*)maskBits, pMaskInfo, DIB_RGB_COLORS))
{
return false;
} // Write directory entry:
ICONDIRENTRY dir;
dir.nWidth = (UCHAR) pBmInfo->bmiHeader.biWidth;
dir.nHeight = (UCHAR) pBmInfo->bmiHeader.biHeight;
dir.nNumColorsInPalette = (nColorBits == ? : );
dir.nReserved = ;
dir.nNumColorPlanes = ;
dir.nBitsPerPixel = pBmInfo->bmiHeader.biBitCount;
dir.nDataLength = pBmInfo->bmiHeader.biSizeImage + pMaskInfo->bmiHeader.biSizeImage + nBmInfoSize;
dir.nOffset = sizeof(dir) + sizeof(icoHeader);
file.Write(&dir, sizeof(dir)); // Write DIB header (including color table):
int nBitsSize = pBmInfo->bmiHeader.biSizeImage;
pBmInfo->bmiHeader.biHeight *= ; // because the header is for both image and mask
pBmInfo->bmiHeader.biCompression = ;
pBmInfo->bmiHeader.biSizeImage += pMaskInfo->bmiHeader.biSizeImage; // because the header is for both image and mask
file.Write(&pBmInfo->bmiHeader, nBmInfoSize); // Write image data:
file.Write((UCHAR*)bits, nBitsSize); // Write mask data:
file.Write((UCHAR*)maskBits, pMaskInfo->bmiHeader.biSizeImage); file.Close(); return true;
} // Test program for SaveIcon() function.
//
// Usage: first argument is input ICO file (must be 32x32 pixels); second argument is output ICO file
//
int _tmain(int argc, _TCHAR* argv[])
{
ASSERT(argc == ); // Load a 32x32 icon:
HICON hIcon = (HICON)LoadImage(, argv[], IMAGE_ICON, , , LR_LOADFROMFILE | LR_CREATEDIBSECTION);
ASSERT(hIcon != NULL); // Save with 24-bits colors:
if (!SaveIcon(hIcon, , argv[]))
{
_ftprintf(stderr, _T("Error: saving icon to %s failed"), argv[]);
return EXIT_FAILURE;
} return EXIT_SUCCESS;
}

answer3:

 #include <windows.h>
#include <stdio.h>
#include <tchar.h> //
// ICONS (.ICO type 1) are structured like this:
//
// ICONHEADER (just 1)
// ICONDIR [1...n] (an array, 1 for each image)
// [BITMAPINFOHEADER+COLOR_BITS+MASK_BITS] [1...n] (1 after the other, for each image)
//
// CURSORS (.ICO type 2) are identical in structure, but use
// two monochrome bitmaps (real XOR and AND masks, this time).
// typedef struct
{
WORD idReserved; // must be 0
WORD idType; // 1 = ICON, 2 = CURSOR
WORD idCount; // number of images (and ICONDIRs) // ICONDIR [1...n]
// ICONIMAGE [1...n] } ICONHEADER; //
// An array of ICONDIRs immediately follow the ICONHEADER
//
typedef struct
{
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes; // for cursors, this field = wXHotSpot
WORD wBitCount; // for cursors, this field = wYHotSpot
DWORD dwBytesInRes;
DWORD dwImageOffset; // file-offset to the start of ICONIMAGE } ICONDIR; //
// After the ICONDIRs follow the ICONIMAGE structures -
// consisting of a BITMAPINFOHEADER, (optional) RGBQUAD array, then
// the color and mask bitmap bits (all packed together
//
typedef struct
{
BITMAPINFOHEADER biHeader; // header for color bitmap (no mask header)
//RGBQUAD rgbColors[1...n];
//BYTE bXOR[1]; // DIB bits for color bitmap
//BYTE bAND[1]; // DIB bits for mask bitmap } ICONIMAGE; //
// Write the ICO header to disk
//
static UINT WriteIconHeader(HANDLE hFile, int nImages)
{
ICONHEADER iconheader;
DWORD nWritten; // Setup the icon header
iconheader.idReserved = ; // Must be 0
iconheader.idType = ; // Type 1 = ICON (type 2 = CURSOR)
iconheader.idCount = nImages; // number of ICONDIRs // Write the header to disk
WriteFile( hFile, &iconheader, sizeof(iconheader), &nWritten, ); // following ICONHEADER is a series of ICONDIR structures (idCount of them, in fact)
return nWritten;
} //
// Return the number of BYTES the bitmap will take ON DISK
//
static UINT NumBitmapBytes(BITMAP *pBitmap)
{
int nWidthBytes = pBitmap->bmWidthBytes; // bitmap scanlines MUST be a multiple of 4 bytes when stored
// inside a bitmap resource, so round up if necessary
if(nWidthBytes & )
nWidthBytes = (nWidthBytes + ) & ~; return nWidthBytes * pBitmap->bmHeight;
} //
// Return number of bytes written
//
static UINT WriteIconImageHeader(HANDLE hFile, BITMAP *pbmpColor, BITMAP *pbmpMask)
{
BITMAPINFOHEADER biHeader;
DWORD nWritten;
UINT nImageBytes; // calculate how much space the COLOR and MASK bitmaps take
nImageBytes = NumBitmapBytes(pbmpColor) + NumBitmapBytes(pbmpMask); // write the ICONIMAGE to disk (first the BITMAPINFOHEADER)
ZeroMemory(&biHeader, sizeof(biHeader)); // Fill in only those fields that are necessary
biHeader.biSize = sizeof(biHeader);
biHeader.biWidth = pbmpColor->bmWidth;
biHeader.biHeight = pbmpColor->bmHeight * ; // height of color+mono
biHeader.biPlanes = pbmpColor->bmPlanes;
biHeader.biBitCount = pbmpColor->bmBitsPixel;
biHeader.biSizeImage = nImageBytes; // write the BITMAPINFOHEADER
WriteFile(hFile, &biHeader, sizeof(biHeader), &nWritten, ); // write the RGBQUAD color table (for 16 and 256 colour icons)
if(pbmpColor->bmBitsPixel == || pbmpColor->bmBitsPixel == )
{ } return nWritten;
} //
// Wrapper around GetIconInfo and GetObject(BITMAP)
//
static BOOL GetIconBitmapInfo(HICON hIcon, ICONINFO *pIconInfo, BITMAP *pbmpColor, BITMAP *pbmpMask)
{
if(!GetIconInfo(hIcon, pIconInfo))
return FALSE; if(!GetObject(pIconInfo->hbmColor, sizeof(BITMAP), pbmpColor))
return FALSE; if(!GetObject(pIconInfo->hbmMask, sizeof(BITMAP), pbmpMask))
return FALSE; return TRUE;
} //
// Write one icon directory entry - specify the index of the image
//
static UINT WriteIconDirectoryEntry(HANDLE hFile, int nIdx, HICON hIcon, UINT nImageOffset)
{
ICONINFO iconInfo;
ICONDIR iconDir; BITMAP bmpColor;
BITMAP bmpMask; DWORD nWritten;
UINT nColorCount;
UINT nImageBytes; GetIconBitmapInfo(hIcon, &iconInfo, &bmpColor, &bmpMask); nImageBytes = NumBitmapBytes(&bmpColor) + NumBitmapBytes(&bmpMask); if(bmpColor.bmBitsPixel >= )
nColorCount = ;
else
nColorCount = << (bmpColor.bmBitsPixel * bmpColor.bmPlanes); // Create the ICONDIR structure
iconDir.bWidth = (BYTE)bmpColor.bmWidth;
iconDir.bHeight = (BYTE)bmpColor.bmHeight;
iconDir.bColorCount = nColorCount;
iconDir.bReserved = ;
iconDir.wPlanes = bmpColor.bmPlanes;
iconDir.wBitCount = bmpColor.bmBitsPixel;
iconDir.dwBytesInRes = sizeof(BITMAPINFOHEADER) + nImageBytes;
iconDir.dwImageOffset = nImageOffset; // Write to disk
WriteFile(hFile, &iconDir, sizeof(iconDir), &nWritten, ); // Free resources
DeleteObject(iconInfo.hbmColor);
DeleteObject(iconInfo.hbmMask); return nWritten;
} static UINT WriteIconData(HANDLE hFile, HBITMAP hBitmap)
{
BITMAP bmp;
int i;
BYTE * pIconData; UINT nBitmapBytes;
DWORD nWritten; GetObject(hBitmap, sizeof(BITMAP), &bmp); nBitmapBytes = NumBitmapBytes(&bmp); pIconData = (BYTE *)malloc(nBitmapBytes); GetBitmapBits(hBitmap, nBitmapBytes, pIconData); // bitmaps are stored inverted (vertically) when on disk..
// so write out each line in turn, starting at the bottom + working
// towards the top of the bitmap. Also, the bitmaps are stored in packed
// in memory - scanlines are NOT 32bit aligned, just 1-after-the-other
for(i = bmp.bmHeight - ; i >= ; i--)
{
// Write the bitmap scanline
WriteFile(
hFile,
pIconData + (i * bmp.bmWidthBytes), // calculate offset to the line
bmp.bmWidthBytes, // 1 line of BYTES
&nWritten,
); // extend to a 32bit boundary (in the file) if necessary
if(bmp.bmWidthBytes & )
{
DWORD padding = ;
WriteFile(hFile, &padding, - bmp.bmWidthBytes, &nWritten, );
}
} free(pIconData); return nBitmapBytes;
} //
// Create a .ICO file, using the specified array of HICON images
//
BOOL SaveIcon3(TCHAR *szIconFile, HICON hIcon[], int nNumIcons)
{
HANDLE hFile;
int i;
int * pImageOffset; if(hIcon == || nNumIcons < )
return FALSE; // Save icon to disk:
hFile = CreateFile(szIconFile, GENERIC_WRITE, , , CREATE_ALWAYS, , ); if(hFile == INVALID_HANDLE_VALUE)
return FALSE; //
// Write the iconheader first of all
//
WriteIconHeader(hFile, nNumIcons); //
// Leave space for the IconDir entries
//
SetFilePointer(hFile, sizeof(ICONDIR) * nNumIcons, , FILE_CURRENT); pImageOffset = (int *)malloc(nNumIcons * sizeof(int)); //
// Now write the actual icon images!
//
for(i = ; i < nNumIcons; i++)
{
ICONINFO iconInfo;
BITMAP bmpColor, bmpMask; GetIconBitmapInfo(hIcon[i], &iconInfo, &bmpColor, &bmpMask); // record the file-offset of the icon image for when we write the icon directories
pImageOffset[i] = SetFilePointer(hFile, , , FILE_CURRENT); // bitmapinfoheader + colortable
WriteIconImageHeader(hFile, &bmpColor, &bmpMask); // color and mask bitmaps
WriteIconData(hFile, iconInfo.hbmColor);
WriteIconData(hFile, iconInfo.hbmMask); DeleteObject(iconInfo.hbmColor);
DeleteObject(iconInfo.hbmMask);
} //
// Lastly, skip back and write the icon directories.
//
SetFilePointer(hFile, sizeof(ICONHEADER), , FILE_BEGIN); for(i = ; i < nNumIcons; i++)
{
WriteIconDirectoryEntry(hFile, i, hIcon[i], pImageOffset[i]);
} free(pImageOffset); // finished!
CloseHandle(hFile); return TRUE;
} int saveIcon(TCHAR* filename, TCHAR* iconFile) {
HICON hIconLarge;
HICON hIconSmall;
BOOL ret; if ( ExtractIconEx(filename, , &hIconLarge, &hIconSmall, ) == ) {
return ;
} ret = SaveIcon3(iconFile, &hIconSmall, );
if ( ret ) {
return ;
}
return -;
} int _tmain(int argc, TCHAR* argv[]) {
if ( argc < ) {
printf("Usage: <exe/dll file> <output ico file>");
return EXIT_FAILURE;
}
_tprintf(_T("src = %s\n"), argv[]);
_tprintf(_T("dest = %s\n"), argv[]);
saveIcon(argv[], argv[]); return ;
}
上一篇:vlc


下一篇:用 Python + Appium 的方式自动化清理微信僵尸好友