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

news/2024/7/5 1:38:02

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

好,这里涉及到了缩略图,就像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


http://lihuaxi.xjx100.cn/news/269855.html

相关文章

2011-11-27

大三&#xff0c;这个关键时刻&#xff0c;目前自己正在写软件课程设计程序-教材订购系统&#xff0c;加油&#xff01;努力&#xff01;转载于:https://blog.51cto.com/3122770/728090

SpringBoot最最最常用的注解梳理

点击上方蓝色“方志朋”&#xff0c;选择“设为星标”回复“666”获取独家整理的学习资料&#xff01;来源&#xff1a;https://s.yam.com/w6mfR一、注解(annotations)列表SpringBootApplication&#xff1a; 包含了ComponentScan、Configuration和EnableAutoConfiguration注解…

php开发之登录注册教程,PHP开发登录注册完整代码之注册PHP页面

创建我们的 reg.php 文件此页面完成的功能如下代码如下<?php session_start();header("Content-type:text/html;charsetutf-8");$link mysqli_connect(localhost,root,root,login);mysqli_set_charset($link,utf8); //设定字符集$name$_POST[name];$pwd$_POST[p…

抖音、快手和直播行业的火爆究竟给了谁机会?

经常收到一些CSDN小伙伴的留言&#xff0c;反馈如下这样的困惑“短视频这么火爆&#xff0c;我该学些什么技术才能入行&#xff1f;”“我想从事音视频开发&#xff0c;该如何入门和进阶&#xff1f;真的像坊间传闻的那么难吗&#xff1f;”音视频的开发前景做一个不恰当的比喻…

第一视角:深度学习框架这几年

点击上方“视学算法”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达‍‍‍‍‍‍‍‍作者 | Peter潘欣转自 | 夕小瑶的卖萌屋和深度学习框架打交道已有多年时间。从Google的TensorFlow, 到百度的PaddlePaddle&#xff0c;再到现在腾讯的无量。…

教程 | 基于LSTM实现手写数字识别

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达基于tensorflow&#xff0c;如何实现一个简单的循环神经网络&#xff0c;完成手写数字识别&#xff0c;附完整演示代码。01 LSTM网络构建基于tensorflow实现简单的LSTM网络…

C++11 带来的新特性 (2)—— 统一初始化(Uniform Initialization)

1 统一初始化&#xff08;Uniform Initialization&#xff09; 在C 11之前&#xff0c;所有对象的初始化方式是不同的&#xff0c;经常让写代码的我们感到困惑。C 11努力创造一个统一的初始化方式。 其语法是使用{}和std::initializer_list&#xff0c;先看示例。 int values[]…

《大话西游》20年后重映(附影评:《大话西游》你真的看懂了吗?)

2014-10-25 02:43:24 来源: 北京日报(北京)本报讯 &#xff08;记者 周南焱&#xff09;“电影里的台词差点儿都能背&#xff0c;但在影院里再看还是会笑。看到最后紫霞仙子死的时候。还是忍不住落泪&#xff01;”昨天下午&#xff0c;经典老片《大话西游》在海航活力天宝影城…