遇到一个场景 文件操作模块是其他同事编写 直接通过HttpPostedFileBase来保存图片 这边不能动原来的上传流程 原来上传的图片都是没有经过压缩 导致APP加载速度会很慢
图片压缩代码
参考自:https://github.com/zkweb-framework/ZKWeb/blob/master/ZKWeb/ZKWebStandard/Extensions/ImageExtensions.cs
using MyCompanyName.Extensions.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCompanyName.Extensions.Extensions
{
public static class ImageExtensions
{
/// <summary>
/// Resize image
/// </summary>
/// <param name="image">Original image</param>
/// <param name="width">Width</param>
/// <param name="height">height</param>
/// <param name="mode">Resize mode</param>
/// <param name="background">Background default is transparent</param>
/// <returns></returns>
public static Image Resize(this Image image,
int width, int height, ImageResizeMode mode, Color? background = null)
{
var src = new Rectangle(0, 0, image.Width, image.Height);
var dst = new Rectangle(0, 0, width, height);
// Calculate destination rectangle by resize mode
if (mode == ImageResizeMode.Fixed)
{
}
else if (mode == ImageResizeMode.ByWidth)
{
height = (int)((decimal)src.Height / src.Width * dst.Width);
dst.Height = height;
}
else if (mode == ImageResizeMode.ByHeight)
{
width = (int)((decimal)src.Width / src.Height * dst.Height);
dst.Width = width;
}
else if (mode == ImageResizeMode.Cut)
{
if ((decimal)src.Width / src.Height > (decimal)dst.Width / dst.Height)
{
src.Width = (int)((decimal)dst.Width / dst.Height * src.Height);
src.X = (image.Width - src.Width) / 2; // Cut left and right
}
else
{
src.Height = (int)((decimal)dst.Height / dst.Width * src.Width);
src.Y = (image.Height - src.Height) / 2; // Cut top and bottom
}
}
else if (mode == ImageResizeMode.Padding)
{
if ((decimal)src.Width / src.Height > (decimal)dst.Width / dst.Height)
{
dst.Height = (int)((decimal)src.Height / src.Width * dst.Width);
dst.Y = (height - dst.Height) / 2; // Padding left and right
}
else
{
dst.Width = (int)((decimal)src.Width / src.Height * dst.Height);
dst.X = (width - dst.Width) / 2; // Padding top and bottom
}
}
// Draw new image
var newImage = new Bitmap(width, height);
using (var graphics = Graphics.FromImage(newImage))
{
// Set smoothing mode
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
// Set background color
graphics.Clear(background ?? Color.Transparent);
// Render original image with the calculated rectangle
graphics.DrawImage(image, dst, src, GraphicsUnit.Pixel);
}
return newImage;
}
/// <summary>
/// Save to jpeg with specified quality
/// </summary>
/// <param name="image">Image object</param>
/// <param name="filename">File path, will automatic create parent directories</param>
/// <param name="quality">Compress quality, 1~100</param>
public static void SaveJpeg(this Image image, string filename, long quality)
{
PathUtils.EnsureParentDirectory(filename);
var encoder = ImageCodecInfo.GetImageEncoders().First(
c => c.FormatID == ImageFormat.Jpeg.Guid);
var parameters = new EncoderParameters();
parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
image.Save(filename, encoder, parameters);
}
/// <summary>
/// Save to icon, see
/// http://stackoverflow.com/questions/11434673/bitmap-save-to-save-an-icon-actually-saves-a-png
/// </summary>
/// <param name="image">Image object</param>
/// <param name="filename">File path, will automatic create parent directories</param>
public static void SaveIcon(this Image image, string filename)
{
PathUtils.EnsureParentDirectory(filename);
using (var stream = new FileStream(filename, FileMode.Create))
{
// Header (ico, 1 photo)
stream.Write(new byte[] { 0, 0, 1, 0, 1, 0 }, 0, 6);
// Size
stream.WriteByte(checked((byte)image.Width));
stream.WriteByte(checked((byte)image.Height));
// No palette
stream.WriteByte(0);
// Reserved
stream.WriteByte(0);
// No color planes
stream.Write(new byte[] { 0, 0 }, 0, 2);
// 32 bpp
stream.Write(new byte[] { 32, 0 }, 0, 2);
// Image data length, set later
stream.Write(new byte[] { 0, 0, 0, 0 }, 0, 4);
// Image data offset, fixed 22 here
stream.Write(new byte[] { 22, 0, 0, 0 }, 0, 4);
// Write png data
image.Save(stream, ImageFormat.Png);
// Write image data length
long imageSize = stream.Length - 22;
stream.Seek(14, SeekOrigin.Begin);
stream.WriteByte((byte)(imageSize));
stream.WriteByte((byte)(imageSize >> 8));
stream.WriteByte((byte)(imageSize >> 16));
stream.WriteByte((byte)(imageSize >> 24));
}
}
/// <summary>
/// Save image by it's file extension
/// Quality parameter only available for jpeg
/// </summary>
/// <param name="image">Image object</param>
/// <param name="filename">File path, will automatic create parent directories</param>
/// <param name="quality">Compress quality, 1~100</param>
public static void SaveAuto(this Image image, string filename, long quality)
{
PathUtils.EnsureParentDirectory(filename);
var extension = Path.GetExtension(filename).ToLower();
if (extension == ".jpg" || extension == ".jpeg")
{
image.SaveJpeg(filename, quality);
}
else if (extension == ".bmp")
{
image.Save(filename, ImageFormat.Bmp);
}
else if (extension == ".gif")
{
image.Save(filename, ImageFormat.Gif);
}
else if (extension == ".ico")
{
image.SaveIcon(filename);
}
else if (extension == ".png")
{
image.Save(filename, ImageFormat.Png);
}
else if (extension == ".tiff")
{
image.Save(filename, ImageFormat.Tiff);
}
else if (extension == ".exif")
{
image.Save(filename, ImageFormat.Exif);
}
else
{
throw new NotSupportedException(
string.Format("unsupport image extension {0}", extension));
}
}
}
/// <summary>
/// Image resize mode
/// </summary>
public enum ImageResizeMode
{
/// <summary>
/// Resize to the specified size, allow aspect ratio change
/// </summary>
Fixed,
/// <summary>
/// Resize to the specified width, height is calculated by the aspect ratio
/// </summary>
ByWidth,
/// <summary>
/// Resize to the specified height, width is calculated by the aspect ratio
/// </summary>
ByHeight,
/// <summary>
/// Resize to the specified size, keep aspect ratio and cut the overflow part
/// </summary>
Cut,
/// <summary>
/// Resize to the specified size, keep aspect ratio and padding the insufficient part
/// </summary>
Padding
}
}
重写HttpPostedFileBase
using MyCompanyName.Extensions.Extensions;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace MyCompanyName.Extensions.Web.Http
{
public class ImageHttpPostedFileBase : HttpPostedFileBase
{
Stream stream;
string contentType;
string fileName;
public int ImageQuality { get; set; }
public Size ImageThumbnailSize { get; set; }
public ImageResizeMode ImageResizeMode { get; set; }
public ImageHttpPostedFileBase(Stream stream, string contentType, string fileName, Size imageThumbnailSize, int ImageQuality, ImageResizeMode imageResizeMode)
{
this.stream = stream;
this.contentType = contentType;
this.fileName = fileName;
this.ImageQuality = ImageQuality;
this.ImageThumbnailSize = imageThumbnailSize;
this.ImageResizeMode = imageResizeMode;
}
public override int ContentLength
{
get { return (int)stream.Length; }
}
public override string ContentType
{
get { return contentType; }
}
public override string FileName
{
get { return fileName; }
}
public override Stream InputStream
{
get { return stream; }
}
public override void SaveAs(string filename)
{
var image = Image.FromStream(stream);
using (var thumbnailImage = image.Resize(ImageThumbnailSize.Width, ImageThumbnailSize.Height, ImageResizeMode, Color.White))
thumbnailImage.SaveAuto(filename, ImageQuality);
}
}
}
重写HttpPostedFileBase加入了一些自定义的属性 SoEasy
ImageHttpPostedFileBase fileBase = new ImageHttpPostedFileBase(file.InputStream, file.ContentType, file.FileName, new Size(800, 800), 90, Extensions.Extensions.ImageResizeMode.ByWidth);