Widows下只认.ico格式为程序图标,这是一种源自bmp的图片格式。ico中的颜色可以通过color table来表示也可以直接通过RGBA数组表示。
ico文件的格式见官方文档:
http://msdn.microsoft.com/en-us/library/ms997538.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376%28v=vs.85%29.aspx
其它一些关于ico文件的文档见:
比较详细的原理介绍:http://blogs.msdn.com/b/oldnewthing/archive/2010/10/18/10077133.aspx
ico格式描述:http://www.daubnet.com/en/file-format-ico
Programming Tips & Tricks:http://tipsandtricks.runicsoft.com/Cpp/BitmapTutorial.html
bmp和ico格式描述:http://www.digicamsoft.com/bmp/bmp.html
ico文件相关实现:
IconImagePlugin in Python PIL: http://code.google.com/p/casadebender/source/browse/python/PIL/Win32IconImagePlugin.py
construct ico from RGBA array - a python implementation:http://fayaa.com/code/view/6094/
png2ico:http://www.winterdrache.de/freeware/png2ico/
下面是一个用从RGBA生成ico文件的C语言实现,生成一个红色的图标文件 - test.ico。
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
void Fwrite(FILE * f, char * data, int byte)
{
if (1 != fwrite(data, byte, 1, f)) {
perror("fwrite error");
exit(1);
}
}
void WriteByte(FILE* f, unsigned int val, int byte)
{
char data[4];
assert(byte <= 4);
memcpy((void *)data, (void *)&val, byte);
Fwrite(f, data, byte);
};
void generate_ico_file(const char * filename, char * body,
int width, int height, int has_alpha)
{
int x, y;
int index = 0;
int Size = 0;
int offset= 6 + 1 * 16;
int bpp = 32;
FILE* outfile=fopen(filename,"wb");
if (outfile==NULL) {
perror("fopen error");
exit(1);
};
WriteByte(outfile,0, 2); //idReserved
WriteByte(outfile,1, 2); //idType
WriteByte(outfile,1, 2); //idCount
WriteByte(outfile,width, 1); //bWidth
WriteByte(outfile,height, 1); //bHeight
WriteByte(outfile,0, 1); //bColorCount
WriteByte(outfile,0, 1); //bReserved
WriteByte(outfile,1, 2); //wPlanes
WriteByte(outfile,bpp, 2); //wBitCount
Size = 40 + height * ((width + 31) / 32 * 32 / 8 + width * 3); //Note 4 bytes alignment
if (bpp == 32)
Size += height * width;
WriteByte(outfile,Size, 4); //dwBytesInRes
WriteByte(outfile,offset, 4); //dwImageOffset
WriteByte(outfile,40, 4); //biSize
WriteByte(outfile,width, 4); //biWidth
WriteByte(outfile,2 * height, 4); //biHeight
WriteByte(outfile,1, 2); //biPlanes
WriteByte(outfile,bpp, 2); //biBitCount
WriteByte(outfile,0, 4); //biCompression
WriteByte(outfile,0, 4); //biSizeImage
WriteByte(outfile,0, 4); //biXPelsPerMeter
WriteByte(outfile,0, 4); //biYPelsPerMeter
WriteByte(outfile,0, 4); //biClrUsed
WriteByte(outfile,0, 4); //biClrImportant
// XOR mask
for (y= height - 1; y >= 0; --y) {
for (x = 0; x < width; ++x) {
index = (y * width + x) * 4;
WriteByte(outfile, body[index], 1); //Blue
WriteByte(outfile, body[index + 1], 1); //Green
WriteByte(outfile, body[index + 2], 1); //Red
WriteByte(outfile, has_alpha ? body[index + 3] : 255, 1); //Alpha
}
}
// AND mask
for (y = 0; y < (height * ((width + 31) / 32 * 32 / 8)); ++y) {
WriteByte(outfile, 0, 1);
}
fclose(outfile);
}
#define WIDTH 72
#define HEIGHT 72
int main()
{
int image[WIDTH * HEIGHT];
int i, j;
for (i = 0; i < HEIGHT; ++i) {
for (j = 0; j < WIDTH; ++j) {
image[i * WIDTH + j] = 0xFFFF0000; // pure red icon, for test
}
}
generate_ico_file("test.ico", (char *)image, WIDTH, HEIGHT, 1);
return 0;
}