在 C# 中减小图像大小

本文关键字:图像 | 更新日期: 2023-09-27 18:33:08

我想要可以减小图像大小的功能。

该函数应采用图像URL,检查图像大小是否为4MB或更大,如果是,则将其大小调整为lover,然后为4MB并返回字节。

我有下一个方法:

public byte[] ResizeImage(string url)
{
    var uri = new Uri(url);
    var c = new WebClient();
    var oldImgStream = new MemoryStream(c.DownloadData(uri));
    if (oldImgStream.Length <= 4194304)
    {
        return oldImgStream.ToArray();
    }
    using (var oldImage = new Bitmap(oldImgStream))
    using (var newImageStream = new MemoryStream())
    {
        var format = oldImage.RawFormat;
        float resizePercent = (float)4194304 / oldImgStream.Length;
        var newImage =  ResizeImageByPercent(oldImage, resizePercent);
        newImage.Save(newImageStream, format);
       return newImageStream.ToArray();
    }
}
public static Bitmap ResizeImageByPercent(Bitmap image, float resizePercent)
{
    //Set minimum resizePercentage to 80%
    resizePercent = resizePercent > 0.8 ? (float)0.8 : resizePercent;
    int newWidth = (int)(image.Width * resizePercent);
    int newHeight = (int)(image.Height * resizePercent);
    var newImage = new Bitmap(newWidth, newHeight);
    using (var graphics = Graphics.FromImage(newImage))
    {
        graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
        graphics.FillRectangle(Brushes.Transparent, 0, 0, newWidth, newHeight);
        graphics.DrawImage(image, 0, 0, newWidth, newHeight);
        return newImage;
    }
}

但这并不正常工作。

我有一个jpg图像作为示例。

图像大小略大于 4MB(4194587 字节(。图像的分辨率为 2272 x 1704。

因此,当我尝试使用上面的方法调整此图像的大小时。它首先计算"调整大小百分比"为:

float resizePercent = (float)4194304 / oldImgStream.Length;
resizePercent = (float)4194304 / 4194587;
resizePercent = 0.9999325 //(99.99325%)

但是因为我设置了最小调整大小百分比,所以它将设置为 0.8 (80%(。

resizePercent = 0.8;

然后它将使用此调整大小百分比计算新的宽度和高度。

新的分辨率将是:1817 x 1363,图像大小调整为新的分辨率。但是在它被保存到流并读取字节后,它会返回更大的图像。返回图像的站点是"5146056字节"5MB

那么有没有人知道如何实现这一点,或者我的方法有什么问题,所以它返回更大的图像,即使分辨率降低。

我应该能够减小图像 png、jpg 和 gif 的大小

在 C# 中减小图像大小

处理压缩位图时,图像文件大小和分辨率之间没有一对一的相关性。对于真正的位图(例如 BMP(,确实存在这种相关性,因为 1 个像素始终等于定义的字节数(基于色彩空间(。

但是,当谈论压缩位图(如 JPEG(时,文件大小基于压缩效率(总体需要编码多少种颜色,基于相同颜色可以组合多少像素,或者可以进行多少抖动以创建更多可以组合的相同颜色的像素(。对于较低分辨率的图像,这最终可能会减少,但它也很容易保持不变甚至增加,这取决于原始压缩的效率以及总体上较少数量的像素对压缩效率的影响。

无论何时何方,您都不能只应用简单的基于百分比的分辨率降低来确保一定的文件大小。您真正能做的最好的事情是逐渐降低分辨率,在每次迭代时测试文件大小,直到它低于阈值,假设它确实低于阈值。有了4MB可以玩,可以想象有一定的分辨率肯定会低于这个分辨率,但这一点在哪里几乎不可能计算。

此外,这将因图像格式的类型而异。JPEG的功能主要是尝试尽可能多地扩展颜色(抖动(。这就是质量较低的 JPEG 显示伪影的原因。不过,PNG和GIF大多是索引的,其中试图减少颜色的总量(尽管两者都可以使用抖动(。PNG 使问题进一步复杂化,因为它也可以拥有无损 PNG,其中保留所有颜色和像素,但应用简单的压缩(很像 ZIP 存档(以减小文件大小。所有这些将具有彼此不同的行为,并且具有不同的分辨率。

尝试更改插值模式、平滑模式、合成质量、像素偏移模式的质量。您可以看到所有这些都设置为高质量