【问题标题】:C# - Decrease image resolution increases file sizeC# - 降低图像分辨率会增加文件大小
【发布时间】:2016-08-10 08:54:19
【问题描述】:

我有一个 MVC 应用程序,您可以在其中上传图片并将其大小调整为最大。 50KB。 我在while循环中调整大小,但问题是当我减小图片的宽度和高度时,文件大小会增加。在某个时候,尺寸会变小,但会以质量为代价

    Request.InputStream.Position = 0;
    string Data = new System.IO.StreamReader(Request.InputStream).ReadToEnd();
    var Base64 = Data.Split(',')[1];
    var BitmapBytes = Convert.FromBase64String(Base64);
    var Bmp = new Bitmap(new MemoryStream(BitmapBytes));

    while (BitmapBytes.Length > 51200)
    {
        int Schritte = 20; //I tested here also with 300
        int maxWidth = Bmp.Width;
        maxWidth = maxWidth - Schritte;
        int maxHeight = Bmp.Height;
        maxHeight = maxHeight - Schritte;
        Bmp = ScaleImage(Bmp, maxWidth, maxHeight);
        var base64 = ReturnImageAsBase64(Bmp);
        BitmapBytes = Convert.FromBase64String(base64);
    }

调整大小的代码:

public static Bitmap ScaleImage(Image image, int maxWidth, int maxHeight)
{
    var ratioX = (double)maxWidth / image.Width;
    var ratioY = (double)maxHeight / image.Height;
    var ratio = Math.Min(ratioX, ratioY);

    var newWidth = (int)(image.Width * ratio);
    var newHeight = (int)(image.Height * ratio);

    Bitmap newImage = new Bitmap(newWidth, newHeight);
    using (Graphics gr = Graphics.FromImage(newImage))
    {
        gr.SmoothingMode = SmoothingMode.HighQuality;
        gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
        gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
        gr.DrawImage(image, new Rectangle(0, 0, newWidth, newHeight));
     }
     return newImage;
}

我从 66964 字节的大小开始。在循环的第一轮之后,它的 85151 字节虽然宽度减少了 300 像素,高度减少了 420 像素。

【问题讨论】:

  • 我会说这是您的 Pixelformat 的问题。例如,如果您有一个 1bpp(黑色或白色)的位图并将其绘制到 ScaleImage 中的 newImage 中,则 newImage 是使用可能使用 Colors 的默认 Pixelformat 创建的,因此您最终会得到 24bpp,这会导致更高的内存大小.

标签: c# image resize size


【解决方案1】:

根据我之前的评论:

我会说这是您的 Pixelformat 的问题。例如,如果您有一个 1bpp(黑色或白色)的位图并将其绘制到 ScaleImage 中的 newImage 中,则 newImage 是使用可能使用 Colors 的默认 Pixelformat 创建的,因此您最终会得到 24bpp,这会导致更高的内存大小.

尝试改变:

Bitmap newImage = new Bitmap(newWidth, newHeight);

Bitmap newImage = new Bitmap(newWidth, newHeight, image.PixelFormat);

编辑:由于使用索引 PixelFormats 似乎不可能从中创建图形对象,因此似乎没有简单的解决方案。

解释图片尺寸变大的原因:

原图: 颜色查找表:

1 = Red   = 255,  0,0
2 = Black =   0,  0,0
3 = Green =   0,255,0
...

         Column    
    Row  1  2  3  4
      1  1  1  1  1
      2  1  1  1  1
      3  2  2  2  2
      4  3  3  3  3

这里有 16 个字节用于 16 个像素,12 个字节用于查找表(一个字节用于索引号,三个字节用于每种颜色的 RGB 通道) 所以Image的总大小是28字节

在 newImage 中没有查找表,因此每个 Pixel 都有完整的 RGB 信息:

         Column    
    Row  1            2            3            4
      1  (255,  0,0)  (255,  0,0)  (255,  0,0)  (255,  0,0)
      2  (255,  0,0)  (255,  0,0)  (255,  0,0)  (255,  0,0)
      3  (  0,  0,0)  (  0,  0,0)  (  0,  0,0)  (  0,  0,0)
      4  (  0,255,0)  (  0,255,0)  (  0,255,0)  (  0,255,0)

所以newImage的大小是3*16=48 Bytes

【讨论】:

  • 这会在我创建新图形的下一行引发异常。 (不能从具有索引像素格式的图像创建图形对象。)
  • 这似乎是 Graphics 类的限制。见这里:stackoverflow.com/questions/17313285/graphics-on-indexed-image
  • 但这完美地解释了会发生什么:您的原始图像有一个颜色查找表,像素仅指向颜色的查找条目。在新图像中,颜色每个像素存储一次,因此您可以为图像检索更大的尺寸。
  • 我更改了代码,以便在调整大小后添加 BPP,但我仍然遇到同样的问题。我发布了另一个问题,在其中添加了一些示例:stackoverflow.com/questions/38872777/…
  • 如果您觉得答案正确,请不要忘记投票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 2016-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多