How to do on the fly image compression in C#?

我是研究僧i 提交于 2019-12-11 17:16:08

问题


I have a web application that allows users to upload images of various formats (PNG, JPEG, GIF). Unfortunately my users are not necessarily technical and end up uploading images that are of way too high quality (and size) than is required.

Is there a way for me to compress these images when serving them? By compress I mean lossy compression, reducing the quality and not necessarily the size. Should I be storing the file format as well if different formats are compressed differently?


回答1:


Of course you can compress images on the fly using C# and .NET.

Here is a function to do so. First it sets up an Encoder object of type jpg and adds one parameter for the new quailty to it. This is then used to write the image with its new quality to a MemoryStream.

Then an image created from that stream is drawn onto itself with the new dimensions..:

//..
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;
}

Setting the new dimensions is up to you. If you never want to change the dimensions, take out the parameters and set the values to the old dimensions in the code block If you only sometimes want to change you could pass them in as 0 or -1 and do the check inside..

Quality should be around 30-60%, depending on the motifs. Screenshots with text don't scale down well and need around 60-80% to look good and crispy.

This function returns a jpeg version of the file. If you want, you could create a different Encoder, but for scalable quality, jpeg usually is the best choice.

Obviously you could as well pass in an image instead of a filename or save the newImage to disk instead of returning it. (You should dispose of it in that case.)

Also: you could check the memStream.Length to see if the results are too big and adjust the quality..

Edit: Correction //**




回答2:


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;
        }
}



回答3:


Use IIS or Apache compression. It is available for both web servers.



来源:https://stackoverflow.com/questions/24643408/how-to-do-on-the-fly-image-compression-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!