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

         原本我程序里用的的图标都是网上下载或者在线用png转成ico,但是之前那个公司不能上外网,而ps和fw都不能直接生成ico格式(ps可以找转ico的插件)。后来,网上找了个C#图片转ico的例子,借助的Icon类,但是生成的图效果不太好,透明图部分会有黑线(预览)。于是乎就折腾了半天ico格式的协议,主要参考的是https://www.cnblogs.com/cswuyg/p/3603707.html以及他的相关参考,还有http://lqzit.iteye.com/blog/1033407。除了掩码没搞明白,其他基本都清楚了,然后根据在线转换网站生成的格式来作为参照,完成了生成ico的功能。(其实可以直接参照开源软件ImageMagick的代码,在源码包的coders文件夹里有各种图的格式,我也是后来才知道,ImageMagick中文网:http://www.imagemagick.com.cn/download.html) 

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

        首先,ico结构=Icon格式头+位图格式头+位图数据(数据行是反过来的,第一行在最后)+位图掩码部分。

(代码中Byte一个字节,Word两个字节,Long和DWord四个字节,小端模式--即低位在前)

第一部分: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字节
};

通过BeyondCompare软件查看得到的icon头hex数据是这样的(64*64像素)

第二部分:位图格式

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

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表示全是重要
}; 

通过BeyondCompare软件查看得到的位图头hex数据是这样的

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

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

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

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龚建波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值