保存前降低图像/流的质量

时间:2012-07-17 14:42:54

标签: c# stream

我正在尝试获取输入流(图像的zip文件)并提取每个文件。但是我必须在保存之前降低每个图像的质量(如果质量<100)。我尝试了以下但它从未压缩图像:

public void UnZip(Stream inputStream, string destinationPath, int quality = 80) {
    using (var zipStream = new ZipInputStream(inputStream)) {
        ZipEntry entry;

        while ((entry = zipStream.GetNextEntry()) != null) {
            var directoryPath = Path.GetDirectoryName(destinationPath + Path.DirectorySeparatorChar + entry.Name);
            var fullPath = directoryPath + Path.DirectorySeparatorChar + Path.GetFileName(entry.Name);

            // Create the stream to unzip the file to
            using (var stream = new MemoryStream()) {
                // Write the zip stream to the stream
                if (entry.Size != 0) {
                    var size = 2048;
                    var data = new byte[2048];

                    while (true) {
                        size = zipStream.Read(data, 0, data.Length);

                        if (size > 0)
                            stream.Write(data, 0, size);
                        else
                            break;
                    }
                }

                // Compress the image and save it to the stream
                if (quality < 100)
                    using (var image = Image.FromStream(stream)) {
                        var info = ImageCodecInfo.GetImageEncoders();
                        var @params = new EncoderParameters(1);
                        @params.Param[0] = new EncoderParameter(Encoder.Quality, quality);
                        image.Save(stream, info[1], @params);
                    }
                }

                // Save the stream to disk
                using (var fs = new FileStream(fullPath, FileMode.Create)) {
                    stream.WriteTo(fs);
                }
            }
        }
    }
}

如果有人能告诉我我做错了什么,我会很感激。此外,任何关于整理它的建议都会受到赞赏,因为代码变得越来越丑陋。感谢

2 个答案:

答案 0 :(得分:2)

您确实不应该使用相同的流来保存压缩图像。 MSDN文档清楚地说:“不要将图像保存到用于构建图像的相同流中。这样做可能会损坏流。” (MSDN Article on Image.Save(...)

using (var compressedImageStream = new MemoryStream())
{
    image.Save(compressedImageStream, info[1], @params);
}

另外,您编码的文件格式是什么?你还没有说明。你刚刚找到了第二个编码器。您不应该依赖结果的顺序。而是搜索特定的编解码器:

var encoder = ImageCodecInfo.GetImageEncoders().Where(x => x.FormatID == ImageFormat.Jpeg.Guid).SingleOrDefault()

...并且不要忘记检查系统上是否存在编码器:

if (encoder != null)
{ .. }

Quality参数对所有文件格式都没有意义。我假设您可能正在使用JPEG?另外,请记住100%JPEG质量!=无损图像。您仍然可以使用Quality = 100进行编码并减少空间。

答案 1 :(得分:1)

从zip流中提取图像后,没有压缩图像的代码。您似乎正在做的就是将解压缩的数据放入MemoryStream中,然后根据质量信息(可能压缩或不压缩图像,根据编解码器)将图像写入相同的流。我首先建议不要写入您正在阅读的同一个流。此外,您从Encoder.Quality属性中获得的“压缩”取决于图像的类型 - 您没有提供任何详细信息。如果图像类型支持压缩并且传入的图像质量低于100以启动,则不会减小尺寸。此外,您尚未提供任何有关此信息。长话短说,你没有提供足够的信息给任何人给你一个真正的答案。