一个简单的 C# 图片缩放模块 —— Less.Image

原创 2017年06月14日 12:01:30

对于 web 项目来说,对图片进行不同尺寸的缩小是必须的。

如果你编写过支持 IE6 的 web 项目,你会记得 IE6 对图片的缩放效果是很差的,要禁止你的图片被浏览器缩放,就要在服务端先把图片缩放到适合的尺寸。现在 IE6 基本被淘汰了,但是为了页面的加载速度,你还是要在服务器端把图片缩小。特别是现在很多人用移动流量浏览网页,为了节省用户的流量费,也要在服务器端把图片缩小,最好服务器端响应的图片,大小和在浏览器呈现的是一样的。

大约在七八年前,我写了一些服务器端缩放图片的代码。现在修改一下开源出来。

取一张测试用的原图,尺寸为 600×721:

读取图片:

Image origin = Image.FromFile(file);

把图片调整为 300×200:

Image test1 = origin.Resize(300, 200);

效果如下:

Resize 方法的这个重载无论指定什么样尺寸,都不会对图片进行裁剪,而是使用填充的方法,自动计算在宽度上填充还是在高度上填充。上面的例子是在宽度上填充的。如果不想这样,可以使用另一个重载:

Image test2 = 
    origin.Resize(300, 200, ResizeMode.WidthFirst);

效果如下:

这次同样是把图片调整为 300×200,但是使用了裁剪的方法。函数的第三个参数 ResizeMode 是一个 Resize 模式选项,有 ResizeMode.WidthFirst 宽度优先,和 ResizeMode.HeightFirst 高度优先两个选项。test2 选择了宽度优先,意思是不在图片的宽度做任何的裁剪和填充,如果调整后的图片和原图比例不同,只在图片的高度上做调整。test2 就在图片的高度上做了裁剪。如果 test2 选择高度优先,效果是和 test1 一样的,test1 函数是因为不能对图片做裁剪,而自动选择了高度优先。

这种缩放的方法是普遍用在 web 编程的服务端上面的,我看到的产品都会使用裁剪的方法,比如微信、微博。裁剪虽然会使图片“损失”了一部分,但对比起填充来说,可以让界面更好看,因为不会有没有意义的底色。

使用 Crop 方法可以指定使用裁剪:

Image test3 = origin.Crop(180, 180);

用现在流行的九宫格方法演示效果:

      
      
      

Less.Image 的裁剪算法是截取图片的中间部分的,因为大部分图片的主体都在中间,比如杨幂这张图片。微博有一种裁剪算法是截取图片的上部的,这是针对现在流行的高度特别大的图片的,比如图片式的长微博,连环画等。

如果对图片的宽高比没有要求,可以使用:

Image test4 = origin.ResizeW(300);

代码的意思是把图片调整成宽度 300 像素,效果如下:

这个方法是不会对图片进行裁剪或填充的,保留了原图的宽高比。当然,也可以只指定高度:

Image test5 = origin.ResizeH(200);

生成了一张高度 200 像素的图片:

Less.Image 还提供了较多的重载方法,比如定填充的底色,插值算法等。可以应付服务器端图片缩放的大部分情况。我写这些代码的时间比较早了,在这期间经过了很多测试,处理过数十万图片的批量缩放,在 Less.Image 的内部是不会发生内存泄露的。你知道,在 System.Drawing 命名空间下,很多类都是非托管的。

NuGet:
https://www.nuget.org/packages/Less.Image

本文代码:GitHub    码云

项目代码:GitHub    码云

Less.Image 还有两个缺点。一是缩放 gif 动画,处理后会剩下第一帧,失去了动画的效果;二是因为 windows 内置的 png 编码器并不能很好地压缩图片,所以对 png 进行缩放的话,图片占用空间会比较大。所以如果图片没有透明像素的话,最好使用 jpg。

如果大家有更好的想法,请与我联系。

一个简单通讯录的c#设计尝试

(1)主界面设计 通讯录的功能主要分为添加、查找、删除与修改这四个功能,因为查找和添加是最常用的功能,所以我把这两个功能单独列出来放到主界面上,把修改和删除合并成为在功能管理通讯录里,另外加上退出通...
  • ckpckp
  • ckpckp
  • 2014年07月10日 12:41
  • 1855

求C#源代码(实现图形的选中,放大,缩小功能)

 求C#源代码(实现图形的选中,放大,缩小功能).
  • liushanzhong
  • liushanzhong
  • 2007年04月22日 17:55
  • 563

写了一个简单的注册登录模块

写了一个注册登录的简单实现,首先要创建名为db的数据库,并包含名为user 的表create database db;use db;create table user (serial int unsi...
  • topfzy
  • topfzy
  • 2007年06月03日 08:04
  • 1762

华为机试题2016(一) 简单错误记录

一:简单错误记录 开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。 处理: 1.记录最多8条错误记录,对相同的错误记录(即文件名称和行号完全匹配)只记录一条,错误计数增加;(...
  • moli152_
  • moli152_
  • 2015年08月26日 19:29
  • 2353

开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。

开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。 处理: 1.记录最多8条错误记录,对相同的错误记录(即文件名称和行号完全匹配)只记录一条,错误计数增加;(文件所在的目录...
  • yuanmo7915
  • yuanmo7915
  • 2016年08月12日 16:23
  • 1521

C#实践—简单的事件设计

    对象之间的交互是通过消息传递来实现的,而事件就是对象发送的消息,用来发信号通知操作的发生。引发事件的对象叫做事件发送方,接收事件的对象叫做事件接收方。在事件通信中,事件发送方知道哪个对象或方法...
  • meteorlWJ
  • meteorlWJ
  • 2008年03月04日 12:32
  • 703

C#学习笔记之以指定的大小缩放图片

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D...
  • qq_29331365
  • qq_29331365
  • 2017年08月03日 10:04
  • 294

C#练习Array.Sort函数列出所有的进程与模块

using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; usi...
  • pukuimin1226
  • pukuimin1226
  • 2012年10月16日 09:26
  • 1408

写了个 Ping 模块 很实用!

今天周末,看见同事为写一个Ping程序着急,我就写了个Ping函数,呵呵,在这里贴出来,想要的同志可以“剪”去,算是我送给大家的一个小礼物!图:Ping通的情况图:Ping失败的情况下面是源代码(VB...
  • tanaya
  • tanaya
  • 2004年08月14日 11:45
  • 3017

用C#做个简单的登录界面

从左边的【工具箱】中向设计窗体拖放1个Label控件,然后在纵向复制1个Label控件,接着依次对2个Label控件的【Text】属性进行修改,分别修改为“用户名:"、“密码”。      从【工具箱...
  • yy15642766973
  • yy15642766973
  • 2016年11月15日 19:41
  • 3008
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一个简单的 C# 图片缩放模块 —— Less.Image
举报原因:
原因补充:

(最多只允许输入30个字)