不用第三方解码码取得图片宽高 附完整C++算法实现代码
在特定的应用场景下,有时候我们只是想获取图片的宽高,
但不想通过解码图片才取得这个信息。
预先知道图片的宽高信息,进而提速图片加载,预处理等相关操作以提升体验。
在stackoverflow有一篇相关讨论。
Get Image size WITHOUT loading image into memory
http://stackoverflow.com/questions/15800704/python-get-image-size-without-loading-image-into-memory/
不加图片到内存,而取得图像的大小。
这个技巧具有一定的实用价值,博主据此进行了相应的编码。
实现了 常用图片格式(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);
完整代码:
#include <stdio.h>
#include <sys/stat.h>
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) {
)) - (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/
// 博客: http://tntmonks.cnblogs.com/
// 邮箱: gaozhihan@vip.qq.com
bool get_image_size_without_decode_image(const char* file_path, int*width, int*height)
{
bool has_image_size = false;
*height = -;
*width = -;
;
FILE * fp = fopen(file_path, "rb");
if (fp == NULL)
return has_image_size;
struct stat st;
];
)
{
fclose(fp);
return has_image_size;
}
else
{
file_size = st.st_size;
}
, , fp) < )
{
fclose(fp);
return has_image_size;
}
char* png_signature = "\211PNG\r\n\032\n";
unsigned ] = { 'I', 'H', 'D', 'R' };
char* gif87_signature = "GIF87a";
char* gif89_signature = "GIF89a";
char* jpeg_signature = "\377\330";
char* bmp_signature = "BM";
) && (memcmp(sigBuf, gif87_signature, strlen(gif87_signature)) == || memcmp(sigBuf, gif89_signature, strlen(gif89_signature)) == ))
{
// image type: gif
unsigned );
*width = size_info[];
*height = size_info[];
has_image_size = true;
}
) && (memcmp(sigBuf, png_signature, strlen(png_signature)) == && memcmp(sigBuf + , ihdr_signature, strlen(ihdr_signature)) == ))
{
// image type: png
unsigned );
*width = byteswap_ulong(size_info[]);
*height = byteswap_ulong(size_info[]);
has_image_size = true;
}
) && (memcmp(sigBuf, png_signature, strlen(png_signature)) == ))
{
// image type: old png
unsigned );
*width = byteswap_ulong(size_info[]);
*height = byteswap_ulong(size_info[]);
has_image_size = true;
}
) && (memcmp(sigBuf, jpeg_signature, strlen(jpeg_signature)) == ))
{
// image type: jpeg
fseek(fp, , SEEK_SET);
;
fread(&sigBuf, , , fp);
fread(&b, , , fp);
;
;
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 ;
fread(&chunk_size, , , fp);
, SEEK_CUR) != )
break;
}
fread(&b, , , fp);
}
&& h != -)
{
*width = w;
*height = h;
}
has_image_size = true;
}
) && (memcmp(sigBuf, bmp_signature, strlen(bmp_signature)) == ))
{
// image type: bmp
unsigned ));
)
{
unsigned );
*width = size_info[];
*height = size_info[];
}
)
{
unsigned );
*width = size_info[];
*height = Abs((size_info[]));
}
has_image_size = true;
}
)
{
// image type: ico
fseek(fp, , SEEK_SET);
unsigned ;
unsigned ;
fread(&reserved, , , fp);
fread(&format, , , fp);
&& format == )
{
unsigned ;
fread(&num, , , fp);
)
{
printf("ico 包含多个图片");
}
else
{
, 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;
}
调用方法:
const char* file_path = "d:\\test.png";
int h, w;
get_image_size_without_decode_image(file_path , &w, &h);
传入图片的位置,输出对应的宽高,高和宽 为-1时,就是解析失败了。
代码比较简单,不多注释了。
若有其他相关问题或者需求可以邮件联系俺探讨。
邮箱地址是:
gaozhihan@vip.qq.com
不用第三方解码码取得图片宽高 附完整C++算法实现代码的更多相关文章
- 不用第三方解码库取得图片宽高 附完整C++算法实现代码
在特定的应用场景下,有时候我们只是想获取图片的宽高, 但不想通过解码图片才取得这个信息. 预先知道图片的宽高信息,进而提速图片加载,预处理等相关操作以提升体验. 在stackoverflow有一篇相关 ...
- JS快速获取图片宽高的方法
快速获取图片的宽高其实是为了预先做好排版样式布局做准备,通过快速获取图片宽高的方法比onload方法要节省很多时间,甚至一分钟以上都有可能,并且这种方法适用主流浏览器包括IE低版本浏览器. 我们一步一 ...
- 转载:JS快速获取图片宽高的方法
快速获取图片的宽高其实是为了预先做好排版样式布局做准备,通过快速获取图片宽高的方法比onload方法要节省很多时间,甚至一分钟以上都有可能,并且这种方法适用主流浏览器包括IE低版本浏览器. 我们一步一 ...
- JS实现图片宽高的等比缩放
关于图片宽高的等比缩放,其实需求就是让图片自适应父容器的宽高,并且是等比缩放图片,使图片不变形. 例如,需要实现如下的效果: 要实现上面的效果,需要知道图片的宽高,父容器的宽高,然后计算缩放后的宽高. ...
- php 图片上传的公共方法(按图片宽高缩放或原图)
写的用于图片上传的公共方法类调用方法: $upload_name='pic';$type = 'logo_val';$file_name = 'logo_' . $user_id .create_st ...
- css3圆形头像(当图片宽高不相等时)
1.图片宽高相等,width:300px: height:300px; 把他变成宽高100px的圆形头像 img{width:100px; height:100px; border-radius:50 ...
- js不需要知道图片宽高的懒加载方法(经过实际测试,不加宽高仍然是无法正常加载的,设置height:auto,height:100%,仍然显示高度为0)
js不需要知道图片宽高的懒加载方法 懒加载是如何实现的? - 简书https://www.jianshu.com/p/e86c61468285找到一个不需要知道图片宽高的懒加载方法了(经过实际测试,不 ...
- css+background实现 图片宽高自适应,拉伸裁剪不变形
图片宽高不固定 ,一样实现自适应,拉伸裁剪不变形,适应各大兼容性. 下面咱们在网上找两张宽高不一样的照片: No.1 ...
- 写个js动态调整图片宽高 (原创)
<body style="TEXT-ALIGN: center;"> <div id="testID" style="backgro ...
随机推荐
- RESTClient调试POST方法&Reflector+de4dot反混淆破解dll
RESTClient调试POST方法 RESTClient是火狐的一款WebAPI测试工具. 1.先看下我们要调试的接口
- Libevent源码分析 (1) hello-world
Libevent源码分析 (1) hello-world ⑨月份接触了久闻大名的libevent,当时想读读源码,可是由于事情比较多一直没有时间,现在手头的东西基本告一段落了,我准备读读libeven ...
- 栈和队列数据结构的相互实现[LeetCode]
栈是先进后出,队列是先进后出,这里讨论一下两种数据结构之间的相互实现. 一.用两个栈实现队列 我们用一个栈来实现队列的进队操作(栈A),用另一个栈来实现队列的出队操作(栈B). 1.入队列: 把元素放 ...
- python 将文件夹内的图片转换成PDF
import os import stringfrom PIL import Imagefrom reportlab.lib.pagesizes import A4, landscapefrom re ...
- bzoj 4813: [Cqoi2017]小Q的棋盘
Description 小Q正在设计一种棋类游戏.在小Q设计的游戏中,棋子可以放在棋盘上的格点中.某些格点之间有连线,棋子只能 在有连线的格点之间移动.整个棋盘上共有V个格点,编号为0,1,2-,V- ...
- HDFS租约实践
一.租约详解 Why租约 HDFS的读写模式为 "write-once-read-many",为了实现write-once,需要设计一种互斥机制,租约应运而生租约本质上是一个有时间 ...
- Java NIO (一) 初识NIO
Java NIO(New IO / Non-Blocking IO)是从JDK 1.4版本开始引入的IO API , 可以替代标准的Java IO API .NIO与原来标准IO有同样的作用和目的,但 ...
- php 理解
<?php class t { var $num; var $dynamic_function; public function dynamic_function() { $func = $th ...
- tomcat 设置jvm 参数
在catalina.bat中设置 正确的做法是设置成这样set JAVA_OPTS=%JAVA_OPTS% -Xms256m -Xmx256m,避免JAVA_OPTS参数覆盖
- php gif处理
http://www.jb51.net/article/51702.htm https://github.com/Sybio/GifCreator https://github.com/Sybio/G ...