【问题标题】:Reduce image size in C#在 C# 中减小图像大小
【发布时间】:2016-05-12 23:13:16
【问题描述】:

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

该函数应获取图像 URL,检查图像大小为 4MB 或更大,如果是则将其调整为情人然后 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。

因此,当我尝试使用上述方法调整此图像的大小时。 它首先计算“resizePercentage”为:

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

但是因为我设置了最小的 resizePercent,它将被设置为 0.8 (80%)。

resizePercent = 0.8;

然后它会用这个 resizePercent 计算新的宽度和高度。

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

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

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

【问题讨论】:

  • 您在接收图像时不知道所应用的 jpg 压缩的质量。因此,也许您正在以比原始图像更高的质量(即压缩更少)保存图像。使用 bmp 图像时问题是否仍然存在?
  • 如果您的测试图像是 JPEG,它的压缩率可能高于 .NET 默认使用的压缩率。由于 JPEG 使用有损压缩,因此有多种可用的压缩比;他们将确定生成的图像看起来有多粗糙。对于无损的 PNG,原始图像仍然有可能通过比 .NET 使用的更好的算法进行压缩。以此类推。

标签: c# asp.net-mvc image bitmap memorystream


【解决方案1】:

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

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

总之,您不能只应用简单的基于百分比的分辨率降低来确保一定的文件大小。最好的办法是逐渐降低分辨率,在每次迭代中测试文件大小,直到它低于你的阈值,假设它确实低于阈值。可以使用 4MB 的空间,可以想象一定的分辨率肯定会低于此值,但实际上无法计算该点所在的位置。

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

【讨论】:

    【解决方案2】:

    尝试改变InterpolationMode、SmoothingMode、CompositingQuality、PixelOffsetMode的质量。您可以看到所有这些都设置为高质量

    【讨论】:

      猜你喜欢
      • 2011-05-08
      • 1970-01-01
      • 2017-02-06
      • 2019-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多