在特定的应用场景下,有时候我们只是想获取图片的宽高,

但不想通过解码图片才取得这个信息。

预先知道图片的宽高信息,进而提速图片加载,预处理等相关操作以提升体验。

在stackoverflow有一篇相关讨论。

Get Image size WITHOUT loading image into memory
http://stackoverflow.com/questions/15800704/python-get-image-size-without-loading-image-into-memory/

不加图片到内存,而取得图像的大小。

这个技巧具有一定的实用价值,博主据此进行了相应的编码。

项目地址:https://github.com/cpuimage/image_size

实现了 常用图片格式(png,jpeg,ico,bmp,gif) 不采用第三方解码库,解析得到图像宽高的函数get_image_size_without_decode_image。

bool get_image_size_without_decode_image(const char* file_path, int*width, int*height,int *filesize);

完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <stdint.h> #if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/
#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
#endif /*_MSC_VER */ unsigned long byteswap_ulong(unsigned long i)
{
unsigned int j;
j = (i << );
j += (i << ) & 0x00FF0000;
j += (i >> ) & 0x0000FF00;
j += (i >> );
return j;
} inline int Abs(int x) {
return (x ^ (x >> )) - (x >> );
} unsigned short byteswap_ushort(unsigned short i)
{
unsigned short j;
j = (i << );
j += (i >> );
return j;
} //Get Image size WITHOUT loading image into memory
//ref: http://stackoverflow.com/questions/15800704/python-get-image-size-without-loading-image-into-memory/ bool get_image_size_without_decode_image(const char* file_path, int*width, int*height, int * file_size)
{
bool has_image_size = false;
*height = -;
*width = -;
*file_size = -;
FILE * fp = fopen(file_path, "rb");
if (fp == NULL)
return has_image_size;
struct stat st;
char sigBuf[];
if (fstat(fileno(fp), &st) < )
{
fclose(fp);
return has_image_size;
}
else
{
*file_size = st.st_size;
}
if (fread(&sigBuf, , , fp) < )
{
fclose(fp);
return has_image_size;
}
char* png_signature = "\211PNG\r\n\032\n";
char* ihdr_signature = "IHDR";
char* gif87_signature = "GIF87a";
char* gif89_signature = "GIF89a";
char* jpeg_signature = "\377\330";
char* bmp_signature = "BM";
if ((*file_size >= ) && (memcmp(sigBuf, gif87_signature, strlen(gif87_signature)) == || memcmp(sigBuf, gif89_signature, strlen(gif89_signature)) == ))
{
// image type: gif
unsigned short* size_info = (unsigned short*)(sigBuf + );
*width = size_info[];
*height = size_info[];
has_image_size = true;
}
else if ((*file_size >= ) && (memcmp(sigBuf, png_signature, strlen(png_signature)) == && memcmp(sigBuf + , ihdr_signature, strlen(ihdr_signature)) == ))
{
// image type: png
unsigned long* size_info = (unsigned long*)(sigBuf + );
*width = byteswap_ulong(size_info[]);
*height = byteswap_ulong(size_info[]);
has_image_size = true;
}
else if ((*file_size >= ) && (memcmp(sigBuf, png_signature, strlen(png_signature)) == ))
{
// image type: old png
unsigned long* size_info = (unsigned long*)(sigBuf + );
*width = byteswap_ulong(size_info[]);
*height = byteswap_ulong(size_info[]);
has_image_size = true;
}
else if ((*file_size >= ) && (memcmp(sigBuf, jpeg_signature, strlen(jpeg_signature)) == ))
{
// image type: jpeg
fseek(fp, , SEEK_SET);
char b = ;
fread(&sigBuf, , , fp);
fread(&b, , , fp);
int w = -;
int h = -;
while (b && ((unsigned char)b & 0xff) != 0xDA) {
while (((unsigned char)b & 0xff) != 0xFF)
{
fread(&b, , , fp);
}
while (((unsigned char)b & 0xff) == 0xFF) {
fread(&b, , , fp);
}
if (((unsigned char)b & 0xff) >= 0xC0 && ((unsigned char)b & 0xff) <= 0xC3)
{
fread(&sigBuf, , , fp);
fread(&sigBuf, , , fp);
unsigned short* size_info = (unsigned short*)(sigBuf);
h = byteswap_ushort(size_info[]);
w = byteswap_ushort(size_info[]);
}
else
{
unsigned short chunk_size = ;
fread(&chunk_size, , , fp);
if (fseek(fp, byteswap_ushort(chunk_size) - , SEEK_CUR) != )
break;
}
fread(&b, , , fp);
}
if (w != - && h != -)
{
*width = w;
*height = h;
}
has_image_size = true;
}
else if ((*file_size >= ) && (memcmp(sigBuf, bmp_signature, strlen(bmp_signature)) == ))
{
// image type: bmp
unsigned int header_size = (*(sigBuf + ));
if (header_size == )
{
unsigned short* size_info = (unsigned short*)(sigBuf + );
*width = size_info[];
*height = size_info[];
}
else if (header_size >= )
{
unsigned int* size_info = (unsigned int*)(sigBuf + );
*width = size_info[];
*height = Abs((size_info[]));
}
has_image_size = true;
}
else if (*file_size >= )
{
// image type: ico
fseek(fp, , SEEK_SET);
unsigned short format = -;
unsigned short reserved = -;
fread(&reserved, , , fp);
fread(&format, , , fp);
if (reserved == && format == )
{
unsigned short num = -;
fread(&num, , , fp);
if (num > )
{
printf("this is a muti-ico file.");
}
else
{
char w = , h = ;
fread(&w, , , fp);
fread(&h, , , fp);
*width = (int)((unsigned char)w & 0xff);
*height = (int)((unsigned char)h & 0xff);
}
}
has_image_size = true;
}
if (fp != NULL)
fclose(fp);
return has_image_size;
} int main(int argc, char ** argv) { const char * pic_file = "lookmanodeps.png";
int w = ;
int h = ;
int filesize = ;
get_image_size_without_decode_image(pic_file, &w, &h, &filesize);
printf("file:%s\nfilesize:%d\nwidth:%d\nheight%d\n", pic_file, filesize, w, h);
getchar();
}

