C# 生成 JPG 缩略图字节数组函数
在 C# 开发中,有时需要直接将图片处理为内存中的字节流以便传输或存入数据库,而非先写入磁盘文件。本教程介绍如何使用 System.Drawing 命名空间编写一个高效、灵活的静态方法,通过指定路径、目标尺寸、压缩质量及缩放模式,快速生成 JPG 格式的缩略图字节数组。
功能目标与准备条件
该方法的核心目标是接收一张原始图片的路径,经过图像处理和压缩后,输出一个 byte[] 数组。为了实现高质量的视觉效果和灵活的控制,我们需要引入以下关键要素:
- 依赖库:需要引用
System.Drawing和System.Drawing.Imaging命名空间。 - 缩放模式:支持四种常见的图像处理需求:
HW:强制拉伸至指定宽和高,可能导致图像变形。W:保持原图纵横比,仅按指定宽度计算高度。H:保持原图纵横比,仅按指定高度计算宽度。Cut:在保持纵横比的前提下,裁切多余部分以适应目标尺寸(不变形)。- 编码参数:使用
Encoder.Quality控制 JPEG 压缩质量(0-100)。
第 1 步:定义核心方法签名
首先创建一个静态类或将其添加到现有工具类中。方法需接收原始图片路径、JPEG 质量系数、目标宽高以及操作模式。
public static byte[] MakeJPGThumbnailBytes(
string originalImagePath,
long quality,
int width,
int height,
string mode)
{
// 待实现逻辑
}
第 2 步:加载原图与初始化画布
使用 Image.FromFile 加载源图像,获取其原始宽高(ow, oh)。同时创建用于绘制的位图和图形上下文,并设置高质量的渲染属性以消除锯齿。
Image originalImage = Image.FromFile(originalImagePath);
MemoryStream s = new MemoryStream();
int towidth = width;
int toheight = height;
int x = 0;
int y = 0;
int ow = originalImage.Width;
int oh = originalImage.Height;
// 创建目标尺寸的 Bitmap 和 Graphics
Image bitmap = new System.Drawing.Bitmap(towidth, toheight);
Graphics g = System.Drawing.Graphics.FromImage(bitmap);
// 设置高级绘图质量
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.Clear(Color.Transparent);
第 3 步:计算裁剪区域与绘制
根据选择的 mode 计算最终图像的源坐标 (x, y) 和源尺寸 (ow, oh),然后使用 DrawImage 将原图的特定部分绘制到新的画布上。
switch (mode)
{
case "HW": // 指定高宽缩放(可能变形)
break; // towidth/toheight 保持不变
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)
{
oh = originalImage.Height;
ow = (originalImage.Height * towidth) / toheight;
y = 0;
x = (originalImage.Width - ow) / 2;
}
else
{
ow = originalImage.Width;
oh = (originalImage.Width * height) / towidth;
x = 0;
y = (originalImage.Height - oh) / 2;
}
break;
default:
break;
}
// 执行绘制
// 参数说明: 目标位置(0,0,towidth,toheight), 源矩形(x,y,ow,oh)
g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
new Rectangle(x, y, ow, oh), GraphicsUnit.Pixel);
第 4 步:配置编码器并保存为字节数组
JPEG 保存需要特定的 ImageCodecInfo。我们通过遍历系统注册的编码器找到对应 MIME 类型的编码器,并设置质量参数。最后将图像保存到 MemoryStream 并返回缓冲区。
try
{
EncoderParameters eps = new EncoderParameters(1);
EncoderParameter ep = new EncoderParameter(Encoder.Quality, quality);
eps.Param[0] = ep;
// 获取 JPEG 编码器信息
ImageCodecInfo codecInfo = GetCodecInfo("image/jpeg");
if (codecInfo == null) throw new Exception("未找到 JPEG 编码器");
bitmap.Save(s, codecInfo, eps);
return s.GetBuffer();
}
catch (System.Exception e)
{
throw e;
}
finally
{
// 务必释放所有非托管资源
originalImage.Dispose();
bitmap.Dispose();
s.Dispose();
g.Dispose();
}
辅助方法:获取 ImageCodecInfo
为了查找正确的图像编码器(如 JPG),需要遍历 ImageCodecInfo.GetImageEncoders() 并匹配 MIME 类型。
private static ImageCodecInfo GetCodecInfo(string mimeType)
{
ImageCodecInfo[] CodecInfo = ImageCodecInfo.GetImageEncoders();
foreach (ImageCodecInfo ici in CodecInfo)
{
if (ici.MimeType == mimeType) return ici;
}
return null;
}
完成判断与注意事项
调用此方法后,您将得到一个包含 JPG 压缩数据的字节数组。使用时请注意以下几点:
- 资源释放:代码已在
finally块中确保了Image、Bitmap、Graphics和MemoryStream的释放,防止内存泄漏。 - 线程安全:
System.Drawing在某些 Windows 服务或非 UI 线程环境中可能存在稳定性问题,建议仅在单线程或确保环境支持的场景下使用。 - 空指针风险:若图片不存在或损坏,
Image.FromFile会抛出异常;若未找到 JPEG 编码器,GetCodecInfo返回 null 会导致后续保存失败,实际项目中建议增加判空逻辑。
以上就是基于 C# GDI+ 实现 JPG 缩略图字节生成的详细内容,更多关于 C# 图像处理及性能优化的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









