duilib不支持ico格式的图标资源, 但是我要想显示ico格式的图标...

发现网上那些转换ico为bmp或其它格式的都不是一个好办法, 也还是不能让duilib直接显示ico...

昨晚稍微研究了一下ico文件的格式, 发现其非常简单, 其就是一个容器而已, ico文件是bmp/png文件的组合.

于是我写了几句代码修改了下duilib的图片解码核心stb_image.c, 让她支持解码ico.

随笔后面有文件下载, 可跳过接下来的内容, 直接下载stb_image.c并重新编译duilib即可.

  代码有BUG, 请不要再使用这种方法. 可以考虑使用评论中的那种方式.

下面是对utils/stb_image.c添加的内容:

//女孩不哭 添加于 2014年4月22日 01:09:35
// QQ: 191035066
// 增加ico支持
// // ICO (file format)
// http://en.wikipedia.org/wiki/ICO_%28file_format%29
#pragma pack(push,1)
typedef struct{
unsigned short reserved;
unsigned short type;
unsigned short nfiles;
}ICONDIR; typedef struct{
unsigned char width;
unsigned char height;
unsigned char ncolors;
unsigned char reserved;
unsigned short color_planes;
unsigned short bpp;
unsigned long cb;
unsigned long offset;
}ICONDIRENTRY; //位图文件头数据
typedef struct _BITMAP_FILE_HEADER{
unsigned char signature[]; //00~01:文件头签名字节,仅检测'BM'序
unsigned long file_size; //02~05:整个文件的大小
unsigned long _reserved1; //06~09:保留4字节,必须为0
unsigned long data_offset; //0A~0D:位图数据距文件开始的偏移
}BITMAP_FILE_HEADER; #pragma pack(pop) static unsigned char png_sig[] = {0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A}; unsigned char* do_load_ico(unsigned char* buffer,unsigned int size,int* psize)
{
// 我实在是讨厌ms不支持完整的C语言
ICONDIR* pIconDir;
ICONDIRENTRY* pIconDirEntry;
int nfiles,themax;
int width,height;
int i; unsigned char* data; if(size < sizeof(ICONDIR)) return NULL;
pIconDir = (ICONDIR*)buffer; if(pIconDir->reserved != ) return NULL;
if(pIconDir->type != ) return NULL;
if(pIconDir->nfiles == ) return NULL; nfiles = pIconDir->nfiles; if(sizeof(ICONDIR) + nfiles*sizeof(ICONDIRENTRY) > size) return NULL; //找最大的那张图出来
width=height = -;
themax = -;
for(i=; i<nfiles; i++){
pIconDirEntry = &((ICONDIRENTRY*)(buffer+sizeof(ICONDIR)))[i];
if(pIconDirEntry->width== && pIconDirEntry->height==){
width=;
height=;
themax = i;
break;
}
if(pIconDirEntry->width > width
&& pIconDirEntry->height > height)
{
width = pIconDirEntry->width;
height = pIconDirEntry->height;
themax = i;
}
} //定位到最大那张
pIconDirEntry = (ICONDIRENTRY*)(buffer+sizeof(ICONDIR)) + themax; if(pIconDirEntry->offset + pIconDirEntry->cb > size) return NULL; if(memcmp(buffer+pIconDirEntry->offset, png_sig, ) == ){ // PNG
data = (unsigned char*)malloc(pIconDirEntry->cb);
if(!data) return NULL;
memcpy(data, buffer+pIconDirEntry->offset,pIconDirEntry->cb);
*psize = pIconDirEntry->cb;
return data;
}else{ //may BMP
BITMAP_FILE_HEADER* pbfh;
data = (unsigned char*)malloc(sizeof(BITMAP_FILE_HEADER) + pIconDirEntry->cb);
if(!data) return NULL;
pbfh = (BITMAP_FILE_HEADER*)data;
pbfh->_reserved1 = ;
pbfh->signature[]='B';
pbfh->signature[]='M';
pbfh->file_size = sizeof(BITMAP_FILE_HEADER) + pIconDirEntry->cb;
pbfh->data_offset = sizeof(BITMAP_FILE_HEADER) + ; // 40: sizeof(BITMAP_INFO_HEADER), defined by MS.
memcpy(data+sizeof(BITMAP_FILE_HEADER), buffer+pIconDirEntry->offset, pIconDirEntry->cb);
*psize = pIconDirEntry->cb + sizeof(BITMAP_FILE_HEADER);
return data;
}
}

找到 stbi_load_main 函数, 并把上面的函数放到它前面即可.(其实放哪儿无所谓, 只要stbi_load_main能调用即可).

然后修改 stbi_load_main 为如下:

