Read .ICO format.

Based on the last post below is a function for reading a .ICO file. The code only reads in the 32bit bitmaps in the icon skipping over the others. The function returns an array of HBITMAP’s of length bmpCount.

All Code is freely provided, no guarantees or warranties about its quality, use at your own risk.

C++
<code>
 
HBITMAP* ReadICO(TCHAR* srcPath, int* bmpCount)
{
 
  *bmpCount = 0;
 
  FILE* fp = _tfopen(srcPath,_T("rb"));
  if(fp == NULL)
    return false;
 
  ICONDIR icoDir;
 
  fread(&icoDir.idReserved,sizeof(WORD), 1, fp);
  fread(&icoDir.idType,sizeof(WORD), 1, fp);
  fread(&icoDir.idCount,sizeof(WORD), 1, fp);
 
  ICONDIRENTRY* entries = (ICONDIRENTRY*)malloc(sizeof(ICONDIRENTRY) * icoDir.idCount);
  memset(entries, 0, sizeof(ICONDIRENTRY) * icoDir.idCount);
 
  for(int i=0;i<icoDir.idCount;i++)
  {
    fread(&entries[i].bWidth,sizeof(BYTE), 1, fp);
    fread(&entries[i].bHeight,sizeof(BYTE), 1, fp);
    fread(&entries[i].bColorCount,sizeof(BYTE), 1, fp);
    fread(&entries[i].bReserved,sizeof(BYTE), 1, fp);
 
    fread(&entries[i].wPlanes,sizeof(WORD), 1, fp);
    fread(&entries[i].wBitCount,sizeof(WORD), 1, fp);
    fread(&entries[i].dwBytesInRes,sizeof(DWORD), 1, fp);
    fread(&entries[i].dwImageOffset,sizeof(DWORD), 1, fp);
 
  }
 
  HBITMAP* bmpResult = (HBITMAP*)malloc(sizeof(HBITMAP) * icoDir.idCount);
  memset(bmpResult, 0, sizeof(HBITMAP) * icoDir.idCount);
 
  HDC hdc = CreateCompatibleDC(NULL);
  for(int i=0;i<icoDir.idCount;i++)
  {
    if(entries[i].wBitCount != 32)
    {
      //only support 32bit
      continue;
    }
 
    fseek(fp, entries[i].dwImageOffset, SEEK_SET);
 
    ICONIMAGE ico;
    ico.lpBits = (LPBYTE)malloc(entries[i].dwBytesInRes);
    fread(ico.lpBits, 1, entries[i].dwBytesInRes, fp);
 
    ico.lpbi = (LPBITMAPINFO) ico.lpBits;    
 
    int height = ico.lpbi->bmiHeader.biHeight / 2;
    BITMAPINFO bmi;
    ::ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
    bmi.bmiHeader.biWidth = ico.lpbi->bmiHeader.biWidth;
    bmi.bmiHeader.biHeight = height;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = ico.lpbi->bmiHeader.biBitCount;
    bmi.bmiHeader.biSizeImage = 0;
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biClrUsed = 0;
    bmi.bmiHeader.biClrImportant = 0;
 
 
    HBITMAP hBitmap = ::CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
    if(((int)hBitmap) != ERROR_INVALID_PARAMETER && ((int)hBitmap) != ERROR_NOT_ENOUGH_MEMORY)
    {
      bmpResult[*bmpCount] = hBitmap;
      *bmpCount += 1;
 
      ::SelectObject(hdc, hBitmap);
      ::SetDIBitsToDevice(hdc, 0, 0, bmi.bmiHeader.biWidth, height,
                0, 0, 0, height, ico.lpBits + sizeof(BITMAPINFO), &bmi, DIB_RGB_COLORS);
    }
 
  }
  DeleteDC(hdc);
 
  fclose(fp);
 
  return bmpResult;
}
 
</code>

Comments (0)

› No comments yet.

Pingbacks (0)

› No pingbacks yet.