图像压缩不起作用

时间:2014-02-06 00:50:18

标签: c# image-compression

我在网站上进行了一项操作,即裁剪图像,但是文件大小合成的裁剪图像显得更大(原始图像为24k,裁剪后的图像为650k)。所以我发现在保存之前我需要对图像应用一些压缩。我想出了以下内容:

public static System.Drawing.Image CropImage(System.Drawing.Image image, Rectangle cropRectangle, ImageFormat format)
{
    var croppedImage = new Bitmap(cropRectangle.Width, cropRectangle.Height);
    using (var g = Graphics.FromImage(croppedImage))
    {
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(
            image, 
            new Rectangle(new Point(0,0), new Size(cropRectangle.Width, cropRectangle.Height)), 
            cropRectangle, 
            GraphicsUnit.Pixel); 
        return CompressImage(croppedImage, format);
    }
}

public static System.Drawing.Image CompressImage(System.Drawing.Image image, ImageFormat imageFormat)
{
    var bmp = new Bitmap(image);
    var codecInfo = EncoderFactory.GetEncoderInfo(imageFormat);
    var encoder = System.Drawing.Imaging.Encoder.Quality;
    var parameters = new EncoderParameters(1);
    var parameter = new EncoderParameter(encoder, 10L);
    parameters.Param[0] = parameter;

    using (var ms = new MemoryStream())
    {
        bmp.Save(ms, codecInfo, parameters);
        var resultImage = System.Drawing.Image.FromStream(ms);
        return resultImage;
    }
}

我将质量设置得很低,只是为了看看是否有任何变化。没有。作物正在外观上得到正确保存,但压缩并不是一种乐趣。如果我完全绕过CompressImage(),文件大小和图像质量都不会有任何不同。

所以,2个问题。为什么没有发生?是否有一种更简单的方法将结果图像压缩为“网络优化”,类似于photoshop保存网页图像的方式(我认为它只是从中删除了大量信息以减小尺寸)。

2 个答案:

答案 0 :(得分:3)

您的问题是您必须在保存图像时“压缩”(真正编码)图像,而不是在保存图像之前。程序中的Image对象始终是未压缩的。

通过保存到MemoryStream并从流中读回来将对图像进行编码,然后再将其解码回相同的大小(如果使用JPEG,则在此过程中会有一些质量损失)。但是,如果将其保存到具有压缩参数的文件中,您将获得压缩的图像文件。

在153 KB源图像上使用JPEG质量等级为90的例程可以得到102 KB的输出图像。如果您想要更小的文件大小(具有更多编码伪像),请将编码器参数更改为小于90的值。

public static void SaveJpegImage(System.Drawing.Image image, string fileName)
{
    ImageCodecInfo codecInfo = ImageCodecInfo.GetImageEncoders()
        .Where(r => r.CodecName.ToUpperInvariant().Contains("JPEG"))
        .Select(r => r).FirstOrDefault();

    var encoder = System.Drawing.Imaging.Encoder.Quality;
    var parameters = new EncoderParameters(1);
    var parameter = new EncoderParameter(encoder, 90L);
    parameters.Param[0] = parameter;

    using (FileStream fs = new FileStream(fileName, FileMode.Create))
    {
        image.Save(fs, codecInfo, parameters);
    }
}

答案 1 :(得分:-1)

我相信在使用引用流的Image.FromStream创建的图像时,不应该丢弃MemoryStream。直接从流创建位图也不起作用。

试试这个:

private static Image CropAndCompressImage(Image image, Rectangle rectangle, ImageFormat imageFormat)
{
    using(Bitmap bitmap = new Bitmap(image))
    {
        using(Bitmap cropped = bitmap.Clone(rectangle, bitmap.PixelFormat))
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                cropped.Save(memoryStream, imageFormat);
                return new Bitmap(Image.FromStream(memoryStream));
            }
        }
    }
}