refer:http://*.com/questions/2289894/how-can-i-save-hicon-to-an-ico-file
answer1:
1 #include "stdafx.h" 2 #include <windows.h> 3 #include <olectl.h> 4 #pragma comment(lib, "oleaut32.lib") 5 6 HRESULT SaveIcon(HICON hIcon, const wchar_t* path) { 7 // Create the IPicture intrface 8 PICTDESC desc = { sizeof(PICTDESC) }; 9 desc.picType = PICTYPE_ICON; 10 desc.icon.hicon = hIcon; 11 IPicture* pPicture = 0; 12 HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)&pPicture); 13 if (FAILED(hr)) return hr; 14 15 // Create a stream and save the image 16 IStream* pStream = 0; 17 CreateStreamOnHGlobal(0, TRUE, &pStream); 18 LONG cbSize = 0; 19 hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize); 20 21 // Write the stream content to the file 22 if (!FAILED(hr)) { 23 HGLOBAL hBuf = 0; 24 GetHGlobalFromStream(pStream, &hBuf); 25 void* buffer = GlobalLock(hBuf); 26 HANDLE hFile = CreateFile(path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); 27 if (!hFile) hr = HRESULT_FROM_WIN32(GetLastError()); 28 else { 29 DWORD written = 0; 30 WriteFile(hFile, buffer, cbSize, &written, 0); 31 CloseHandle(hFile); 32 } 33 GlobalUnlock(buffer); 34 } 35 // Cleanup 36 pStream->Release(); 37 pPicture->Release(); 38 return hr; 39 40 } 41 int _tmain(int argc, _TCHAR* argv[]) 42 { 43 HICON hIcon = (HICON)LoadImage(0, L"c:\\windows\\system32\\perfcentercpl.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE); 44 if (!hIcon) return GetLastError(); 45 HRESULT hr = SaveIcon(hIcon, L"c:\\temp\\test.ico"); 46 return hr; 47 }
answer2:
1 #include <afx.h> 2 #include <afxwin.h> 3 #include <atlbase.h> 4 5 struct ICONDIRENTRY 6 { 7 UCHAR nWidth; 8 UCHAR nHeight; 9 UCHAR nNumColorsInPalette; // 0 if no palette 10 UCHAR nReserved; // should be 0 11 WORD nNumColorPlanes; // 0 or 1 12 WORD nBitsPerPixel; 13 ULONG nDataLength; // length in bytes 14 ULONG nOffset; // offset of BMP or PNG data from beginning of file 15 }; 16 17 // Helper class to release GDI object handle when scope ends: 18 class CGdiHandle 19 { 20 public: 21 CGdiHandle(HGDIOBJ handle) : m_handle(handle) {}; 22 ~CGdiHandle(){DeleteObject(m_handle);}; 23 private: 24 HGDIOBJ m_handle; 25 }; 26 27 28 // Save icon referenced by handle 'hIcon' as file with name 'szPath'. 29 // The generated ICO file has the color depth specified in 'nColorBits'. 30 // 31 bool SaveIcon(HICON hIcon, int nColorBits, const TCHAR* szPath) 32 { 33 ASSERT(nColorBits == 4 || nColorBits == 8 || nColorBits == 24 || nColorBits == 32); 34 35 if (offsetof(ICONDIRENTRY, nOffset) != 12) 36 { 37 return false; 38 } 39 40 CDC dc; 41 dc.Attach(::GetDC(NULL)); // ensure that DC is released when function ends 42 43 // Open file for writing: 44 CFile file; 45 if (!file.Open(szPath, CFile::modeWrite | CFile::modeCreate)) 46 { 47 return false; 48 } 49 50 // Write header: 51 UCHAR icoHeader[6] = {0, 0, 1, 0, 1, 0}; // ICO file with 1 image 52 file.Write(icoHeader, sizeof(icoHeader)); 53 54 // Get information about icon: 55 ICONINFO iconInfo; 56 GetIconInfo(hIcon, &iconInfo); 57 CGdiHandle handle1(iconInfo.hbmColor), handle2(iconInfo.hbmMask); // free bitmaps when function ends 58 BITMAPINFO bmInfo = {0}; 59 bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 60 bmInfo.bmiHeader.biBitCount = 0; // don't get the color table 61 if (!GetDIBits(dc, iconInfo.hbmColor, 0, 0, NULL, &bmInfo, DIB_RGB_COLORS)) 62 { 63 return false; 64 } 65 66 // Allocate size of bitmap info header plus space for color table: 67 int nBmInfoSize = sizeof(BITMAPINFOHEADER); 68 if (nColorBits < 24) 69 { 70 nBmInfoSize += sizeof(RGBQUAD) * (int)(1 << nColorBits); 71 } 72 73 CAutoVectorPtr<UCHAR> bitmapInfo; 74 bitmapInfo.Allocate(nBmInfoSize); 75 BITMAPINFO* pBmInfo = (BITMAPINFO*)(UCHAR*)bitmapInfo; 76 memcpy(pBmInfo, &bmInfo, sizeof(BITMAPINFOHEADER)); 77 78 // Get bitmap data: 79 ASSERT(bmInfo.bmiHeader.biSizeImage != 0); 80 CAutoVectorPtr<UCHAR> bits; 81 bits.Allocate(bmInfo.bmiHeader.biSizeImage); 82 pBmInfo->bmiHeader.biBitCount = nColorBits; 83 pBmInfo->bmiHeader.biCompression = BI_RGB; 84 if (!GetDIBits(dc, iconInfo.hbmColor, 0, bmInfo.bmiHeader.biHeight, (UCHAR*)bits, pBmInfo, DIB_RGB_COLORS)) 85 { 86 return false; 87 } 88 89 // Get mask data: 90 BITMAPINFO maskInfo = {0}; 91 maskInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 92 maskInfo.bmiHeader.biBitCount = 0; // don't get the color table 93 if (!GetDIBits(dc, iconInfo.hbmMask, 0, 0, NULL, &maskInfo, DIB_RGB_COLORS)) 94 { 95 return false; 96 } 97 ASSERT(maskInfo.bmiHeader.biBitCount == 1); 98 CAutoVectorPtr<UCHAR> maskBits; 99 maskBits.Allocate(maskInfo.bmiHeader.biSizeImage); 100 CAutoVectorPtr<UCHAR> maskInfoBytes; 101 maskInfoBytes.Allocate(sizeof(BITMAPINFO) + 2 * sizeof(RGBQUAD)); 102 BITMAPINFO* pMaskInfo = (BITMAPINFO*)(UCHAR*)maskInfoBytes; 103 memcpy(pMaskInfo, &maskInfo, sizeof(maskInfo)); 104 if (!GetDIBits(dc, iconInfo.hbmMask, 0, maskInfo.bmiHeader.biHeight, (UCHAR*)maskBits, pMaskInfo, DIB_RGB_COLORS)) 105 { 106 return false; 107 } 108 109 // Write directory entry: 110 ICONDIRENTRY dir; 111 dir.nWidth = (UCHAR) pBmInfo->bmiHeader.biWidth; 112 dir.nHeight = (UCHAR) pBmInfo->bmiHeader.biHeight; 113 dir.nNumColorsInPalette = (nColorBits == 4 ? 16 : 0); 114 dir.nReserved = 0; 115 dir.nNumColorPlanes = 0; 116 dir.nBitsPerPixel = pBmInfo->bmiHeader.biBitCount; 117 dir.nDataLength = pBmInfo->bmiHeader.biSizeImage + pMaskInfo->bmiHeader.biSizeImage + nBmInfoSize; 118 dir.nOffset = sizeof(dir) + sizeof(icoHeader); 119 file.Write(&dir, sizeof(dir)); 120 121 // Write DIB header (including color table): 122 int nBitsSize = pBmInfo->bmiHeader.biSizeImage; 123 pBmInfo->bmiHeader.biHeight *= 2; // because the header is for both image and mask 124 pBmInfo->bmiHeader.biCompression = 0; 125 pBmInfo->bmiHeader.biSizeImage += pMaskInfo->bmiHeader.biSizeImage; // because the header is for both image and mask 126 file.Write(&pBmInfo->bmiHeader, nBmInfoSize); 127 128 // Write image data: 129 file.Write((UCHAR*)bits, nBitsSize); 130 131 // Write mask data: 132 file.Write((UCHAR*)maskBits, pMaskInfo->bmiHeader.biSizeImage); 133 134 file.Close(); 135 136 return true; 137 } 138 139 // Test program for SaveIcon() function. 140 // 141 // Usage: first argument is input ICO file (must be 32x32 pixels); second argument is output ICO file 142 // 143 int _tmain(int argc, _TCHAR* argv[]) 144 { 145 ASSERT(argc == 3); 146 147 // Load a 32x32 icon: 148 HICON hIcon = (HICON)LoadImage(0, argv[1], IMAGE_ICON, 32, 32, LR_LOADFROMFILE | LR_CREATEDIBSECTION); 149 ASSERT(hIcon != NULL); 150 151 // Save with 24-bits colors: 152 if (!SaveIcon(hIcon, 24, argv[2])) 153 { 154 _ftprintf(stderr, _T("Error: saving icon to %s failed"), argv[2]); 155 return EXIT_FAILURE; 156 } 157 158 return EXIT_SUCCESS; 159 }
answer3:
1 #include <windows.h> 2 #include <stdio.h> 3 #include <tchar.h> 4 5 // 6 // ICONS (.ICO type 1) are structured like this: 7 // 8 // ICONHEADER (just 1) 9 // ICONDIR [1...n] (an array, 1 for each image) 10 // [BITMAPINFOHEADER+COLOR_BITS+MASK_BITS] [1...n] (1 after the other, for each image) 11 // 12 // CURSORS (.ICO type 2) are identical in structure, but use 13 // two monochrome bitmaps (real XOR and AND masks, this time). 14 // 15 16 typedef struct 17 { 18 WORD idReserved; // must be 0 19 WORD idType; // 1 = ICON, 2 = CURSOR 20 WORD idCount; // number of images (and ICONDIRs) 21 22 // ICONDIR [1...n] 23 // ICONIMAGE [1...n] 24 25 } ICONHEADER; 26 27 // 28 // An array of ICONDIRs immediately follow the ICONHEADER 29 // 30 typedef struct 31 { 32 BYTE bWidth; 33 BYTE bHeight; 34 BYTE bColorCount; 35 BYTE bReserved; 36 WORD wPlanes; // for cursors, this field = wXHotSpot 37 WORD wBitCount; // for cursors, this field = wYHotSpot 38 DWORD dwBytesInRes; 39 DWORD dwImageOffset; // file-offset to the start of ICONIMAGE 40 41 } ICONDIR; 42 43 // 44 // After the ICONDIRs follow the ICONIMAGE structures - 45 // consisting of a BITMAPINFOHEADER, (optional) RGBQUAD array, then 46 // the color and mask bitmap bits (all packed together 47 // 48 typedef struct 49 { 50 BITMAPINFOHEADER biHeader; // header for color bitmap (no mask header) 51 //RGBQUAD rgbColors[1...n]; 52 //BYTE bXOR[1]; // DIB bits for color bitmap 53 //BYTE bAND[1]; // DIB bits for mask bitmap 54 55 } ICONIMAGE; 56 57 // 58 // Write the ICO header to disk 59 // 60 static UINT WriteIconHeader(HANDLE hFile, int nImages) 61 { 62 ICONHEADER iconheader; 63 DWORD nWritten; 64 65 // Setup the icon header 66 iconheader.idReserved = 0; // Must be 0 67 iconheader.idType = 1; // Type 1 = ICON (type 2 = CURSOR) 68 iconheader.idCount = nImages; // number of ICONDIRs 69 70 // Write the header to disk 71 WriteFile( hFile, &iconheader, sizeof(iconheader), &nWritten, 0); 72 73 // following ICONHEADER is a series of ICONDIR structures (idCount of them, in fact) 74 return nWritten; 75 } 76 77 // 78 // Return the number of BYTES the bitmap will take ON DISK 79 // 80 static UINT NumBitmapBytes(BITMAP *pBitmap) 81 { 82 int nWidthBytes = pBitmap->bmWidthBytes; 83 84 // bitmap scanlines MUST be a multiple of 4 bytes when stored 85 // inside a bitmap resource, so round up if necessary 86 if(nWidthBytes & 3) 87 nWidthBytes = (nWidthBytes + 4) & ~3; 88 89 return nWidthBytes * pBitmap->bmHeight; 90 } 91 92 // 93 // Return number of bytes written 94 // 95 static UINT WriteIconImageHeader(HANDLE hFile, BITMAP *pbmpColor, BITMAP *pbmpMask) 96 { 97 BITMAPINFOHEADER biHeader; 98 DWORD nWritten; 99 UINT nImageBytes; 100 101 // calculate how much space the COLOR and MASK bitmaps take 102 nImageBytes = NumBitmapBytes(pbmpColor) + NumBitmapBytes(pbmpMask); 103 104 // write the ICONIMAGE to disk (first the BITMAPINFOHEADER) 105 ZeroMemory(&biHeader, sizeof(biHeader)); 106 107 // Fill in only those fields that are necessary 108 biHeader.biSize = sizeof(biHeader); 109 biHeader.biWidth = pbmpColor->bmWidth; 110 biHeader.biHeight = pbmpColor->bmHeight * 2; // height of color+mono 111 biHeader.biPlanes = pbmpColor->bmPlanes; 112 biHeader.biBitCount = pbmpColor->bmBitsPixel; 113 biHeader.biSizeImage = nImageBytes; 114 115 // write the BITMAPINFOHEADER 116 WriteFile(hFile, &biHeader, sizeof(biHeader), &nWritten, 0); 117 118 // write the RGBQUAD color table (for 16 and 256 colour icons) 119 if(pbmpColor->bmBitsPixel == 2 || pbmpColor->bmBitsPixel == 8) 120 { 121 122 } 123 124 return nWritten; 125 } 126 127 // 128 // Wrapper around GetIconInfo and GetObject(BITMAP) 129 // 130 static BOOL GetIconBitmapInfo(HICON hIcon, ICONINFO *pIconInfo, BITMAP *pbmpColor, BITMAP *pbmpMask) 131 { 132 if(!GetIconInfo(hIcon, pIconInfo)) 133 return FALSE; 134 135 if(!GetObject(pIconInfo->hbmColor, sizeof(BITMAP), pbmpColor)) 136 return FALSE; 137 138 if(!GetObject(pIconInfo->hbmMask, sizeof(BITMAP), pbmpMask)) 139 return FALSE; 140 141 return TRUE; 142 } 143 144 // 145 // Write one icon directory entry - specify the index of the image 146 // 147 static UINT WriteIconDirectoryEntry(HANDLE hFile, int nIdx, HICON hIcon, UINT nImageOffset) 148 { 149 ICONINFO iconInfo; 150 ICONDIR iconDir; 151 152 BITMAP bmpColor; 153 BITMAP bmpMask; 154 155 DWORD nWritten; 156 UINT nColorCount; 157 UINT nImageBytes; 158 159 GetIconBitmapInfo(hIcon, &iconInfo, &bmpColor, &bmpMask); 160 161 nImageBytes = NumBitmapBytes(&bmpColor) + NumBitmapBytes(&bmpMask); 162 163 if(bmpColor.bmBitsPixel >= 8) 164 nColorCount = 0; 165 else 166 nColorCount = 1 << (bmpColor.bmBitsPixel * bmpColor.bmPlanes); 167 168 // Create the ICONDIR structure 169 iconDir.bWidth = (BYTE)bmpColor.bmWidth; 170 iconDir.bHeight = (BYTE)bmpColor.bmHeight; 171 iconDir.bColorCount = nColorCount; 172 iconDir.bReserved = 0; 173 iconDir.wPlanes = bmpColor.bmPlanes; 174 iconDir.wBitCount = bmpColor.bmBitsPixel; 175 iconDir.dwBytesInRes = sizeof(BITMAPINFOHEADER) + nImageBytes; 176 iconDir.dwImageOffset = nImageOffset; 177 178 // Write to disk 179 WriteFile(hFile, &iconDir, sizeof(iconDir), &nWritten, 0); 180 181 // Free resources 182 DeleteObject(iconInfo.hbmColor); 183 DeleteObject(iconInfo.hbmMask); 184 185 return nWritten; 186 } 187 188 static UINT WriteIconData(HANDLE hFile, HBITMAP hBitmap) 189 { 190 BITMAP bmp; 191 int i; 192 BYTE * pIconData; 193 194 UINT nBitmapBytes; 195 DWORD nWritten; 196 197 GetObject(hBitmap, sizeof(BITMAP), &bmp); 198 199 nBitmapBytes = NumBitmapBytes(&bmp); 200 201 pIconData = (BYTE *)malloc(nBitmapBytes); 202 203 GetBitmapBits(hBitmap, nBitmapBytes, pIconData); 204 205 // bitmaps are stored inverted (vertically) when on disk.. 206 // so write out each line in turn, starting at the bottom + working 207 // towards the top of the bitmap. Also, the bitmaps are stored in packed 208 // in memory - scanlines are NOT 32bit aligned, just 1-after-the-other 209 for(i = bmp.bmHeight - 1; i >= 0; i--) 210 { 211 // Write the bitmap scanline 212 WriteFile( 213 hFile, 214 pIconData + (i * bmp.bmWidthBytes), // calculate offset to the line 215 bmp.bmWidthBytes, // 1 line of BYTES 216 &nWritten, 217 0); 218 219 // extend to a 32bit boundary (in the file) if necessary 220 if(bmp.bmWidthBytes & 3) 221 { 222 DWORD padding = 0; 223 WriteFile(hFile, &padding, 4 - bmp.bmWidthBytes, &nWritten, 0); 224 } 225 } 226 227 free(pIconData); 228 229 return nBitmapBytes; 230 } 231 232 // 233 // Create a .ICO file, using the specified array of HICON images 234 // 235 BOOL SaveIcon3(TCHAR *szIconFile, HICON hIcon[], int nNumIcons) 236 { 237 HANDLE hFile; 238 int i; 239 int * pImageOffset; 240 241 if(hIcon == 0 || nNumIcons < 1) 242 return FALSE; 243 244 // Save icon to disk: 245 hFile = CreateFile(szIconFile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); 246 247 if(hFile == INVALID_HANDLE_VALUE) 248 return FALSE; 249 250 // 251 // Write the iconheader first of all 252 // 253 WriteIconHeader(hFile, nNumIcons); 254 255 // 256 // Leave space for the IconDir entries 257 // 258 SetFilePointer(hFile, sizeof(ICONDIR) * nNumIcons, 0, FILE_CURRENT); 259 260 pImageOffset = (int *)malloc(nNumIcons * sizeof(int)); 261 262 // 263 // Now write the actual icon images! 264 // 265 for(i = 0; i < nNumIcons; i++) 266 { 267 ICONINFO iconInfo; 268 BITMAP bmpColor, bmpMask; 269 270 GetIconBitmapInfo(hIcon[i], &iconInfo, &bmpColor, &bmpMask); 271 272 // record the file-offset of the icon image for when we write the icon directories 273 pImageOffset[i] = SetFilePointer(hFile, 0, 0, FILE_CURRENT); 274 275 // bitmapinfoheader + colortable 276 WriteIconImageHeader(hFile, &bmpColor, &bmpMask); 277 278 // color and mask bitmaps 279 WriteIconData(hFile, iconInfo.hbmColor); 280 WriteIconData(hFile, iconInfo.hbmMask); 281 282 DeleteObject(iconInfo.hbmColor); 283 DeleteObject(iconInfo.hbmMask); 284 } 285 286 // 287 // Lastly, skip back and write the icon directories. 288 // 289 SetFilePointer(hFile, sizeof(ICONHEADER), 0, FILE_BEGIN); 290 291 for(i = 0; i < nNumIcons; i++) 292 { 293 WriteIconDirectoryEntry(hFile, i, hIcon[i], pImageOffset[i]); 294 } 295 296 free(pImageOffset); 297 298 // finished! 299 CloseHandle(hFile); 300 301 return TRUE; 302 } 303 304 305 int saveIcon(TCHAR* filename, TCHAR* iconFile) { 306 HICON hIconLarge; 307 HICON hIconSmall; 308 BOOL ret; 309 310 311 if ( ExtractIconEx(filename, 0, &hIconLarge, &hIconSmall, 1) == 0 ) { 312 return 1; 313 } 314 315 ret = SaveIcon3(iconFile, &hIconSmall, 1); 316 if ( ret ) { 317 return 0; 318 } 319 return -1; 320 } 321 322 int _tmain(int argc, TCHAR* argv[]) { 323 if ( argc < 3 ) { 324 printf("Usage: <exe/dll file> <output ico file>"); 325 return EXIT_FAILURE; 326 } 327 _tprintf(_T("src = %s\n"), argv[1]); 328 _tprintf(_T("dest = %s\n"), argv[2]); 329 saveIcon(argv[1], argv[2]); 330 331 return 0; 332 }