Icon图标格式(用于生成*.ico图标)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gongjianbo1992/article/details/80871026

        之前写程序的图标都是用Fireworks画,然后在线用png转成ico的。现在公司不能上外网了(万恶),但是ps和fw都不能直接生成ico格式。网上找了个C#图片转ico的例子,不过自带类生成的貌似格式不太好,透明图会有黑线。于是乎就折腾了半天ico格式的协议,主要参考的是https://www.cnblogs.com/cswuyg/p/3603707.html以及他的相关参考,还有http://lqzit.iteye.com/blog/1033407。除了掩码没搞明白,其他基本都清楚了,然后我根据常用的那个在线转换网站生成的格式来作为生成的格式。(其实有个开源的软件可以直接参照那些格式,在源码包的coders文件夹里有各种图的格式,要是我早点看到就好了ImageMagick中文网:http://www.imagemagick.com.cn/download.html

        废话少说,如果要了解icon相关的协议,可以百度或者看我最上面那个链接,这里我只写下我的实现。生成的是32色RGBA的ico图,在xp/win7/win10下显示正常,没有发现有黑线。

        首先,ico图=icon格式头+位图格式头+imge数据(数据行是反过来的)+掩码部分

第一部分:icon格式头(22Byte)

struct IconHeader
{
     WORD idReserved; // 保留位必须为0
     WORD idType; // 类型 (1表示icon),也就是必须为1
     WORD idCount; // 包含多少张图(icon可以含多张图,分别在不同尺寸下展示)
     ICONDIRENTRY idEntries[]; // 对应idCount的结构体,多少张图就有多少个该结构
} ;


struct ICONDIRENTRY
{
     BYTE bWidth; // 图片的像素宽度
     BYTE bHeight; // 图片的像素高度
     BYTE bColorCount; // 颜色深度:=1<<(wBitCount×wPlanes),如果大于等于8就为0;但是可以不管,填0就行
     BYTE bReserved; // 保留位必须为零
     WORD wPlanes; // Color Planes,我填的1
     WORD wBitCount; // Bits per pixel,我填的32
     DWORD dwBytesInRes; //该图字节数(位图头+image数据+掩码的字节总数)
     DWORD dwImageOffset; //相对于文件开始处的偏移量,单个图填22,毕竟icon头加起来22字节
};


第二部分:位图格式

struct BitmapHeader
{
    BITMAPINFOHEADER icHeader; // DIB header
    RGBQUAD icColors[]; // 颜色表,24/32色不用颜色表
    BYTE icXOR[]; // DIB bits for XOR mask
    BYTE icAND[]; // DIB bits for AND mask 这两个单色的时候位置相反
} ;

虽然后两个xor和and没搞懂协议怎么算的,但是我根据生成的格式倒推出,icHeader位图格式头,40Byte;icColors去掉;icXor填图片原始数据,并且行数是倒过来的,第一行是原图的最后一行,以此类推,每个像素先后填入颜色B.G.R.A部分值,共width×height×4  Byte;icAnd部分,对应不透明度,如果是透明就为1,半透明和不透明都是0(相当于1位对应于一个像素点,行数同height,宽度若原为16/32则为掩码占的宽度为4Byte,若原为48/64则为8Byte,若原为128则为16Byte,并且16和48时有效位填不满,空出来的是每行后部分字节填0(自行脑补二维数组,行数相等,arr[0][0]有效arr[0][n-1]为0)),掩码部分占了width×掩码宽度 Byte

struct bitmapHeader
{
    DWORD  biSize;//结构长度,40Byte
    LONG   biWidth; //图宽度
    LONG   biHeight;//图高度(xor+and的)也就是两倍高度
    WORD   biPlanes;//我填的1
    WORD   biBitCount;//我填的32
    DWORD   biCompression;//压缩方式,填的0
    DWORD   biSizeImage;//图大小,仅rgba部分
    LONG    biXPelsPerMeter;//(后面四个貌似不用管,是属于bmp的格式),X方向分辨率
    LONG    biYPelsPerMeter;//Y方向分辨率
    DWORD  biClrUsed;//颜色数,可以填0默认
    DWORD  biClrImportant;//重要颜色数,填0表示全是重要
} 

 
 

这样,假如是64*64的ico图标,应该占16958字节,22+40+16384+512.

自己的新电脑没有二进制查看工具,没法截图示例,有空(严重怀疑!)补上。

知道了格式就容易把图片转为ico图标了,获取rgab值然后填充字节数组就行了。

猜你喜欢

转载自blog.csdn.net/gongjianbo1992/article/details/80871026