当前位置: 首页 > 编程日记 > 正文

ASP.NET将原始图片按照指定尺寸等比例缩放显示图片

网站上可能会有很多图片,比如产品图片等,而且他们可能大小不一,宽度和高度也不一定一样,有的很大有的很小。如果放在一张网页上,可能会破坏版面,但是如果强制让他们按照指定的宽度和高度显示,因为比例不同还会出现变形,显示效果很糟糕,还有最大的缺点是,文件尺寸丝毫没有变化,当图片很大的时候,用户想要看到图片,必须经过漫长等待下载图片,怎么办呢?

好,这里涉及到了缩略图,就像Windows中的缩略图查看一样,你所看到的是从原图按照1:1比例缩小的图片,而且满足规定在指定宽度和高度的范围内显示(如果图片填不满,就用空白)。缩略图不是原图,而是利用原图实时按照指定大小生成的,他的好处就是你可以充分控制缩略图的质量,宽度高度,文件大小也在合理的范围内,省去漫长等待。

本文将讨论如何生成缩略图,举一反三,又可以派生许多用处,比如,自己写一个验证码控件等。

1、理解对图片的请求和流
一般来说,我们用http://xxx/a.aspx对a.aspx网页请求。ASP.NET处理了网页以后,就把该网页的内容发送回浏览器。a.aspx的内容一般是含有超文本标记的文本文件流(Response.ContentType即输出流的 HTTP MIME 类型,默认值是“text/html”),这是谁都不会怀疑的。但是a.aspx不但能够返回这种平常的网页文本外,把它广义开来,它其实可以返回任何类型的流数据。而,我们只需要对Response对象进行操作即可改变输出流的内容。
把图像文件看作是一个二进制流,我们试图从一个图像文件创建了他的流对象,并且将流写入到Response.OutputStream中,这样图像文件就被发给了请求的浏览器。但是浏览器还必须要识别出这是一个图像文件,因此,在发送这个流之前,将Response.ContentType更改成这种图像文件的MIME类型。浏览器在收到这个流之后,调用相关的应用程序,图像就被显示在了浏览器上。虽然实际地址还是aspx结尾。
这样我们就能很好理解怎么去向用户发送标记。例如,在一张普通的网页中写img标签,使它的src指向a.aspx。浏览器在得到这张网页后,会处理img标签的内容,并向a.aspx发出请求,这时a.aspx作为图像流返回,浏览器就将图片显示出来。

2、生成缩略图

新建webform页面,它通过接受传入的参数,生成缩略图的流,发送回浏览器。cs代码如下:

using System;
using System.Drawing;
using System.Drawing.Imaging;namespace Demo.Web
{public partial class GetThumbnail : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){Response.Clear();string originalFileName =Server.MapPath( Request.QueryString["imgSrc"]);int thumbnailWidth = Convert.ToInt32(Request.QueryString["width"]);int thumbnailHeight = Convert.ToInt32(Request.QueryString["height"]);System.Drawing.Image img = System.Drawing.Image.FromFile(originalFileName);var thisFormat = img.RawFormat;System.Drawing.Size newSize = GetNewSize(thumbnailWidth, thumbnailHeight, img.Width, img.Height);var outBmp = new System.Drawing.Bitmap(thumbnailWidth, thumbnailHeight);var g = System.Drawing.Graphics.FromImage(outBmp);//设置画布的描绘质量g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;g.Clear(System.Drawing.Color.FromArgb(255, 249, 255, 240));//.Transparent);//.FromArgb(255, 249, 255, 240));g.DrawImage(img, new Rectangle((thumbnailWidth - newSize.Width) / 2,(thumbnailHeight - newSize.Height) / 2,newSize.Width, newSize.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);g.Dispose();if (thisFormat == System.Drawing.Imaging.ImageFormat.Gif){Response.ContentType = "image/gif";}else{Response.ContentType = "image/jpeg";} // 设置压缩质量     EncoderParameters encoderParams = new EncoderParameters();long[] quality = new long[1];quality[0] = 100;EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);encoderParams.Param[0] = encoderParam;//获得包含有关内置图像编码解码器的信息的ImageCodecInfo 对象。var arrayICI = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();System.Drawing.Imaging.ImageCodecInfo jpegICI = null;for (int fwd = 0; fwd < arrayICI.Length; fwd++){if (arrayICI[fwd].FormatDescription.Equals("JPEG")){jpegICI = arrayICI[fwd];break;}}if (jpegICI != null)outBmp.Save(Response.OutputStream, jpegICI, encoderParams);elseoutBmp.Save(Response.OutputStream, img.RawFormat);}private Size GetNewSize(int maxWidth, int maxHeight, int width, int height){double w = 0.0;double h = 0.0;double sw = Convert.ToDouble(width);double sh = Convert.ToDouble(height);double mw = Convert.ToDouble(maxWidth);double mh = Convert.ToDouble(maxHeight);if (sw < mw && sh < mh){w = sw;h = sh;}else if ((sw / sh) > (mw / mh)){w = maxWidth;h = (w * sh) / sw;}else{h = maxHeight;w = (h * sw) / sh;}return new System.Drawing.Size(Convert.ToInt32(w), Convert.ToInt32(h));}}
}

