文档章节

关于.net中获取图像缩略图的函数GetThumbnailImage的一些认识。

abcijkxyz
 abcijkxyz
发布于 2016/11/22 16:40
字数 1557
阅读 2
收藏 0
点赞 0
评论 0

  在很多图像软件中,打开一幅图像的时候都会显示其缩略图,在看图软件中这样的需求更为常见。如何快速的获取缩略图的信息并提供给用户查看,是个值得研究的问题。在我所研究过的图像格式中,只有JPG和PSD两种格式可能内嵌了图像自身的缩略图信息。

  在.net中,图像处理方面的内容主要是借助于GDI+的平板化API函数实现的。为了获取GDI+能支持的那几种格式的缩略图,可以调用Bitmap或者Image类的GetThumbnailImage函数。用Reflecor反编译后知道,这个函数的主要实现代码如下所示:

public Image GetThumbnailImage(int thumbWidth, int thumbHeight, GetThumbnailImageAbort callback, IntPtr callbackData) { IntPtr zero = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipGetImageThumbnail(new HandleRef(this, this.nativeImage), thumbWidth, thumbHeight, out zero, callback, callbackData); if (status != 0) { throw SafeNativeMethods.Gdip.StatusException(status); } return CreateImageObject(zero); }

  那么其实他也是直接调用GdipGetImageThumbnail函数。

    下面我们主要通过实验说说这个函数的实质和其可应用的场合以及不应该应用的场合。

  为了测试公平,我们选用VB6作为测试语言,这有两个原因:(1)因为VB6直接调用GDI+的API函数很方便,也可以降低.net中创建各种对象所用的时间。(2)我在C#中调用Bitmap.FromFile读取文件的时间比VB6中使用同样的API要慢很多,不知道为什么。

 

    结论1: 该函数首先判断图像是否内嵌了缩略图,如果有,则直接读取他,然后再将获得的缩略图缩放到用户调用时指定的大小。如果没有,则从图像数据中抽样填充到缩略图数据中,至于抽样算法,这个没有研究,也许是线性插值吧。

       验证前的准备工作: 

     (1)  一副4000*3000的数码照片,JPG格式,内嵌了缩略图信息(如何验证:可以用很多查看EXIF信息的软件查看),可在此处下载

       (2)  一副4000*3000的照片,JPG格式,没有内嵌缩略图信息(如何验证:可以用很多查看EXIF信息的软件查看),可在此处下载

       (3) 一副4000*3000的照片,Png格式,由于无法上传大于5MB的文件,请朋友自行用工具转换。

        对上述三幅图像进行获取缩略图的操作,具体代码如下:

 '第一步:加载图像
    Elapse = GetTickCount GdipLoadImageFromFile StrPtr(FileName), Bitmap Result = Result + "加载图像用时: " & GetTickCount - Elapse & " 毫秒。" + vbCrLf GdipGetImageWidth Bitmap, Width GdipGetImageHeight Bitmap, Height GetFitSize Width, Height, 600, 450, FitX, FitY, FitWidth, FitHeight '第二步:获取缩略图
    Elapse = GetTickCount GdipGetImageThumbnail Bitmap, FitWidth, FitHeight, Thumb Result = Result + "获取缩略图用时: " & GetTickCount - Elapse & " 毫秒。" + vbCrLf GdipCreateFromHDC Hdc, Graphics '第三步:绘制缩略图
    Elapse = GetTickCount GdipDrawImageRect Graphics, Thumb, FitX, FitY, FitWidth, FitHeight Result = Result + "绘制缩略图: " & GetTickCount - Elapse & " 毫秒。" + vbCrLf GdipDisposeImage Bitmap GdipDisposeImage Thumb GdipDeleteGraphics Graphics

     我们依次查看结果:

   

                                                            图1 : 内嵌了缩略图的JPG图像

   

                                    图2: 未内嵌缩略图的JPG图像

   

                                        图3: PNG图像

  上述缩略图的大小设置为600*450。

   通过上面3个测试结果图的比较,可以明显看到:  内嵌了缩略图的JPG图像获得最后的缩略图很模糊,但是速度相当的块,而未内嵌了缩略图的JPG图像以及PNG图像获得的缩略图非常的清晰,但是耗时很多。因此我们可以初步的判断如果内嵌了缩略图,则GdipGetImageThumbnail会直接从内嵌的数据中进行缩放。为了进一步验证这一点,我生成了一副缩略图和原图完全不配套的JPG图像,来验证这一点,可从此处下载:

     处理结果如下图:

   

      可见,执行速度还是不错的,缩略图的结果却是错误的,但是和我们嵌入的缩略图却是一致的。 

      附带说一个问题:不知道大家注意到没有,上述代码中  GdipLoadImageFromFile 函数执行的时间都很短,而基本相同的函数在C#的Bitmap.FromFile函数中对于上述测试图像都要200多ms,不知为什么,附上Bitmap.FromFile的源码:

