减少任何图像大小

时间:2012-09-13 23:31:47

标签: c# asp.net image image-processing image-size

计划

我需要减少图像尺寸,同时保持一定的质量。 但是,我接受GIF,JPEG,JPG和PNG。


现状

上传图像非常实用,我已经能够成功地扩展它的宽度和/或高度。

我找到了一个awesome post here on Stackoverflow,它给了我一个非常好的代码示例:

Image myImage = //... load the image somehow 

//保存质量为50%的图片 SaveJpeg(destImagePath,myImage,50); //添加这个! 使用System.Drawing.Imaging;

                      /// <summary> 
    /// Saves an image as a jpeg image, with the given quality 
    /// </summary> 
    /// <param name="path">Path to which the image would be saved.</param> 
    // <param name="quality">An integer from 0 to 100, with 100 being the 
    /// highest quality</param> 
    public static void SaveJpeg (string path, Image img, int quality) 
    { 
        if (quality<0  ||  quality>100) 
            throw new ArgumentOutOfRangeException("quality must be between 0 and 100."); 


        // Encoder parameter for image quality 
        EncoderParameter qualityParam = 
            new EncoderParameter (Encoder.Quality, quality); 
        // Jpeg image codec 
        ImageCodecInfo   jpegCodec = GetEncoderInfo("image/jpeg"); 

        EncoderParameters encoderParams = new EncoderParameters(1); 
        encoderParams.Param[0] = qualityParam; 

        img.Save (path, jpegCodec, encoderParams); 
    } 

    /// <summary> 
    /// Returns the image codec with the given mime type 
    /// </summary> 
    private static ImageCodecInfo GetEncoderInfo(string mimeType) 
    { 
        // Get image codecs for all image formats 
        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); 

        // Find the correct image codec 
        for(int i=0; i<codecs.Length; i++) 
            if(codecs[i].MimeType == mimeType) 
                return codecs[i]; 
        return null; 
    } 

但是,此代码似乎仅适用于JPEG图像。


问题

  1. JPEG格式比PNG或GIF更轻?如果是这样,我应该转换并保存JPEG中的所有图像吗?
    • 在这种情况下,示例代码应该可以正常工作吗?
    • 如果没有,给定示例代码,我们可以使用其他格式?
  2. 我们可以在C#中使用哪些工具来减轻图像重量? (除了缩小尺寸)
  3. 推荐的&#34;质量损失&#34;对于图像,为了保持可读性,颜色,清晰度和清晰度的合理状态?
  4. 是图像处理&#34;重&#34;在服务器上?

4 个答案:

答案 0 :(得分:3)

首先,JPEG使用“有损”压缩算法,这就是为什么你可以调整质量。较低的质量将导致更好的压缩,但代价是更高的数据丢失。还要意识到JPEG格式是为照片般的图像设计的,将JPEG应用于其他类型的图像可能会令人失望(谷歌“jpeg artifacts”)。

PNG和GIF无损,因此无法支持质量参数。这并不是说你无法从中获得更好的压缩 - 有各种各样的工具可以减小PNG的大小(pngcrush,punypng等),但这些工具(大多数)以一种根本不同的方式工作比JPEG压缩器呢。需要注意的一点是,GIF支持比PNG更小的调色板 - 最多只有256种颜色。

所以按顺序回答你的问题:

  1. 无法真正比​​较,因为JPEG中的压缩带来权衡,而PNG和GIF中的压缩则没有,并且权衡的可接受程度取决于图像的类型。也就是说,JPEG通常会提供更好的压缩,但如果图像不是照片,结果会明显变差。

  2. 您的JPEG代码很好。谷歌与PNG的C#兼容工具。

  3. 您需要尝试所需的图像类型。

答案 1 :(得分:0)

您可能想阅读我的文章20 Image Resizing pitfalls。它涵盖了4个问题中的3个。

答案 2 :(得分:0)

我们可以通过不同的方式做到这一点,

最好的方法之一是将所有图像转换为jpeg,因为它会以更小的尺寸提供更好的清晰度,在此我们不需要更改特定图像的任何高度或宽度

