c# - c#如何在保留图像类型的同时将任何图像的大小调整为特定的千字节
问题描述
我已经看到了大量用于减小图像大小的 stackoverflow 文章,但它们都没有保持原始图像类型(或者我发现了)。它们通常具有减小像素尺寸、降低图像质量以及转换为特定类型图像(通常是 jpeg)的步骤。
我有一组需要调整大小的图像。它们具有各种图像类型,并且文件名都存储在数据库中,这使得从一种图像类型转换为另一种图像类型有些问题。我不能只将文件名从 png 更改为 jpg,因为这样数据库就不会指向真实文件。
有没有人有如何将图像调整大小/缩小到“256 KB”并保持原始图像类型的示例?
例如,这是我目前正在摆弄的代码。
public static byte[] ResizeImageFile(Image oldImage, int targetSize) // Set targetSize to 1024
{
Size newSize = CalculateDimensions(oldImage.Size, targetSize);
using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format24bppRgb))
{
using (Graphics canvas = Graphics.FromImage(newImage))
{
canvas.SmoothingMode = SmoothingMode.AntiAlias;
canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));
MemoryStream m = new MemoryStream();
newImage.Save(m, ImageFormat.Jpeg);
return m.GetBuffer();
}
}
}
也许有一种方法可以让我先获取文件 fileinfo 或 mime 类型,然后打开 .Save 以获取图像类型?
解决方案
这是我想出的(基于我在网上找到的一些不是 100% 完整的示例。
private void EnsureImageRequirements(string filePath)
{
try
{
if (File.Exists(filePath))
{
// If images are larger than 300 kilobytes
FileInfo fInfo = new FileInfo(filePath);
if (fInfo.Length > 300000)
{
Image oldImage = Image.FromFile(filePath);
ImageFormat originalFormat = oldImage.RawFormat;
// manipulate the image / Resize
Image tempImage = RefactorImage(oldImage, 1200); ;
// Dispose before deleting the file
oldImage.Dispose();
// Delete the existing file and copy the image to it
File.Delete(filePath);
// Ensure encoding quality is set to an acceptable level
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
// Set encoder to fifty percent compression
EncoderParameters eps = new EncoderParameters
{
Param = { [0] = new EncoderParameter(Encoder.Quality, 50L) }
};
ImageCodecInfo ici = (from codec in encoders where codec.FormatID == originalFormat.Guid select codec).FirstOrDefault();
// Save the reformatted image and use original file format (jpeg / png / etc) and encoding
tempImage.Save(filePath, ici, eps);
// Clean up RAM
tempImage.Dispose();
}
}
}
catch (Exception ex)
{
this._logger.Error("Could not resize oversized image " + filePath, ex);
}
}
private static Image RefactorImage(Image imgToResize, int maxPixels)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
int destWidth = sourceWidth;
int destHeight = sourceHeight;
// Resize if needed
if (sourceWidth > maxPixels || sourceHeight > maxPixels)
{
float thePercent = 0;
float thePercentW = 0;
float thePercentH = 0;
thePercentW = maxPixels / (float) sourceWidth;
thePercentH = maxPixels / (float) sourceHeight;
if (thePercentH < thePercentW)
{
thePercent = thePercentH;
}
else
{
thePercent = thePercentW;
}
destWidth = (int)(sourceWidth * thePercent);
destHeight = (int)(sourceHeight * thePercent);
}
Bitmap tmpImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(tmpImage);
g.InterpolationMode = InterpolationMode.HighQualityBilinear;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return tmpImage;
}
推荐阅读
- javascript - 如何为证书故意显示“连接是安全的”消息
- kubernetes - AKS | 网络政策 | 在使用 Azure CNI 时阻止入口流量
- sql-server - SQL Server:用户登录失败
- python-3.x - Jupyter Notebook 以编程方式运行单元格
- assembly - 如何在 C 和内联汇编中计算 T = 2.01*sqrt(L)
- three.js - 未捕获的类型错误:加载 gLTF 模型并创建网格时,无法读取三个.js 中未定义的属性“类型”
- vb.net - 标签未显示已编码的功能
- json - Go:是否可以编组循环的 json
- objective-c - Objective-C:将对象类型转换为 integer_t
- javascript - 如何拥有一个可以滚动到 fullPage.js 中每个部分的固定链接?