我们在Page_Load事件处理函数中,先获取要生成缩略图的原始文件的路径,和缩略图的宽度高度。
然后设置了一个子函数GetNewSize用以计算真正缩略图的大小(为什么还要计算阿?因为缩略图的宽高比和原始图片的宽高比不一样,缩小的图片要保证比例,按照比例缩小的原始图片,是按照约束在指定缩略图宽高范围内的原则,填充不满的地方使用背景色填补空白。另外,原图比缩略图小的话,我们就不做放大,而是按原图输出,所以计算是必须的)。

我们从原始图像创建了他的Image对象,并获得它的格式等信息,稍后用得到。

接下来新建一个BitMap对象,并由新的BitMap对象创建画板。设置画笔质量为高,交错模式为高质量立方式,这些的目的是使用最好的质量描绘缩略图,否则图片缩小后信息丢失图片失真就不好看了。接着,用指定的宽度和高度将原始图像的Image对象“画”在新的画板上。

修改Response.ContentType,这一步是告诉浏览器发送回的流的MIME类型,这个内容包含在HTTP Header中发送给浏览器。

图像画好了,现在我们要将其压缩一下,因为位图对象是很大的,不利于传输。因此下面的操作,我们设定一些高质量的压缩参数,根据获得的ICI(图像编码解码器信息),使用BitMap的Save方法将图片保存在Response.OutputStream流中。

这样在浏览器看来,对该网页的请求,相当于对一个图片文件的请求,只不过图片是实时生成的,只要传递参数合法有效,即可得到该图片的缩略图。

3、使用缩略图
使用缩略图就变得相对简单了,只需要在URL后附上参数imgSrc表示原始文件的位置(相对于根目录),width缩略图宽度,height缩略图高度,下列简单显示了在Repeater中使用的情景:

<img alt='' border="0" src='GetThumbnail.aspx?imgsrc=<%#Eval("ImgUrl") %>&width=300&height=300' />

下面就等着看看缩略图的效果:

后记
本文中所述的缩略图生成法,使用的是流的概念,和文件系统也不沾边,因此这种方式可以跳过对文件系统权限检查,百分之百正确运行。当然,也可以借助文件系统。另外,根据上面流输出的概念,举一反三,可以弄出很多用法,例如NeoDynamic的条形码控件,你会发现条形码图片的路径居然就是本页页面,他巧妙地将对本页的请求通过对几个特征参数的判定而转向生成图片流,从而达到了不添加任何页面,不借助文件系统的“神奇效果”,只需要一个DLL即可使用。
另外,很多人问生成验证码图片,也可以使用这样的思路,自己做一个这样的控件,或者网页。如果能做自定义控件更好。相信大家有这个能力。

转载于:https://www.cnblogs.com/buguge/p/5059679.html

相关文章:

前端开发框架选择

Vue Vant 适用场景&#xff1a;开发移动端 (vue) 上手难度&#xff1a;1 Vant是一款很好用的移动端UI框架&#xff0c;非常轻便&#xff0c;适合小型项目 https://vant-contrib.gitee.io/vant/#/zh-CN/ 微信小程序 适用场景&#xff1a;微信小程序&#xff08;小程序原生框架…

anki_Anki如何挽救我的工程生涯

ankiby Jeffrey Shek通过Jeffrey Shek Anki如何挽救我的工程生涯 (How Anki saved my Engineering Career) I was burned out and my software career was stalling just three years in. My memory sucked. Was my poor memory from stress, lack of sleep or was it always …

信息安全系统设计基础期末总结

【博客汇总】 一、每周读书笔记链接汇总 •[第二周读书笔记] http://www.cnblogs.com/20135302wei/p/4842480.html •[第三周读书笔记] http://www.cnblogs.com/20135302wei/p/4858760.html •[第四周读书笔记] http://www.cnblogs.com/20135302wei/p/4870113.html •[第五周读…

方法 retrun 异步的值,创建一个变量直接等于一个异步方法返回的值

需求&#xff1a;我想创建一个变量&#xff0c;他的值是一个openid&#xff0c; openid 从 getOpenid (封装的一个异步方法) 里面返回&#xff0c;通常调用 getOpenid ,会返回一个Promise 对象&#xff0c;.then 之后才能得到值&#xff0c;例如&#xff1a; //模拟一个异步方…

ps混合模式glsl代码

