|
#define ICON_SIZE 32

static int _HBitmapToBmp32Bits(HBITMAP hBitmap, U8 *out, int out_len)
  {
 /**//*
* 注意:
* 该函数代码部分参考csdn。向原作者致敬!
*/
// 设备描述表
HDC hDC;
//位图中每个像素所占字节数
WORD wBitCount;
// 定义调色板大小,位图中像素字节大小,位图文件大小,写入文件字节数
DWORD dwBmBitsSize;
//位图属性结构
BITMAP Bitmap;
//位图信息头结构
BITMAPINFOHEADER bi;
// 定义文件,分配内存句柄,调色板句柄
// 计算位图文件每个像素所占字节数
HANDLE hPal, hOldPal = NULL;

// 设置位图信息头结构
wBitCount = 32;
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
 if (Bitmap.bmWidth != ICON_SIZE || Bitmap.bmHeight != ICON_SIZE) {
Dbg("size not fit\n");
return 0;
}

memset(&bi, 0, sizeof(bi));
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;

// 计算位图大小
dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32) * 4 * Bitmap.bmHeight;
if (out_len < (int)dwBmBitsSize)
return 0;

// 处理调色板
hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
 if (hPal) {
hDC = GetDC(NULL);
hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}

// 获取该调色板下新的像素值
GetDIBits(hDC,
hBitmap,
0,
(UINT)Bitmap.bmHeight,
(LPSTR)out,
(BITMAPINFO *)&bi,
DIB_PAL_COLORS
);

// 恢复调色板
 if (hOldPal) {
SelectPalette(hDC,(HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
}

return dwBmBitsSize;
}


static int ExtToIcoFile(char *ext, U8 *out, int out_len)
  {
SHFILEINFOA sfi;
 char str[32] = { "*." };
U32 *buf;
ICONINFO ii;
U8 *orig = out;
int i;

#define XOR_SIZE ICON_SIZE*ICON_SIZE*4
#define AND_SIZE ICON_SIZE*ICON_SIZE/8

// Calc File Length
// 文件头6字节
// 图像信息块16字节
// BMP信息头40字节
// XOR位图
// 单色AND位图
if (out_len < 6 + 16 + 40 + XOR_SIZE + AND_SIZE)
return 0;

strncat(str, ext, sizeof(str) - 8);
SHGetFileInfoA(str,
FILE_ATTRIBUTE_NORMAL,
&sfi,
sizeof(SHFILEINFO),
SHGFI_USEFILEATTRIBUTES | SHGFI_ICON
);
GetIconInfo(sfi.hIcon, &ii);

 /**//*
(一、文件头6字节)
000(000)2 保留的字节 00 00
002(002)2 资源类型 01 00 (01为图标,02为光标)
004(004)2 图象个数 01 00
*/
*(U16 *)out = 0; out += 2;
*(U16 *)out = 1; out += 2;
*(U16 *)out = 1; out += 2;

 /**//*
(二、图像信息块16字节)
006(006)1 图标宽度 20
007(007)1 图标高度 20
008(008)1 颜色计数 00(02=单色, 00≥256色)
009(009)1 未用 00
010(00A)4 保留的 00 00 00 00
014(00E)4 图象数据块的长度 28 01 00 00(10进制=296)
018(012)4 图象数据块相对于文件头部的偏移量 16 00 00 00(10进制=22)
*/
*out++ = ICON_SIZE;
*out++ = ICON_SIZE;
*out++ = 0;
*out++ = 0;
*(U32 *)out = 0; out += 4;
*(U32 *)out = 40 + XOR_SIZE + AND_SIZE; out += 4;
*(U32 *)out = 22; out += 4;

 /**//*
(三、BMP信息头40字节)
022(016)4 BMP 信息头结构长度 28 00 00 00(10进制=40)
026(01A)4 图像宽度 10 00 00 00
030(01E)4 图像高度(XOR图高度+AND图高度) 20 00 00 00
034(022)2 位面板数 01 00
036(024)2 每象素所占位数 04 00
038(026)4 象素数据的压缩类型 00 00 00 00(表示未压缩)
042(02A)4 图象数据的长度 C0 00 00 00(10进制=192)
046(02E)16 未用 16个00
*/
*(U32 *)out = 40; out += 4;
*(U32 *)out = 32; out += 4;
*(U32 *)out = 64; out += 4;
*(U16 *)out = 1; out += 2; // ??
*(U16 *)out = 32; out += 2;
*(U32 *)out = 0; out += 4;
*(U32 *)out = XOR_SIZE + AND_SIZE; out += 4;
memset(out, 0, 16); out += 16;

 /**//*
(五、XOR位图的数据)
*/
if (_HBitmapToBmp32Bits(ii.hbmColor, out, XOR_SIZE) != XOR_SIZE)
return 0;
out += 32*32*4;

 /**//*
(六、单色AND位图的数据)
*/
buf = (U32 *)malloc(XOR_SIZE);
if (!buf)
return 0;
if (_HBitmapToBmp32Bits(ii.hbmMask, (U8 *)buf, XOR_SIZE) != XOR_SIZE)
return 0;
memset(out, 0, AND_SIZE);
//out += 32*32/8;
 for (i = 0; i < AND_SIZE*8; i++) {
if (buf[i])
*out |= (1 << (7 - (i&7)));
if ((i&7) == 7)
out++;
}
free(buf);

#undef AND_SIZE
#undef XOR_SIZE

return out - orig;
}

#undef ICON_SIZE


int main()
  {
void *s, *a;
int len;
static char line[1024], method[16], url[128];
FILE *fp;
static U8 buf[1024*1024*1];
fp = fopen("b.ico", "wb+");
len = ExtToIcoFile("mp3", buf, sizeof(buf));
len = fwrite(buf, len, 1, fp);
fclose(fp);
return 0;

|