如何在C#中进行快速图像压缩?

时间:2014-07-09 00:00:53

标签: c# image performance compression

我有一个网络应用程序,允许用户上传各种格式的图像(PNG,JPEG,GIF)。不幸的是,我的用户不一定是技术人员,最终会上传质量(和尺寸)超出要求的图片。

有没有办法让我在服务时压缩这些图像?通过压缩我的意思是有损压缩,降低质量而不一定是尺寸。如果不同的格式压缩不同,我是否应该存储文件格式?

4 个答案:

答案 0 :(得分:2)

当然,您可以使用C#和.NET动态压缩图像。

这是一个这样做的功能。首先,它设置jpg类型的Encoder对象,并为其添加一个新quailty参数。然后将其用于将图像的新质量写入MemoryStream

然后使用新尺寸将从该流创建的图像绘制到自身上。:

//..
using System.Drawing.Imaging;
using System.IO;
//..

private Image compressImage(string fileName,  int newWidth, int newHeight, 
                            int newQuality)   // set quality to 1-100, eg 50
{
    using (Image image = Image.FromFile(fileName))
    using (Image memImage= new Bitmap(image, newWidth int newHeight )  //**
    {
        ImageCodecInfo myImageCodecInfo;
        System.Drawing.Imaging.Encoder myEncoder;
        EncoderParameter myEncoderParameter;
        EncoderParameters myEncoderParameters;
        myImageCodecInfo = GetEncoderInfo("image/jpeg"); 
        myEncoder = System.Drawing.Imaging.Encoder.Quality;
        myEncoderParameters = new EncoderParameters(1);
        myEncoderParameter = new EncoderParameter(myEncoder, newQuality);
        myEncoderParameters.Param[0] = myEncoderParameter;

        MemoryStream memStream = new MemoryStream();
        memImage.Save(memStream, myImageCodecInfo, myEncoderParameters);
        Image newImage = Image.FromStream(memStream);
        ImageAttributes imageAttributes = new ImageAttributes();
        using (Graphics g = Graphics.FromImage(newImage))
        {
            g.InterpolationMode = 
              System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;  //**
            g.DrawImage(newImage,  new Rectangle(Point.Empty, newImage.Size), 0, 0, 
              newImage.Width, newImage.Height, GraphicsUnit.Pixel, imageAttributes);
        }
        return newImage;
    }
}

private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
    ImageCodecInfo[] encoders;
    encoders = ImageCodecInfo.GetImageEncoders();
    foreach (ImageCodecInfo ici in encoders)
        if (ici.MimeType == mimeType) return ici;

    return null;
}

设置新尺寸取决于您。如果您永远不想更改尺寸,请取出参数并将值设置为代码块中的旧尺寸如果您有时只想更改,可以将它们作为0或-1传递给内部进行检查.. < / p>

质量应该在30-60%左右,具体取决于图案。带有文字的屏幕截图不能很好地缩小,需要大约60-80%才能看起来很好而且很脆。

此函数返回文件的jpeg版本。如果你愿意,你可以创建一个不同的编码器,但为了可扩展的质量,jpeg通常是最好的选择。

显然你也可以传入图像而不是文件名,或者将newImage保存到磁盘而不是返回它。 (在这种情况下你应该处理它。)

另外:您可以查看memStream.Length以查看结果是否过大并调整质量。

编辑:更正// **

答案 1 :(得分:0)

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace export
{
    class Program
    {
        static void Main(string[] args)
        {

	foreach (string file in Directory.EnumerateFiles(@"C:\Temp\Images"))
            {
                	FileInfo file_info = new FileInfo(file);
                

                        var filePathOriginal = Path.Combine(@"C:\Temp\Images",
                            String.Format("{0}", file_info.Name));

                        if (File.Exists(filePathOriginal) && file_info.Name.Contains(".png"))
                        {
                            Task.Factory.StartNew(() => VaryQualityLevel(filePathOriginal));  
                            Console.WriteLine("Compressed {0}. {1}", count, file_info.Name);
                            count++;
                        }

            }            
            Console.WriteLine("End Compressing {0} Images{2}{2}Date: {1}{2}", count, DateTime.Now, Environment.NewLine);
            Console.WriteLine("Done");
            Console.ReadLine();
        }

	static void VaryQualityLevel(string file)
        {
            var img = new Bitmap(file);

            try
            {
                SaveJpeg(img, file); 
                img.Dispose();
                if (File.Exists(file))
                    File.Delete(file);
                File.Move(file + 1, file);
            }
            catch (Exception ex)
            {
                // Keep going

            }

        }

        static void SaveJpeg(Image img, string filename)
        {
            EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, 100L);
            ImageCodecInfo jpegCodec = GetEncoder(ImageFormat.Jpeg);
            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;
            img.Save(filename + 1, jpegCodec, encoderParams);
        }

        static ImageCodecInfo GetEncoder(ImageFormat format)
        {

            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();

            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.FormatID == format.Guid)
                {
                    return codec;
                }
            }
            return null;
        }
}

答案 2 :(得分:0)

这是一个用.net 4.0编写的小型应用程序,可以实时压缩图像。 也许可以帮上忙 https://github.com/user5934951/CompressImageLiveNet

答案 3 :(得分:-5)

使用IIS或Apache压缩。它适用于两个Web服务器。