https://github.com/jamieowen/glsl-blend 转载于:https://www.cnblogs.com/guochen/p/7645227.html

应用程序启动器 标记为信任_为什么您今天不能信任应用程序-以及如何解决它...

应用程序启动器 标记为信任亲爱的每家高科技公司&#xff0c;请窃取这个想法 (Dear Every Single Tech Company, Please Steal This Idea) When you send a photo to someone, your messaging app actually first sends the photo to an app’s server, which then sends the p…

小程序客服自动回复图片,云开发的实现

小程序先开通云开发&#xff0c;创建一个文件夹&#xff0c;并配置为云函数的目录 小程序客服自动回复图片实现步骤&#xff1a; 1.云函数接收消息推送 第一步&#xff1a;开发者工具云开发控制台中增加配置 打开云开发控制台&#xff0c;到设置 tab 中选择全局设置 - 添加消…

ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务解决

方法1&#xff1a; a、通过oracle 工具 Net Configuration Assistant 重新配置监听&#xff0c;注意如果有双网卡请配置第一块网上IP。如何知道哪一块是一块网卡&#xff0c;可以通过ipconfig命令查看最上面的ip就是一块网卡的 b、通过Net Configuration Assistant 工具配置 “…

r语言 编辑 d3.js_d3.js的语言介绍

r语言 编辑 d3.jsby Matt Oxley由马特奥克斯利(Matt Oxley) d3.js的语言介绍 (A linguistic introduction to d3.js) 如何从一个试探者变成一个自信的用户 (How to go from a tentative to a confident user) d3.js is a fantastic library — but I can honestly tell you th…

【Luogu3041】视频游戏的连击(AC自动机,动态规划)

题面链接 题解 首先构建出AC自动机 然后在AC自动机上面跑DP 转移很显然从Trie树的节点跳到他的儿子节点 但是要注意一个问题&#xff0c; 在计算的时候&#xff0c;每一个节点加入后能够 造成的贡献 要加上他的子串的贡献 至于DP&#xff1a; 设f[i][j]表示已经使用了i个字母 当…

拥抱高效、拥抱 Bugtags 之来自用户的声音(三)

小编按&#xff1a;这是一篇 Bugtags 用户来稿&#xff0c;主要是介绍了使用 Bugtags 前后对测试及解决 Bug 所带来的变化&#xff0c;感谢山西农业大学 - 高正炎同学对 Bugtags 的信赖和支持。小编在这里诚邀各位热心用户向我们投稿&#xff0c;说出你使用 Bugtags 的故事。 0…

小程序打开文档标题乱码处理

先下载&#xff0c;自定义临时文件目录名称&#xff0c;然后再打开就可以了。 wx.downloadFile({url: https://xxx.cn/sfxy.docx, //仅为示例&#xff0c;并非真实的资源filePath: wx.env.USER_DATA_PATH /这是自定义标题.docx,success(res) {console.log(0, res)wx.openDocum…

我是“真正的”软件工程师吗?

by Sun-Li Beatteay通过孙丽贝蒂 我是“真正的”软件工程师吗&#xff1f; (Am I a “real” Software Engineer yet?) Am I a “real” Software Engineer yet?我是“真正的”软件工程师吗&#xff1f; This question has haunted me for years. And it seems I’m not al…

ntpdate[31915]: the NTP socket is in use, exiting

[rootmaster local]# ntpdate cn.pool.ntp.org 10 Oct 13:24:36 ntpdate[31915]: the NTP socket is in use, exitingcron 作业中运行 ntpdate&#xff0c;以便大约每隔一小时就设置一次本地时间。最近&#xff0c;我每次运行该命令时都会收到下列错误消息。 ntpdate[31915]: t…

小程序云开发更新数组的指定对象的值

云开发&#xff0c;在小程序实现 代码说明‘&#xff1a; 在这里&#xff0c;数据集合 groupList 中的 userList 是一个用户列表数组&#xff0c;我要更新数组中&#xff0c;openid 等于我的openid 的在线状态为 true。 先查询条件&#xff0c;集合里面的 _id 等于我传的id&a…

Unreal Engine 4 RenderTarget制作Live Camera效果

Unreal Engine 4 RenderTarget制作Live Camera效果 先上效果&#xff1a; Live Camera我不知道怎么翻译。反正意思就是将一个摄影机的Image渲染到一个2D平面上。 以下介绍下详细的实现方法&#xff1a; 1.创建一个Scene Capture 2D对象 将这个对象拖动到合适的地方。2.创建Re…

领导让我重构代码_领导不是由代码构成

领导让我重构代码The team leader is a key figure in a team of developers. It is a difficult role, involving both technical and social skills. This is the reason why not everyone is tailored for it.团队负责人是开发人员团队中的关键人物。 这是一项艰巨的任务&am…

Spring学习-理解IOC和依赖注入

