ICON合并(2)

上次写了一个完整的icon文件结构了,那么,读取一个icon文件的代码也就容易写了,有个小地方要注意,打开文件的选项是rb,因为icon文件是2进制文件,针对32x32的256色icon文件的 代码如下:

LPTSTR              filename,
ICONDIR*            pIconDir,
ICONDIRENTRY*       pIconDirEntry,
ICONIMAGE*          pIconImage,
BITMAPINFOHEADER *  pBIH,
RGBQUAD *           pColorTable,
BYTE*               xorMask,
BYTE*               andMask

FILE *f=fopen(filename,"rb");
// 创建ICONDIR来存放数据
pIconDir =(ICONDIR*)malloc(sizeof(ICONDIR));
// 保留字
fread(&(pIconDir->idReserved),sizeof(WORD),1,f);
// 类型字
fread(&(pIconDir->idType),sizeof(WORD),1,f);
// 文件中包含的图标个数
fread(&(pIconDir->idCount),sizeof(WORD),1,f);
// 根据图像个数重新分配ICONDIR空间
pIconDir = (ICONDIR*)realloc( pIconDir,
    (sizeof(WORD)* 3 )+
    (sizeof(ICONDIRENTRY)*pIconDir->idCount));
// 读取ICONDIRENTRY
fread(pIconDir->idEntries,
      pIconDir->idCount*sizeof(ICONDIRENTRY),1,f);
// 对于每个图标,循环
for(i=0;i<pIconDir->idCount;i++)
{
    pIconDirEntry=&(pIconDir->idEntries[i]);
    // 分配保存图像信息的空间
    pIconImage = (ICONIMAGE* )malloc(
                    pIconDirEntry->dwBytesInRes );
    // seek至图像所在位置
    fseek(f,pIconDir->idEntries[i].dwImageOffset,
            SEEK_SET);
    // 读取图像数据
    fread(pIconImage,
        pIconDir->idEntries[i].dwBytesInRes,1,f);
    pBIH=&(pIconImage->icHeader);
    // 获得色彩表
    pColorTable=(RGBQUAD*)(
        (LPSTR)pIconImage+
        (WORD) (pIconImage->icHeader.biSize));
    xorMask=(BYTE*)((LPSTR)pColorTable+256*4);
    andMask=xorMask+32*32;
    /*
    do something
    */
}

至于icon的合并,图片分为前景图片和背景图片,对前景图片每个像素遍历,如果像素不是透明的,就把该像素的颜色复制到背景图片上去。这里颜色是不能直接复制的,当前像素的掩码就是当前像素颜色在颜色表中的索引,查找颜色表得到像素的RGB编码,然后在背景图片的颜色表中找到该RGB编码对应的索引,再把该索引写到背景图片的掩码区。我说得可能啰嗦了点,简单点表示就是:前景xorMask -> 前景颜色表index -> RGB -> 背景颜色表index -> 背景xorMask。然后还有一点不能忽略,该像素如果在背景颜色的andMask中表明是透明(值为1)的话,现在要改为非透明(值为0)。

思路大体如此,但并不完善,因为前景图片中的颜色也许在背景图片里面就没有,要真正解决好这个问题,可能还有些麻烦,要重新构建icon的颜色表。

Comments