Сжатие и распаковка файла перед сохранением на диск

#c# #asp.net #image-compression #compression

#c# #asp.net #сжатие изображения #сжатие

Вопрос:

В моем приложении у меня есть один веб-сервис, который получает один файл из FormData (на стороне клиента), и я хочу сжать этот файл перед сохранением на диск (без использования дополнительной папки).

я прочитал много ответов отсюда, но я запутался, какой метод я буду использовать в коде, чтобы добиться лучшего сжатия. а также я хочу распаковать этот файл во время доступа.

В настоящее время в коде я использую приведенный ниже код для непосредственного сохранения файла.

 var httpPostedFile = HttpContext.Current.Request.Files["UploadedImage"];
// Get the complete file path
var fileSavePath = Path.Combine(HttpContext.Current.Server.MapPath("~/Download/"), httpPostedFile.FileName);
// Save the uploaded file to "UploadedFiles" folder
httpPostedFile.SaveAs(fileSavePath);
  

Комментарии:

1. Вы могли бы просто включить сжатие NTFS в родительской папке, а затем ничего не делать, сжатие и де-сжатие обрабатываются автоматически. Но если загруженные файлы представляют собой изображения в формате JPEG, GIF или PNG, их сжатие не будет очень эффективным, поскольку они уже сжаты.

2. Я буду загружать только изображения, поэтому вы говорите, что я хочу вручную включить сжатие в папке решения или с помощью кода.

3. Я включил сжатие, выбрав свойства этой папки, но когда я попытался загрузить изображение размером (5,7 МБ), оно приняло тот же размер в этой папке после загрузки,

4. Посмотрите на общие свойства файла, вы можете увидеть Size on disk , что он может быть намного меньше, чем Size , но для большинства изображений или небольших файлов он также может быть больше, чем Size . Это потому, что изображения уже сжаты, и их повторное сжатие просто увеличивает накладные расходы. Не утруждайте себя сжатием изображений, вы не получите свободного места на вашем жестком диске.

5. Правильно. Если только вы не имеете дело со старыми форматами, подобные BMP этому, не имеют встроенного сжатия.

Ответ №1:

Мы можем сделать это разными способами,

один из лучших способов — преобразовать все изображения в формат 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 и веб-сервиса и передаю файл как 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 SettingsRasmiMy DocumentsVisual Studio2008WebSitescompressImageFileLogo");
                 imgCompress.Save(httpPostedFile.FileName, HttpContext.Current.Server.MapPath("~/Download/"));

             }
         }
     }