简单的图像调整大小库
一个简单的库,用于管理和缩放上传的图片。
引言
我似乎经常需要处理很多与图片相关的事情,特别是动态缩放图片的问题——所以我决定编写一个库,让这个过程尽可能简单。
背景
这个库的目标是易于使用,并且足够灵活,无论你如何存储图片(文件系统、数据库、亚马逊网络服务等),都可以使用它。至于哪种存储图片的方式“最好”的讨论,我将留给其他人。然而,无论你选择哪种方式,仍然有一些共同的事情需要考虑:缩放图片并保持纵横比、文件名唯一性等。
使用代码
我通常会尝试 **不** 在创建这种简单的库时添加额外的对象——但在这种情况下,我认为它实际上可能会有帮助。要缩放图片,有时需要很多信息:图像流、内容类型、期望的宽度或高度等。因此,与其创建带有大量参数的方法,这个库将使用 ImageInfo
对象,该对象为我们保存了大部分信息。我还将一些方法拆分到两个“管理器”类中:WebManager
和 FileManager
。如果你在代码隐藏页面上使用这个库,那么“WebManager
”对象可能是最好的选择——否则,你将使用“FileManager
”类。
最棒的是,你可以覆盖或继承几乎任何东西,所以你可以根据自己的具体情况进行修改。
附带的演示项目包含了这里描述的所有示例,以及一个包含该库的独立项目。
示例:保存上传的图片及其缩放版本
在第一个示例中,我们假设刚刚发布了一个 ASPX 页面,并使用 FileUpload
控件选择了要上传的图片。这段代码放在 ButtonSubmit_Click
方法中。
//use WebManager to get the file, and save it
IImageInfo img = WebManager.GetImageInfo(fileUploader);
img.Path = "uploadedImages";
img.Save();
//now create resized versions, and save them
IImageInfo imgLarge = img.ResizeMe(null, 300); //constrain to 300 pixels wide
imgLarge.Save("uploadedImages/large"); //save file in a folder named "large"
IImageInfo imgMedium = img.ResizeMe(185, null); //constrain to 185 pixels high
imgMedium.Save("uploadedImages/medium");
IImageInfo imgSmall = img.ResizeMe(null, 100); //constrain to 100 pixels wide
imgSmall.Save("uploadedImages/small");
IImageInfo imgTiny = img.ResizeMe(50, null); //constrain to 50 pixels high
imgTiny.Save("uploadedImages/tiny");
让我们逐行解释上面的示例。第一行调用 WebManager
类上的静态 GetImageInfo
方法。此方法接收 FileUpload
,填充一个使用 IImageInfo
接口的对象,其中包含上传图片的原始信息,并返回该对象。
IImageInfo img = WebManager.GetImageInfo(fileUploader);
下一行将 Path
设置为目录“uploadedImages”。这是我们希望将原始上传文件保存到的目录。**请注意,您必须调整此目录的权限,允许 .NET 进程写入。在我这里,我为三个用户授予了“修改”权限:IIS_WPG、ASPNET 和 IIS_IUSRS。
img.Path = "uploadedImages";
下一行简单地调用 ImageInfo
对象上可用的 Save
方法。由于我们没有传递任何参数,此方法将使用其现有的文件名保存上传的图片。
img.Save();
下一行使用 ImageInfo
类上可用的 ResizeMe
方法来缩放它包含的图片,然后返回一个包含缩放后图片的新 ImageInfo
对象。ImageInfo
对象包含与原始图片相同的所有信息(路径、文件名等),但 PhotoStream
、Width
和 Height
被设置为缩放后的图片尺寸。ResizeMe
方法接受两个可空整数:maxHeight
和 maxWidth
。在这种情况下,我们只关心宽度为 300 像素——所以我们可以将 maxHeight
设置为 null
(或 0)。同时设置 maxHeight
和 maxWidth
参数将缩放图片,使其不会超过 maxHeight
或 maxWidth
。它 **不会** 将图片缩放到指定的 maxHeight
和 maxWidth
的确切尺寸——它仍然会保持正确的纵横比。在下面的示例中,我们将 maxHeight
传递为 null
,将宽度设置为 *300*,结果是宽度为 300 像素的缩放图片。
IImageInfo imgLarge = img.ResizeMe(null, 300);
下一行再次调用 Save
方法,但这次我们传递了我们想要保存图片的路径。在这种情况下,我们希望缩放后的图片位于“uploadedImages/large”目录中。
imgLarge.Save("uploadedImages/large");
(**注意:我们也可以在 imgLarge
变量的现有 Path
属性前加上“/large”,如下图所示,然后调用 Save()
)
imgLarge.Path += "/large";
下一节执行与上面相同的缩放操作,但这次通过设置 maxHeight
而不是 maxWidth
来缩放图片。
IImageInfo imgMedium = img.ResizeMe(185, null);
imgMedium.Save("uploadedImages/medium");
好了,这就是基本示例。然而,你并不总是以这种方式保存图片;很多时候,它们需要与数据库中的特定记录关联,或者以特定的方式命名。让我们看看在其他一些情况下我们可以怎么做。
其他示例
在下面的代码示例中,我们将首先将图片指针保存在数据库中,然后使用新的 ID 作为图片文件名。
//get uploaded image
IImageInfo img = WebManager.GetImageInfo(fileUploader);
string[] fileNameParts = img.FileName.split('.');
string fileExtension = fileNameParts.GetValue((fileNameParts.Length - 1));
Photo p = new Photo();
p.ProductID = 1; //tie it to a product
p.Path = "uploadedImages/photos";
p.Description = "Left side view";
p.FileExtension = fileExtension;
ProductRepository.Save(p);
int newID = p.PhotoID;
img.Path = p.Path;
img.FileName = string.Format("{0}.{1}", newID.ToString(), p.FileExtension);
img.Save();
//save thumbnail versions
img.ResizeMe(null, 185).Save(p.Path += "/large");
img.ResizeMe(null, 100).Save(p.Path += "/medium");
img.ResizeMe(null, 50).Save(p.Path += "/small");
上面的示例展示了当保存产品照片时,这个库如何使事情变得更简单。在该示例中,我们首先将记录保存到数据库,然后使用记录创建时生成的唯一 ID 将图片保存到文件系统。现在,当我们想显示这张产品照片时,我们只需指向“uploadedImages/photos/[PhotoID].[FileExtension]”文件。如果需要较小的图片,只需指向“large”、“medium”或“small”子文件夹下的图片。
那么,根据上面的示例,如果我们想删除一个照片怎么办?最好能同时从文件系统中删除原始图片以及生成的所有缩略图。幸运的是,我们可以通过几种不同的方式来做到这一点。要删除上面示例中创建的图片,你可以这样做:
Photo p = PhotoRepository.GetPhotoByID(id);
//first, delete the images
string[] pathsToDeleteFrom = new string[] { p.Path, p.Path +=
"/large", p.Path += "/medium", p.Path += "/small" };
WebManager.DeleteImageSetFromFileSystem(string.Format("{0}.{1}",
p.PhotoID.ToString(), p.FileExtension), pathsToDeleteFrom);
//now delete the database record
PhotoRepository.Delete(p);
DeleteImageSetFromFileSystem
方法接收文件名和要从中删除该文件的路径(目录)的字符串数组。因此,在此示例中,该照片的 PhotoID
文件名将从字符串数组中的每个路径中删除。
结论
好了,这就是对该库的快速概览。希望你觉得它很有用。我希望将来能更新更多功能,并在发布时在此处发布。
非常欢迎任何反馈/建议!