将png流写回另一个png会增加大小。为什么?

时间:2016-04-15 14:20:04

标签: c# .net image png

有人可以向我解释为什么将PNG图像中的流写回另一个PNG文件会增加最终输出的大小吗?

原始文件:大小(28.6 KB),磁盘大小(32.0 KB)

输出文件:大小(32.1 KB),磁盘大小(36.0 KB)。

执行此操作的代码非常简单:

private void button1_Click(object sender, EventArgs e)
    {
        var result = openFileDialog1.ShowDialog();

        if (result == DialogResult.OK)
        {
            var file = openFileDialog1.FileName;
            var stream = new FileStream(file, FileMode.Open);
            var newImg = Image.FromStream(stream);
            newImg.Save("newPNG.png", ImageFormat.Png);
            stream.Close();
        }
    }

我该如何避免这种情况?我希望最终图像的尺寸与原始图像完全相同。

LE:如果有人想尝试,我上传了原始图片。 cat image

2 个答案:

答案 0 :(得分:2)

来自Wikipedia

  

有五种可能的过滤器类型可以单独指定   在每条扫描线上以及搜索LZ77的几种可能策略   火柴。因此,存在非常多的不同组合   如何压缩图像。哪种组合最好   压缩取决于各个图像的属性。

也就是说,压缩PNG有很多方法,显然在你的情况下,原始文件的压缩方式与.NET的默认方式不同。我不确定您可以对.NET的输出产生多大影响,但是Image.Save覆盖了EncoderParameters。你可能想看一下。 Link

答案 1 :(得分:0)

我敢打赌,因为像GDI +这样的东西会保存不同设置的图像,也可能是不同的编码。

如果您创建新的FileStream并从第一个读取字节,然后将它们写入第二个,则可以保留相同的大小。因此复制文件。

stream.Position = 0;
using(FileStream fs = new FileStream("newPNG.png"))
{
    int totalBytesRead = 0;
    while(totalBytesRead < stream.Length)
    {
        byte[] byteBuffer = new byte[8192];
        int bytesRead = stream.Read(readBytes, 0, byteBuffer.Length);
        fs.Write(byteBuffer, totalBytesRead, bytesRead);
        totalBytesRead += bytesRead;
    }
}
stream.Position = 0;

我之前和之后都将stream.Position设置为零,因为我不知道您将在何处使用此代码。将其设置为零将使FileStream从文件的开头开始读取。