在asp.net项目开发中,对上传的图片进行缩略图生成和水印添加是常见需求,通过System.Drawing命名空间下的相关类可以高效实现这两个功能,无需依赖第三方组件。

核心依赖类说明
实现功能主要用到以下几个核心类:
- Image类:用于加载原始图片,获取图片的尺寸、格式等基础信息
- Bitmap类:继承自Image类,用于创建新的图像对象,支持像素级别的操作
- Graphics类:提供绘图功能,可用于绘制缩略图和添加文字、图片水印
- EncoderParameters类:用于设置图片保存的编码参数,比如图片质量
生成缩略图实现方法
生成缩略图的核心逻辑是先加载原始图片,再根据目标尺寸计算缩放比例,最后使用Graphics对象绘制缩放后的图像。以下是完整的实现代码:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
public class ImageHelper
{
/// <summary>
/// 生成图片缩略图
/// </summary>
/// <param name="originalPath">原始图片路径</param>
/// <param name="thumbnailPath">缩略图保存路径</param>
/// <param name="width">缩略图目标宽度</param>
/// <param name="height">缩略图目标高度</param>
/// <param name="mode">缩放模式:W表示按宽度缩放,H表示按高度缩放,Cut表示裁剪</param>
public static void GenerateThumbnail(string originalPath, string thumbnailPath, int width, int height, string mode)
{
// 加载原始图片
using (Image originalImage = Image.FromFile(originalPath))
{
int toWidth = width;
int toHeight = height;
int x = 0;
int y = 0;
int originalWidth = originalImage.Width;
int originalHeight = originalImage.Height;
// 根据缩放模式计算目标尺寸和绘制起始位置
switch (mode.ToUpper())
{
case "W": // 按宽度缩放,高度按比例计算
toHeight = originalImage.Height * width / originalImage.Width;
break;
case "H": // 按高度缩放,宽度按比例计算
toWidth = originalImage.Width * height / originalImage.Height;
break;
case "CUT": // 裁剪模式,保持目标比例,裁剪多余部分
if ((double)originalImage.Width / (double)originalImage.Height > (double)toWidth / (double)toHeight)
{
originalHeight = originalImage.Height;
originalWidth = originalImage.Height * toWidth / toHeight;
y = 0;
x = (originalImage.Width - originalWidth) / 2;
}
else
{
originalWidth = originalImage.Width;
originalHeight = originalImage.Width * height / toWidth;
x = 0;
y = (originalImage.Height - originalHeight) / 2;
}
break;
default: // 默认按等比例缩放,不超过目标尺寸
if ((double)originalImage.Width / (double)originalImage.Height > (double)toWidth / (double)toHeight)
{
toHeight = originalImage.Height * toWidth / originalImage.Width;
}
else
{
toWidth = originalImage.Width * toHeight / originalImage.Height;
}
break;
}
// 创建缩略图Bitmap对象
using (Bitmap thumbnailBitmap = new Bitmap(toWidth, toHeight))
{
// 创建Graphics绘图对象
using (Graphics graphics = Graphics.FromImage(thumbnailBitmap))
{
// 设置绘图质量
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.Clear(Color.Transparent);
// 绘制缩略图
graphics.DrawImage(originalImage, new Rectangle(0, 0, toWidth, toHeight), new Rectangle(x, y, originalWidth, originalHeight), GraphicsUnit.Pixel);
}
// 设置图片保存质量参数
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 95L);
// 获取图片编码信息
ImageCodecInfo imageCodec = GetImageCodec(originalImage.RawFormat);
// 保存缩略图
thumbnailBitmap.Save(thumbnailPath, imageCodec, encoderParams);
}
}
}
/// <summary>
/// 根据图片格式获取对应的编码信息
/// </summary>
private static ImageCodecInfo GetImageCodec(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
}
添加水印实现方法
水印分为文字水印和图片水印两种,都可以通过Graphics对象的绘制方法实现,以下是两种水印的实现代码:
文字水印实现
/// <summary>
/// 给图片添加文字水印
/// </summary>
/// <param name="originalPath">原始图片路径</param>
/// <param name="outputPath">添加水印后图片保存路径</param>
/// <param name="text">水印文字</param>
/// <param name="position">水印位置:1右下角,2左下角,3右上角,4左上角</param>
public static void AddTextWatermark(string originalPath, string outputPath, string text, int position = 1)
{
using (Image originalImage = Image.FromFile(originalPath))
{
using (Bitmap watermarkBitmap = new Bitmap(originalImage.Width, originalImage.Height))
{
using (Graphics graphics = Graphics.FromImage(watermarkBitmap))
{
// 将原图绘制到新画布
graphics.DrawImage(originalImage, 0, 0, originalImage.Width, originalImage.Height);
// 设置文字字体和颜色
Font font = new Font("微软雅黑", 16, FontStyle.Bold);
Brush brush = new SolidBrush(Color.FromArgb(128, 255, 255, 255)); // 半透明白色
// 计算文字尺寸
SizeF textSize = graphics.MeasureString(text, font);
float x = 0;
float y = 0;
// 根据位置计算文字起始坐标
switch (position)
{
case 1: // 右下角
x = originalImage.Width - textSize.Width - 10;
y = originalImage.Height - textSize.Height - 10;
break;
case 2: // 左下角
x = 10;
y = originalImage.Height - textSize.Height - 10;
break;
case 3: // 右上角
x = originalImage.Width - textSize.Width - 10;
y = 10;
break;
case 4: // 左上角
x = 10;
y = 10;
break;
}
// 绘制文字水印
graphics.DrawString(text, font, brush, x, y);
}
// 保存带水印的图片
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 95L);
ImageCodecInfo imageCodec = GetImageCodec(originalImage.RawFormat);
watermarkBitmap.Save(outputPath, imageCodec, encoderParams);
}
}
}
图片水印实现
/// <summary>
/// 给图片添加图片水印
/// </summary>
/// <param name="originalPath">原始图片路径</param>
/// <param name="watermarkPath">水印图片路径</param>
/// <param name="outputPath">添加水印后图片保存路径</param>
/// <param name="position">水印位置:1右下角,2左下角,3右上角,4左上角</param>
/// <param name="transparency">水印透明度,0-255,值越小越透明</param>
public static void AddImageWatermark(string originalPath, string watermarkPath, string outputPath, int position = 1, int transparency = 128)
{
using (Image originalImage = Image.FromFile(originalPath))
{
using (Image watermarkImage = Image.FromFile(watermarkPath))
{
using (Bitmap outputBitmap = new Bitmap(originalImage.Width, originalImage.Height))
{
using (Graphics graphics = Graphics.FromImage(outputBitmap))
{
// 绘制原始图片
graphics.DrawImage(originalImage, 0, 0, originalImage.Width, originalImage.Height);
// 计算水印位置
int x = 0;
int y = 0;
switch (position)
{
case 1: // 右下角
x = originalImage.Width - watermarkImage.Width - 10;
y = originalImage.Height - watermarkImage.Height - 10;
break;
case 2: // 左下角
x = 10;
y = originalImage.Height - watermarkImage.Height - 10;
break;
case 3: // 右上角
x = originalImage.Width - watermarkImage.Width - 10;
y = 10;
break;
case 4: // 左上角
x = 10;
y = 10;
break;
}
// 设置水印图片的透明度
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.Matrix33 = transparency / 255f; // 设置透明度
ImageAttributes imageAttributes = new ImageAttributes();
imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
// 绘制带透明度的水印图片
graphics.DrawImage(watermarkImage, new Rectangle(x, y, watermarkImage.Width, watermarkImage.Height), 0, 0, watermarkImage.Width, watermarkImage.Height, GraphicsUnit.Pixel, imageAttributes);
}
// 保存图片
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 95L);
ImageCodecInfo imageCodec = GetImageCodec(originalImage.RawFormat);
outputBitmap.Save(outputPath, imageCodec, encoderParams);
}
}
}
}
方法调用示例
以下是调用上述方法生成缩略图并添加水印的示例:
// 生成缩略图,按宽度缩放,目标宽度200
ImageHelper.GenerateThumbnail(Server.MapPath("~/Uploads/original.jpg"), Server.MapPath("~/Uploads/thumb.jpg"), 200, 0, "W");
// 给缩略图添加文字水印,水印放在右下角
ImageHelper.AddTextWatermark(Server.MapPath("~/Uploads/thumb.jpg"), Server.MapPath("~/Uploads/thumb_watermark.jpg"), "版权所有", 1);
// 给原始图添加图片水印
ImageHelper.AddImageWatermark(Server.MapPath("~/Uploads/original.jpg"), Server.MapPath("~/Uploads/watermark.png"), Server.MapPath("~/Uploads/original_watermark.jpg"), 1, 128);
注意事项
- 使用完Image、Bitmap、Graphics等对象后,一定要使用using语句或者手动调用Dispose方法释放资源,避免内存泄漏
- 如果处理的图片是用户上传的,需要提前校验图片格式,避免加载恶意文件导致程序异常
- 生成缩略图时如果原始图片尺寸小于目标尺寸,可根据需求选择是否放大,默认逻辑是不放大保持原尺寸
- 添加文字水印时,如果文字颜色和水印位置背景色接近,可以调整文字颜色或者添加文字描边提升辨识度