修改stb_image.c以让Duilib直接支持Ico格式的图标显示
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格式的图标显示的更多相关文章
- Photoshop支持ico输出
1.Photoshop支持ico格式插件下载:ICOFormat.8bi 2.把文件放到ps安装目录:xxx/Plug-ins/File Formats 下 3.重启下ps
- Duilib 修改程序exe、在任务栏以及任务管理器上的图标
参考:https://blog.csdn.net/Rongbo_J/article/details/47379997 https://www.cnblogs.com/happinessda ...
- 扩展GDAL,支持CNSDTF格式(一)
扩展GDAL,支持CNSDTF格式(一) 一. 简介 本文主要根据<中华人民共和国国家标准GB/T17798-2007--地理空间数据交换格式(Geospatialdata tra ...
- 配置iis支持.json格式的文件
配置iis支持.json格式的文件发现要让IIS支持json文件并不是单纯的添加mime这么简单啊,以下是设置方法:一.IIS 6 1. MIME设置:在IIS的站点属性的HTTP头设置里,选MIME ...
- VMware ESXi 不支持NTFS格式的USB外接硬盘
本来想搞直通USB外接大容量硬盘(希捷Seagate Backup+ Hub WH 8T),实现在同一部ESXi下,直接将NAS的数据转移到外接硬盘.结果发现虚拟机下的win server系统识别不了 ...
- FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库
FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库:1. 安装faad2 # wget http://downloads.sourceforge.net/fa ...
- 使用video.js支持flv格式
html5的video标签只支持mp4.webm.ogg三种格式,不支持flv格式,在使用video.js时,如果使用html5是会报错不支持. 修改了一下代码 js部分 videojs.option ...
- Kindle支持哪些格式
官方产品介绍页面有相关技术参数: Kindle Format 8 (AZW3), Kindle (AZW), TXT,PDF, MOBI, PRC原格式,HTML,DOC,DOCX,JPEG,GIF, ...
- c# 播放器 支持所有格式
原文:c# 播放器 支持所有格式 ---恢复内容开始--- 直接上代码 internal static class LibVlcAPI { internal struct PointerToArray ...
随机推荐
- std::bind(二)
bind - boost 头文件: boost/bind.hpp bind 是一组重载的函数模板. 用来向一个函数(或函数对象)绑定某些参数. bind的返回值是一个函数对象. 它的源文件太长了. 看 ...
- zabbix 邮件报错 Support for SMTP authentication was not compiled in
服务器系统是centos6.5 zabbix版本是3.0.4 根据 网上教程配置好邮件脚本后,触发发送邮件的时候报错: Support for SMTP authentication was not ...
- Visual Studio Online Integrations-Planning
原文:http://www.visualstudio.com/zh-cn/explore/vso-integrations-directory-vs
- How can I style a JavaFX SplitMenuButton in CSS
0 down vote favorite I try to style a SplitMenuButton in JavaFX. I've got a menuButton and a SplitMe ...
- C++编程思想重点笔记(下)
上篇请看:C++编程思想重点笔记(上) 宏的好处与坏处 宏的好处:#与##的使用 三个有用的特征:字符串定义.字符串串联和标志粘贴. 字符串定义的完成是用#指示,它容许设一个标识符并把它转化为字符串, ...
- 微信公众平台开发(十) 消息回复总结——用其xml模板
一.简介 微信公众平台提供了三种消息回复的格式,即文本回复.音乐回复和图文回复,在这一篇文章中,我们将对这三种消息回复的格式做一下简单讲解,然后封装成函数,以供读者使用. 二.思路分析 对于每一个PO ...
- HNU 12827 NASSA’s Robot
题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12827&courseid=268 #include&l ...
- unity3d中资源文件从MAX或者MAYA中导出的注意事项
原地址:http://blog.sina.com.cn/s/blog_6ad33d3501011ekx.html 之前在项目中,没有怎么接触过美术的软件(之前的美术团队很犀利,被他们宠坏了).在自己公 ...
- crontab添加定时任务
(这些文章都是从我的个人主页上粘贴过来的,大家也可以访问我的主页 www.iwangzheng.com) crontab是LINUX系统下的定时任务触发器,常用的方法如下: crontab -l ...
- next_permutation 和 一个不成功的案例
一个失败的案例:(POJ 1009) 题目描述 小翔同学的宿舍WIFI添加了密码,密码每天都会变更.而小翔每天都会给蹭网的同学们提供密码提示.现在请你根据密码提示,编写程序破译密码. 已知密码提示给出 ...