public static Image FromFile(string filename, bool useEmbeddedColorManagement) { int num; if (!File.Exists(filename)) { IntSecurity.DemandReadFileIO(filename); throw new FileNotFoundException(filename); } filename = Path.GetFullPath(filename); IntPtr zero = IntPtr.Zero; if (useEmbeddedColorManagement) { num = SafeNativeMethods.Gdip.GdipLoadImageFromFileICM(filename, out zero); } else { num = SafeNativeMethods.Gdip.GdipLoadImageFromFile(filename, out zero); } if (num != 0) { throw SafeNativeMethods.Gdip.StatusException(num); } num = SafeNativeMethods.Gdip.GdipImageForceValidation(new HandleRef(null, zero)); if (num != 0) { SafeNativeMethods.Gdip.GdipDisposeImage(new HandleRef(null, zero)); throw SafeNativeMethods.Gdip.StatusException(num); } Image image = CreateImageObject(zero); EnsureSave(image, filename, null); return image; } 
View Code

     上述源码中多了一些错误处理的代码,但那些代码明显不会太耗时间。这也是我这里用VB6做测试的原因。

     结论2:GetThumbnailImage不适合于做快速的图像缩放预览之类的工作,但是却是选择单开单个图像预览时的好选择。

     由以上图片测试结果可以看出,GetThumbnailImage是无法胜任任意大小预览模式的,但是对于大哥图像预览时,大部分大小都只有160*120大小的预览窗口的图像,确实非常合适的。

    结论3:C#下的Bitmap或者Image类的GetThumbnailImage函数不适合于做预览工作,原因就是他不如我在VB6下工作的快,特别是对于那些已经内嵌了缩略图的图像。如果是用C#做,我可能会像类似于VB中这样,直接调用GDI+的API函数。 

  测试源码下载: http://files.cnblogs.com/Imageshop/ThumbNail.rar

   附在的说一下: JPG的EXIF信息中的缩略图格式其实也是JPG格式,这也可以看成为什么JPG内部不一定非要内嵌缩略图的原因,不然缩略图本身格式也是JPG,那缩略图里有要嵌入缩略图....想想吧,会出现什么。

    后记: 用了下美图秀秀,在打开8000*6000这样尺寸的JPG进行预览时,初次打开的速度就很快,没感觉到有延迟,并且图像质量还可以,这个的算法过程期待有高人指点下。

   

 

 ***************************作者: laviewpbt   时间: 2013.6.16    联系QQ:  33184777  转载请保留本行信息*************************

 

本文转载自:http://www.cnblogs.com/Imageshop/archive/2013/06/16/3138623.html

共有 人打赏支持
abcijkxyz
粉丝 60
博文 6196
码字总数 1876
作品 0
深圳
项目经理
怎样编写一个Photoshop滤镜(4) -- 在对话框上增加缩略图

在上一篇文章里,我们讲解了为滤镜添加术语资源,从而使我们的滤镜可以被PS的scripting system感知和描述,这样即友好支持了PS的“动作”面板。在这一篇文章中,我们将对此前的DEMO进行进一步...

hoodlum1980
2009/05/23
0
0
Python计算机视觉:第一章 图像处理基础