最近刚买了一本介绍ssm框架的书&#xff0c;里面主要对Mybatis、spring、springmvc和redis做了很多的讲解&#xff0c;个人觉得虽然有的内容我看不懂&#xff0c;但是整体上还是不错的。最近正在学习中&#xff0c;一边学习一边做一些总结&#xff0c;现在我对这些思想技术还没…

windows server2012怎样关机怎样重启-详细教程

|浏览&#xff1a;1991|更新&#xff1a;2014-12-15 17:33123456分步阅读百度经验:jingyan.baidu.com windows server2012和以往有些不同&#xff0c;关机/重启按钮不是在左边&#xff0c;甚至左边的“开始”都不见了&#xff0c;那怎样关机/重启呢&#xff1f;这里开始演示&am…

封装 localStorage 缓存,兼容网页,微信小程序,uni-app

封装的缓存功能&#xff0c;兼容网页&#xff0c;微信小程序&#xff0c;uni-app 使用&#xff0c;支持设置缓存&#xff0c;获取缓存&#xff0c;移除缓存&#xff0c;清空缓存&#xff0c;设置缓存时间&#xff0c;分组缓存设置。 把最下面的 Str4.js 代码拷贝到项目内可以直…

考csp所需算法_CSP vs RxJS:您所不知道的。

考csp所需算法by Kevin Ghadyani通过凯文加迪亚尼(Kevin Ghadyani) CSP vs RxJS&#xff1a;您所不知道的。 (CSP vs RxJS: what you don’t know.) CSP发生了什么&#xff1f; (What happened to CSP?) You probably clicked this article thinking “what is CSP?” It’s…

iOS蓝牙4.0开发例子

1建立中心角色 123#import <CoreBluetooth/CoreBluetooth.h> CBCentralManager *manager; manager [[CBCentralManager alloc] initWithDelegate:self queue:nil]; 2扫描外设&#xff08;discover&#xff09; [manager scanForPeripheralsWithServices:nil options:…

Spark Shuffle原理解析

Spark Shuffle原理解析 一&#xff1a;到底什么是Shuffle&#xff1f; Shuffle中文翻译为“洗牌”&#xff0c;需要Shuffle的关键性原因是某种具有共同特征的数据需要最终汇聚到一个计算节点上进行计算。 二&#xff1a;Shuffle可能面临的问题&#xff1f;运行Task的时候才会产…

云开发使用 got 的 get/post 传参请求示例代码

使用 got 进行网络请求的步骤&#xff1a; 1.创建云函数&#xff0c;并在终端执行云函数 2.执行 npm 安装 got &#xff0c;命令&#xff1a;cnpm install --save got 3.在云函数中使用 示例代码&#xff1a; // 云函数入口文件 const cloud require(wx-server-sdk) cons…

JavaScript词法作用域的简单介绍

by Michael McMillan迈克尔麦克米兰(Michael McMillan) JavaScript词法作用域的简单介绍 (An easy intro to Lexical Scoping in JavaScript) Lexical scoping is a topic that frightens many programmers. One of the best explanations of lexical scoping can be found in…

Flex 布局详解 - 转自阮一峰老师

Flex 是 Flexible Box 的缩写&#xff0c;意为"弹性布局"&#xff0c;用来为盒状模型提供最大的灵活性。任何的盒子都可以使用它。 下面我们来看一下使用 Flex 布局的容器的属性 flex-direction flex-wrap flex-flow justify-content align-items align-content 1.…

bzoj 1086: [SCOI2005]王室联邦

Description “余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省&#xff0c;每个省都由他们王室联邦的一个成员来管理。他的国家有n个城市&#xff0c;编号为1..n。一些城市之间有道路相连&#xff0c;任意两个不同的城市之间有且仅有一条直接或间接的道路。为…

在7分钟内深刻理解咖喱

Eric Elliott’s exceptional Composing Software series is initially what got me excited about functional programming. Its a must-read. 埃里克埃利奥特(Eric Elliott)杰出的合成软件系列最初使我对函数式编程感到兴奋。 这是必读的。 At one point in the series, he …

github后端开发面试题大集合(一)

作者&#xff1a;小海胆链接&#xff1a;https://www.nowcoder.com/discuss/3614?type0&order0&pos5&page0?fromwb来源&#xff1a;牛客网 转载自github&#xff0c;中文--->链接在这&#xff0c;英文---->链接在这文章较长&#xff0c;我把它拆分了三个部…

微信小程序左滑删除效果的实现完整源码附效果图

效果图&#xff1a; 功能描述&#xff0c;小程序列表左滑删除功能的实现完整源代码实现&#xff1a; <view wx:for{{friends}} wx:key"" wx:if{{groupType4}} catchtap"nav_oneChat" id"{{item._id}}" class"item p_r" style"…