传入图片的位置,输出对应的宽高,高和宽 为-1时,就是解析失败了。

代码比较简单,不多注释了。

若有其他相关问题或者需求可以邮件联系俺探讨。

邮箱地址是: 
gaozhihan@vip.qq.com

不用第三方解码库取得图片宽高 附完整C++算法实现代码的更多相关文章

  1. 不用第三方解码码取得图片宽高 附完整C++算法实现代码

    在特定的应用场景下,有时候我们只是想获取图片的宽高, 但不想通过解码图片才取得这个信息. 预先知道图片的宽高信息,进而提速图片加载,预处理等相关操作以提升体验. 在stackoverflow有一篇相关 ...

  2. JS快速获取图片宽高的方法

    快速获取图片的宽高其实是为了预先做好排版样式布局做准备,通过快速获取图片宽高的方法比onload方法要节省很多时间,甚至一分钟以上都有可能,并且这种方法适用主流浏览器包括IE低版本浏览器. 我们一步一 ...

  3. 转载:JS快速获取图片宽高的方法

    快速获取图片的宽高其实是为了预先做好排版样式布局做准备,通过快速获取图片宽高的方法比onload方法要节省很多时间,甚至一分钟以上都有可能,并且这种方法适用主流浏览器包括IE低版本浏览器. 我们一步一 ...

  4. php 图片上传的公共方法(按图片宽高缩放或原图)

    写的用于图片上传的公共方法类调用方法: $upload_name='pic';$type = 'logo_val';$file_name = 'logo_' . $user_id .create_st ...

  5. css3圆形头像(当图片宽高不相等时)

    1.图片宽高相等,width:300px: height:300px; 把他变成宽高100px的圆形头像 img{width:100px; height:100px; border-radius:50 ...

  6. JS实现图片宽高的等比缩放

    关于图片宽高的等比缩放,其实需求就是让图片自适应父容器的宽高,并且是等比缩放图片,使图片不变形. 例如,需要实现如下的效果: 要实现上面的效果,需要知道图片的宽高,父容器的宽高,然后计算缩放后的宽高. ...

  7. js不需要知道图片宽高的懒加载方法(经过实际测试,不加宽高仍然是无法正常加载的,设置height:auto,height:100%,仍然显示高度为0)

    js不需要知道图片宽高的懒加载方法 懒加载是如何实现的? - 简书https://www.jianshu.com/p/e86c61468285找到一个不需要知道图片宽高的懒加载方法了(经过实际测试,不 ...

  8. css+background实现 图片宽高自适应,拉伸裁剪不变形

    图片宽高不固定 ,一样实现自适应,拉伸裁剪不变形,适应各大兼容性.  下面咱们在网上找两张宽高不一样的照片:     No.1                                      ...

  9. 写个js动态调整图片宽高 (原创)

    <body style="TEXT-ALIGN: center;"> <div id="testID" style="backgro ...

随机推荐

  1. centos 7.0远程登录

    http://blog.csdn.net/e1219092641/article/details/79586476 linux在虚拟机上操作也是有许多不便之处的,但是远程登录的使用可以使操作简单不少, ...

  2. python全栈学习--day1

      计算机基础 CPU:中央处理器 内存:4GB,8GB,临时处理事务的地方,供给CPU数据. 硬盘:相当于电脑的数据库,存储着大量的数据,文件,电影等. 操作系统:执行者,支配所有关系 window ...

  3. 云计算--网络原理与应用--20171120--VLAN与三层交换机配置

    什么是VLAN及其配置 Trunk的原理与配置 三层交换机的基本配置 实验:配置一个三层交换机 一 VLAN 的概念及优势 VLAN(virtual local area network)就是虚拟局域 ...

  4. pjax实例demo(c#,iis)

    pjax 百度都是api 也没找到demo 自己写了一个 C#写的 需要iis架设 测试ie10 和 火狐 成功 ie10不要用兼容模式 不然不好使 iis 可以直接架设webDemo1文件夹(源码) ...

  5. 学号:201621123032 《Java程序设计》第7周学习总结

    1:本周学习总结 1.1:思维导图:Java图形界面总结 2:书面作业 2.1: GUI中的事件处理 2.1.1: 写出事件处理模型中最重要的几个关键词 事件:如鼠标单击,滑动,输入汉字等. 事件源: ...

  6. 转 Eclipse快捷键调试大全

    (1)Ctrl+M --切换窗口的大小(2)Ctrl+Q --跳到最后一次的编辑处(3)F2      ---重命名类名 工程名 --当鼠标放在一个标记处出现Tooltip时候按F2则把鼠标移开时To ...

  7. 201621123068 Week03-面向对象入门

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识点组织起来.请使用工具画出本周学习到的知识点及知识点之间的联系.步骤如下: 1.1 写出你 ...

  8. DistBlockNet:A Distributed Blockchains-Based Secure SDN Architecture for IOT Network

    现有问题 随着IOT中智能设备多样性和数目的增加,IOT的灵活性,效率,可用性,安全性和可扩展性的问题越来越明显. 实验目标 按照高适应性,可用性,容错性,性能,可靠性,可扩展性和安全性的设计原则,构 ...

  9. XCode Build Settings中几种Search Paths

    Header search path:去查找头文件的路径,同在在你需要使用第三方库的时候,在这里设置你的头文件路径目录,如图 <code><span class="str& ...

  10. 怎么去理解JAVA中类与对象的关系

    首先要明确,在现实生活中,每一个物体都有自己的基本特征,专业一点也可以说成是属性有些甚至还有一定的行为.例如 汽车的特征:有车门.有轮胎.颜色各一等等,行为:有行驶,开车门,开车灯,等等.有这些属性和 ...