第一章 图像处理基础 1.1 PIL-Python图像库 1.2 Matplotlib库 1.3 NumPy库 1.3.3 直方图均衡化 1.4 SciPy模块 1.5 更高级的例子:图像降噪 1.1 PIL-Python图像库 PIL (Python Imaging Librar...

weixin_37773766
05/24
0
0
web实战:video结合canvas实现视频在线截图

给大家讲解下我前几天看到的一个有趣小demo:视频在线截图。以下是我修改和添加了新功能后的效果图: 是不是很酷,其实挺简单的,下面就给大家讲讲怎么弄哈。 这里主要分为三大块功能,首先是...

newbeehh
06/22
0
0
[发布] Photoshop 油画效果滤镜

    【原创性声明】本滤镜是我采用 PS SDK 开发而成,而滤镜的算法具体是由谁提出的可能不详,我是参考了 FilterExplorer 的源码(VC 6),本算法的主要参考来源是该项目中的 Filters.cp...

hoodlum1980
2011/01/15
0
0
用 HTML Canvas 创建一个图片浏览器

HTML 5 引入了新的的网页元素: 。Canvas 是一片空白的绘图区域,网页开发者可以利用 JavaScript 在该区域中自由地进行 2D 绘图。Canvas 可以用于渲染华丽的网页设计界面。本文通过一个详细的...

红薯
2009/12/13
4.5K
9
phpPHP创建创建jpg格式图片以及压缩图片_无需整理

其实是因为一些业务上的需求,所以需要对用户上传后的图片进行压缩,因为上传的图片比较大,显示的时候加载起来如果网速不给力的话就很吃力了,而且大图片也浪费空间,于是找了一下相关的资源...

辣条拌鱼翅
2015/01/01
0
0
WordPress 开启日志缩略图 以及不用插件的程序使用方法

很多 WordPress 主题,特别是那些杂志型的主题,会给每篇日志加上一张缩略图,这种展现方式一般用在首页,可能单独出现,或者和日志摘要一起。但是目前位置没有一个标准的方法去实现日志缩略...

李佳顺
2012/11/14
0
0
再来二十一段救命的PHP代码

PHP可阅读随机字符串 此代码将创建一个可阅读的字符串,使其更接近词典中的单词,实用且具有密码验证功能。 /** *@length - length of random string (must be a multiple of 2) **/ functio...

零点钟
2011/10/28
0
1
Android之如何获取视频或者图片的缩略图

import java.io.File; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.ThumbnailUtils; import android.os.B......

请叫我高级研发工程师
2013/12/16
0
0
结合ashx来在DataGrid中显示从数据库中读出的图片

作者:木子 http://blog.csdn.net/derny/ 下面利用ashx文件可以方便实现从数据库中读取图片并显示在datagrid当中 //---------------------------------------BindImage.aspx --------------...

晨曦之光
2012/03/09
68
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

设计神器 - 摹客设计系统上线了 | 晒出你的设计规范,赢iPad Pro!

在国内,设计规范也许还是个不太常用的概念,但是如果你正好有参与互联网公司的产品设计,你应该早就已经体会到设计规范的重要性了。UI设计师总是要花费大量的时间和精力向开发描述一大堆设计...

mo311
9分钟前
0
0
Thymeleaf 使用过程中的一些记录

Thymeleaf格式化时间: th:value="${#dates.format(gw.regDT,'yyyy-MM-ddHH:mm:ss')}" Thymeleaf select反选: <select id="status" name="status" th:field="${gw.status}" th:value="${gw.......

惊尘大人
12分钟前
0
0
istio源码分析之pilot-discovery模块分析

本文分析的istio代码版本为0.8.0,commit为0cd8d67,commit时间为2018年6月18日。 本文为Service Mesh深度学习系列之一: Service Mesh深度学习系列part1—istio源码分析之pilot-agent模块分...

xiaomin0322
17分钟前
0
0
数据库基本操作:增删改查及联表操作

所用软件:SQL Server Management Studio 首先第一步,建立一个表。在这里命名为T1。并在里面填入几条数据。如图: T1 一.查询 查询所有:select * from T1; 按条件查询:select * from T1 ...

小_橙_子
21分钟前
0
0
Crontab作业时间设置

今天,遇到这么一个题目,周一到周五的9:00-16:59之间,每隔两分钟将某个命令运行一次。给的答案是: */2 9-16 * * 1-5 /usr/sbin/somecommand dosomething 乍一看,这个答案不对,应...

大别阿郎
26分钟前
0
0
ES17-JAVA API文档管理

1.保存文档 可以通过json工具把java对象转换成json字符串进行保存,也可以通过内置的帮助类直接构建json格式 /** * 获取客户端 * * @return */public static TransportClie...

贾峰uk
27分钟前
0
0
Python代码规范和命名规范

前言 Python 学习之旅,先来看看 Python 的代码规范,让自己先有个意识,而且在往后的学习中慢慢养成习惯 一、简明概述 1、编码 如无特殊情况, 文件一律使用 UTF-8 编码 如无特殊情况, 文件头...

blackfoxya
30分钟前
0
0
联动滑动之一:NestScrollChild和NestedScrollingParent

NestScrollChild和NestedScrollingParent 吐槽一下开源中国竟然标题字数有限制 由于项目中使用了CoordinateLayout来解决联动以及实现炫酷的UI效果,那么必须就要研究一波源码了,毕竟知其然知...

JerryLin123
47分钟前
1
0
cloudera spark2.2 读写hbase

cloudera spark2.2 读写hbase 例子 host = 'bigdata-03,bigdata-05,bigdata-04'conf = { "hbase.zookeeper.quorum": host, "hbase.mapreduce.inputtable": "student1"}k......

osenlin
51分钟前
0
0
数据库规范化

转载自 一个小时学会MySQL数据库 地址:http://www.cnblogs.com/best/p/6517755.html 截取其中 1.4 部分 用于自己学习使用 感谢作者:张果 1.4、数据库规范化 经过一系列的步骤,我们现在终于...

十万猛虎下画山
52分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部