static unsigned char *stbi_load_main(stbi *s, int *x, int *y, int *comp, int req_comp)
{
unsigned char* p; // 这个是我定义的
int size; if (stbi_jpeg_test(s)) return stbi_jpeg_load(s,x,y,comp,req_comp);
if (stbi_png_test(s)) return stbi_png_load(s,x,y,comp,req_comp);
if (stbi_bmp_test(s)) return stbi_bmp_load(s,x,y,comp,req_comp);
if (stbi_gif_test(s)) return stbi_gif_load(s,x,y,comp,req_comp);
if (stbi_psd_test(s)) return stbi_psd_load(s,x,y,comp,req_comp);
if (stbi_pic_test(s)) return stbi_pic_load(s,x,y,comp,req_comp); //////////////////////////////////////////////////////////////////////////
//因为ico用得少, 所以放到最后
p = do_load_ico(s->img_buffer,s->img_buffer_end-s->img_buffer_original,&size);
if(p){
unsigned char* q;
stbi s;
start_mem(&s,p,size);
if (stbi_png_test(&s)) q = stbi_png_load(&s,x,y,comp,req_comp);
else if (stbi_bmp_test(&s)) q = stbi_bmp_load(&s,x,y,comp,req_comp);
else q = NULL;
free(p);
if(q) return q;
}
////////////////////////////////////////////////////////////////////////// #ifndef STBI_NO_HDR
if (stbi_hdr_test(s)) {
float *hdr = stbi_hdr_load(s, x,y,comp,req_comp);
return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
}
#endif // test tga last because it's a crappy test!
if (stbi_tga_test(s))
return stbi_tga_load(s,x,y,comp,req_comp);
return epuc("unknown image type", "Image not of any known type, or corrupt");
}

作了上面的修改后, duilib应该就能够直接加载ico并显示了.

另外, ico文件中的图片大小信息无法直接知道, 还有另外一个几行代码拼成的小程序用来显示将要加载的ico的大小信息, 在后面一并提供下载.

显示效果:

stb_image.c和ico大小查看工具下载: http://share.weiyun.com/e4ac833f8c6d9315b7694e4007b8cf28

另外提供一个ico转换png的工具:  http://www.cnblogs.com/memset/p/ico2png.html

女孩不哭 @ cnblogs.com/memset @ 2014-04-22

结束~~~~~~~~~~~~~

修改stb_image.c以让Duilib直接支持Ico格式的图标显示的更多相关文章

  1. Photoshop支持ico输出

    1.Photoshop支持ico格式插件下载:ICOFormat.8bi 2.把文件放到ps安装目录:xxx/Plug-ins/File Formats 下 3.重启下ps

  2. Duilib 修改程序exe、在任务栏以及任务管理器上的图标

    参考:https://blog.csdn.net/Rongbo_J/article/details/47379997       https://www.cnblogs.com/happinessda ...

  3. 扩展GDAL,支持CNSDTF格式(一)

    扩展GDAL,支持CNSDTF格式(一) 一.        简介 本文主要根据<中华人民共和国国家标准GB/T17798-2007--地理空间数据交换格式(Geospatialdata tra ...

  4. 配置iis支持.json格式的文件

    配置iis支持.json格式的文件发现要让IIS支持json文件并不是单纯的添加mime这么简单啊,以下是设置方法:一.IIS 6 1. MIME设置:在IIS的站点属性的HTTP头设置里,选MIME ...

  5. VMware ESXi 不支持NTFS格式的USB外接硬盘

    本来想搞直通USB外接大容量硬盘(希捷Seagate Backup+ Hub WH 8T),实现在同一部ESXi下,直接将NAS的数据转移到外接硬盘.结果发现虚拟机下的win server系统识别不了 ...

  6. FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库

    FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库:1. 安装faad2 # wget http://downloads.sourceforge.net/fa ...

  7. 使用video.js支持flv格式

    html5的video标签只支持mp4.webm.ogg三种格式,不支持flv格式,在使用video.js时,如果使用html5是会报错不支持. 修改了一下代码 js部分 videojs.option ...

  8. Kindle支持哪些格式

    官方产品介绍页面有相关技术参数: Kindle Format 8 (AZW3), Kindle (AZW), TXT,PDF, MOBI, PRC原格式,HTML,DOC,DOCX,JPEG,GIF, ...

  9. c# 播放器 支持所有格式

    原文:c# 播放器 支持所有格式 ---恢复内容开始--- 直接上代码 internal static class LibVlcAPI { internal struct PointerToArray ...

随机推荐

  1. 设置button不同状态下的背景色,即把这个颜色变成图片设置成,背景图片

    - (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state { [self setBack ...

  2. pyenv 以及 virtualenv

    244 pyenv global 3.5.1 245 which python 246 python 247 pip install virtualenv 248 ls 249 pwd 250 ls ...

  3. git配置global信息

    git 执行提交时,提示用户输入用户和邮箱 git commit -m '*add newCat file' newCat/ *** Please tell me who you are. Run g ...

  4. Android 将可以按地点自动启动应用程序

    导读Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发.尚未有统一中文名称,中国大陆地区较多人使用“安 ...

  5. unity3d 截屏

    原地址:http://www.cnblogs.com/88999660/archive/2013/01/21/2869747.html void OnGUI(){ if(GUI.Button(new ...

  6. UIScrollview使用

    改变内容偏移 - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;  // animate at const ...

  7. iOS UILabel圆角

    对于UIView 直接设置 uiview.layer.cornerRadius = 5 就可以有圆角了 但是对于UILabel则不然, 要多设置一个uilabel.clipsToBounds = YE ...

  8. MySQL sql语句总结

    1.说明:创建数据库CREATE DATABASE database-name2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备份数据的 d ...

  9. KBS2 SBS MBC 高清播放地址 + mplayer 播放 录制

    网页flash播放KBS2 SBS MBC时占CPU资源太高,为了解决这个问题可以使用 mplayer播放器直接播放,还可以录制. 播放命令 mplayer http://pull.kktv8.com ...

  10. ubuntu dpkg 命令详解

    linux的包管理有多种,除了rpm,apt等还有优秀的dpkg,下面是dpkg命令的详细使用教程,希望对你有用.deb包的管理是比较优秀的包管理工具,用的linux系统有 debian ubuntu ...