不用第三方解码码取得图片宽高 附完整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 ...
随机推荐
- go实例之排序
1.默认排序 使用sort包进行排序.排序是就地排序,因此它会更改给定的切片,并且不返回新的切片. package main import "fmt" import "s ...
- Spring(概念)
在本文中只讲述一些概念性的东西,因为我在开始学习JAVA的时候对这些概念性的东西总是不太理解,总结总结再感悟一下,也方便后人. 理解的不深,用通俗的语言讲一下: 百度百科这样介绍: spring框架主 ...
- SuperSocket 最基础入门
---恢复内容开始--- SuperSocket 是什么? 首先我们明确一下SuperSocket 本质是什么? 网络框架 ! ok , 那么我们直接上上官网,作者已经开源到Github,可以做两件 ...
- NOI2009 植物大战僵尸
啊一道好题感觉写得挺爽的啊这题这种有一点懵逼然后学了一点东西之后很明朗的感觉真是好!预处理参考 :http://www.cppblog.com/MatoNo1/archive/2014/11/01/1 ...
- oracle自动备份_expdp_Linux
[oracle@hbsjxtdb1 ~]$ crontab -e 0 4 * * * /backup/script/backupexpdp.sh [oracle@hbsjxtdb1 ~]$ cront ...
- Struts2-整理笔记(一)介绍、搭建、流程、详解struts.xml
Struts2是一种前端的技术框架 替代Servlet来处理请求 Struts2优势 自动封装参数 参数校验 结果的处理(转发|重定向) 国际化 显示等待页面 表单的防止重复提交 搭建框架:导 ...
- Java语言的概述?-什么是Java? (附一张Java工程师的学习路线图)
什么是Java? Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语言具有功能强大和简单易用两个特征.Java语言作为静态面向 ...
- Windows 7样式地址栏(Address Bar)控件实现
介绍 从Vista开始,地址栏就有了很大的改变,不知道大家有什么感觉,笔者觉得很方便,同时又兼容之前的功能,是个很不错的创新.不过,微软并不打算把这一很酷的功能提供给广大的开发人员. 本文提供了一个简 ...
- 关于linux命令ssh的总结
因为项目计算量比较大,需要将任务分布到多台电脑上面运行,因为对于分布式概念不熟,就想到了linux最简单的ssh协议,远程控制其他电脑,然后写shell脚本统一在所有电脑上运行程序.(我的操作系统为U ...
- Nginx 学习笔记(七)如何解决nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
出现:nginx: [emerg] bind() to [::]:80 failed (98: Address already in use) 错误,有以下两种情况 1.80端口被占用 2.ipv4端 ...