How can I save HICON to an .ico file

refer:http://stackoverflow.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 }
View Code

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
"), argv[1]);
328     _tprintf(_T("dest = %s
"), argv[2]);
329     saveIcon(argv[1], argv[2]);
330 
331     return 0;
332 }
原文地址:https://www.cnblogs.com/devc/p/3423750.html