这实际上是多个问题合二为一:
- 如何从 GDI+ 获得高质量的缩放?
- 保存时如何保持透明度和原始图像信息?
- 保存到磁盘时保持图像质量的最佳方法是什么?
在剩下的部分中,我试图回答每一个问题。
高质量缩放
要开始回答第一个问题,您可能不想使用GetThumbnail()
例程。它几乎是一个黑匣子,不允许您更改很多设置。相反,你会想要做这样的匆忙制作的例程:
// aspectScale = when true, create an image that is up to the size (new w, new h)
// that maintains original image aspect. When false, just create a
// new image that is exactly the (new w, new h)
private static Bitmap ReduceImageSize(Bitmap original, int newWidth, int newHeight, bool aspectScale)
{
if (original == null || (original.Width < newWidth && original.Height < newHeight)) return original;
// calculate scale
var scaleX = newWidth / (float)original.Width;
var scaleY = newHeight / (float)original.Height;
if (scaleY < scaleX) scaleX = scaleY;
// calc new w/h
var calcWidth = (aspectScale ? (int)Math.Floor(original.Width * scaleX) : newWidth);
var calcHeight = (aspectScale ? (int)Math.Floor(original.Height * scaleX) : newHeight);
var resultImg = new Bitmap(calcWidth, calcHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (var offsetMtx = new System.Drawing.Drawing2D.Matrix())
{
offsetMtx.Translate(calcWidth / 2.0f, calcHeight / 2.0f);
offsetMtx.Scale(scaleX, scaleX);
offsetMtx.Translate(-original.Width / 2.0f, -original.Height / 2.0f);
using (var resultGraphics = System.Drawing.Graphics.FromImage(resultImg))
{
// scale
resultGraphics.Transform = offsetMtx;
// IMPORTANT: Compromise between quality and speed for these settings
resultGraphics.SmoothingMode = SmoothingMode.HighQuality;
resultGraphics.InterpolationMode = InterpolationMode.Bicubic;
// For a white background add: resultGraphics.Clear(Color.White);
// render the image
resultGraphics.DrawImage(original, Point.Empty);
}
}
return resultImg;
}
关于此例程,您会注意到您可以更改SmoothingMode
,也可以更改InterpolationMode
. 这些允许您自定义从该例程中获得的缩放质量。要调用我的简单示例,您只需使用:
var newImage = ReduceImageSize(originalImage, 100, 100, true);
这会将您的原始图像缩放到小于或等于 100px 的宽度和相同的高度(这可能是您想要的)。
高品质节省
对于另一部分 - 如何保存,如果您需要透明度,则不能使用 JPEG。作为一个简单的起点,我建议使用 PNG 格式进行保存。看起来像:
newImage.Save(fileName + ".png", ImageFormat.Png);
默认情况下,PNG 包含一定程度的压缩(很像 JPEG),但它也保持透明度,这对您来说似乎很重要。如果您需要进一步压缩,您可以查看已有的 JPEG 文件,减少像素深度或索引颜色。如果你在 google 上搜索,你应该想出很好的方法来支持其中的每一个。
维护原始数据
你没有问过它,但要意识到的是,图像不仅仅是一堆像素——它们还有元数据。元数据包括诸如 EXIF 信息或其他描述图像拍摄方式的数据。当 .NET 创建一个新图像并保存时,您已经有效地从图像中删除了这些数据(这可能是也可能不是这里的目标)。如果您想保留此数据,则可以从使用PropertyItems
列表开始。您可以在旧图像上迭代此数组,复制到新图像。
这实际上并没有公开所有可用的数据。如果您真的想完整地将元数据从原始图像复制到输出图像,您可能需要阅读图像规范或使用诸如 Phil Harvey 提供的工具:http://www.sno。 phy.queensu.ca/~phil/exiftool/。
希望这有助于您朝着正确的方向前进!祝你好运!