方法1:将所有图像转换为jpeg(无需额外压缩)

  private static void VaryQualityLevel(Image imgToResize,string imageName)
      {
        // Get a bitmap.
        Bitmap bmp1 = new Bitmap(imgToResize);
        ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

        // Create an Encoder object based on the GUID
        // for the Quality parameter category.
        System.Drawing.Imaging.Encoder myEncoder =
            System.Drawing.Imaging.Encoder.Quality;

        // Create an EncoderParameters object.
        // An EncoderParameters object has an array of EncoderParameter
        // objects. In this case, there is only one
        // EncoderParameter object in the array.
        EncoderParameters myEncoderParameters = new EncoderParameters(1);

        EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder,
            50L);
        myEncoderParameters.Param[0] = myEncoderParameter;

        var fileSavePath = Path.Combine(HttpContext.Current.Server.MapPath("~/Download/"), imageName+".jpeg");
        bmp1.Save(fileSavePath, jgpEncoder,
            myEncoderParameters);

        //myEncoderParameter = new EncoderParameter(myEncoder, 100L);
        //myEncoderParameters.Param[0] = myEncoderParameter;
        //fileSavePath = Path.Combine(HttpContext.Current.Server.MapPath("~/Download/"), "TestPhotoQuality100.jpeg");
        //bmp1.Save(fileSavePath, jgpEncoder,
        //    myEncoderParameters);

        // Save the bitmap as a JPG file with 75 quality level compression.
        myEncoderParameter = new EncoderParameter(myEncoder, 75L);
        //myEncoderParameters.Param[0] = myEncoderParameter;
        //fileSavePath = Path.Combine(HttpContext.Current.Server.MapPath("~/Download/"), "TestPhotoQuality75.jpeg");
        //bmp1.Save(fileSavePath, jgpEncoder,
        //    myEncoderParameters);

    }

    private static ImageCodecInfo GetEncoder(ImageFormat format)
    {

        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();

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

方法2:通过改变图像的高度和宽度(没有jpeg转换)

CommonConstant.CS

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EmptyDemo.compression
{
#region[Directive]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#endregion[Directive]

/// <summary>
/// This class is used to get the constants
/// </summary>
public class CommonConstant
{
    public const string JPEG = ".jpeg";
    public const string PNG = ".png";
    public const string JPG = ".jpg";
    public const string BTM = ".btm";
}
}

ImageCompress.CS

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EmptyDemo.compression
{
#region[Directive]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
#endregion[Directive]

/// <summary>
/// This class is used to compress the image to
/// provided size
/// </summary>
public class ImageCompress
{
    #region[PrivateData]
    private static volatile ImageCompress imageCompress;
    private Bitmap bitmap;
    private int width;
    private int height;
    private Image img;
    #endregion[Privatedata]

    #region[Constructor]
    /// <summary>
    /// It is used to restrict to create the instance of the      ImageCompress
    /// </summary>
    private ImageCompress()
    {
    }
    #endregion[Constructor]

    #region[Poperties]
    /// <summary>
    /// Gets ImageCompress object
    /// </summary>
    public static ImageCompress GetImageCompressObject
    {
        get
        {
            if (imageCompress == null)
            {
                imageCompress = new ImageCompress();
            }
            return imageCompress;
        }
    }

    /// <summary>
    /// Gets or sets Width
    /// </summary>
    public int Height
    {
        get { return height; }
        set { height = value; }
    }

    /// <summary>
    /// Gets or sets Width
    /// </summary>
    public int Width
    {
        get { return width; }
        set { width = value; }
    }

    /// <summary>
    /// Gets or sets Image
    /// </summary>
    public Bitmap GetImage
    {
        get { return bitmap; }
        set { bitmap = value; }
    }
    #endregion[Poperties]

    #region[PublicFunction]
    /// <summary>
    /// This function is used to save the image
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="path"></param>
    public void Save(string fileName, string path)
    {
        if (ISValidFileType(fileName))
        {
            string pathaname = path + @"\" + fileName;
            save(pathaname, 60);
        }
    }
    #endregion[PublicFunction]

    #region[PrivateData]
    /// <summary>
    /// This function is use to compress the image to
    /// predefine size
    /// </summary>
    /// <returns>return bitmap in compress size</returns>
    private Image CompressImage()
    {
        if (GetImage != null)
        {
            Width = (Width == 0) ? GetImage.Width : Width;
            Height = (Height == 0) ? GetImage.Height : Height;
            Bitmap newBitmap = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
            newBitmap = bitmap;
            newBitmap.SetResolution(80, 80);
            return newBitmap.GetThumbnailImage(Width, Height, null, IntPtr.Zero);
        }
        else
        {
            throw new Exception("Please provide bitmap");
        }
    }

    /// <summary>
    /// This function is used to check the file Type
    /// </summary>
    /// <param name="fileName">String data type:contain the file name</param>
    /// <returns>true or false on the file extention</returns>
    private bool ISValidFileType(string fileName)
    {
        bool isValidExt = false;
        string fileExt = Path.GetExtension(fileName);
        switch (fileExt.ToLower())
        {
            case CommonConstant.JPEG:
            case CommonConstant.BTM:
            case CommonConstant.JPG:
            case CommonConstant.PNG:
                isValidExt = true;
                break;
        }
        return isValidExt;
    }

    /// <summary>
    /// This function is used to get the imageCode info
    /// on the basis of mimeType
    /// </summary>
    /// <param name="mimeType">string data type</param>
    /// <returns>ImageCodecInfo data type</returns>
    private ImageCodecInfo GetImageCoeInfo(string mimeType)
    {
        ImageCodecInfo[] codes = ImageCodecInfo.GetImageEncoders();
        for (int i = 0; i < codes.Length; i++)
        {
            if (codes[i].MimeType == mimeType)
            {
                return codes[i];
            }
        }
        return null;
    }
    /// <summary>
    /// this function is used to save the image into a
    /// given path
    /// </summary>
    /// <param name="path">string data type</param>
    /// <param name="quality">int data type</param>
    private void save(string path, int quality)
    {
        img = CompressImage();
        ////Setting the quality of the picture
        EncoderParameter qualityParam =
            new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
        ////Seting the format to save
        ImageCodecInfo imageCodec = GetImageCoeInfo("image/jpeg");
        ////Used to contain the poarameters of the quality
        EncoderParameters parameters = new EncoderParameters(1);
        parameters.Param[0] = qualityParam;
        ////Used to save the image to a  given path
        img.Save(path, imageCodec, parameters);
    }
    #endregion[PrivateData]
}
}

这里我在jquery和web服务的帮助下上传图片,我将文件作为formdata传递

    [WebMethod]
    public void UploadFile()
     {
         if (HttpContext.Current.Request.Files.AllKeys.Any())
         {
             // Get the uploaded image from the Files collection
             var httpPostedFile = HttpContext.Current.Request.Files["UploadedImage"];
             if (httpPostedFile != null)
             {
                 ImageCompress imgCompress = ImageCompress.GetImageCompressObject;
                 imgCompress.GetImage = new System.Drawing.Bitmap(httpPostedFile.InputStream);
                 imgCompress.Height = 260;
                 imgCompress.Width = 358;
                 //imgCompress.Save(httpPostedFile.FileName, @"C:\Documents and Settings\Rasmi\My Documents\Visual Studio2008\WebSites\compressImageFile\Logo");
                 imgCompress.Save(httpPostedFile.FileName, HttpContext.Current.Server.MapPath("~/Download/"));

             }
         }
     }

答案 3 :(得分:0)

我使用相同的概念来调整图像大小而不会因为改变比例因子而损失质量。在上传图片后的社交网站中,他们会减少照片的大小,但看到我试着写这篇文章后质量会相同

using System.Drawing.Imaging;
using System.Drawing;

public partial class Default3 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        VaryQualityLevel();
    }
    private void VaryQualityLevel()
    {
        Bitmap bmp1 = new Bitmap(Server.MapPath("test2.png"));
        ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);
        System.Drawing.Imaging.Encoder myEncoder =System.Drawing.Imaging.Encoder.Quality;
        EncoderParameters myEncoderParameters = new EncoderParameters(1);
        EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
        myEncoderParameters.Param[0] = myEncoderParameter;
        bmp1.Save(Server.MapPath("~/Images/1.jpg"), jgpEncoder, myEncoderParameters);
        //myEncoderParameter = new EncoderParameter(myEncoder, 75L);
        //myEncoderParameters.Param[0] = myEncoderParameter;
        //bmp1.Save(Server.MapPath("~/Images/2.jpg"), jgpEncoder, myEncoderParameters);

    }
    private ImageCodecInfo GetEncoder(ImageFormat format)
    {
        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();

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