zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    spring学习记录_Spring中的新注解
    spring学习记录_spring的 注解
    spring学习记录_spring的 ioc核心容器
    关于myeclipse项目运行报错:Access denied for user 'root'@'localhost' (using password: YES)
    vue项目中实现多语言切换
    OC中限制UITextView的最大字数的实现
    简单瀑布流的实现
    仿购物车的实现
    仿QQ好友列表界面的实现
    类似QQ侧滑菜单功能实现
  • 原文地址:https://www.cnblogs.com/devc/p/3423750.html
Copyright © 2011-2022 走看看