Изменение размера изображения в asp.net без потери качества изображения - PullRequest
35 голосов
/ 23 февраля 2010

Я занимаюсь разработкой веб-приложения ASP.NET 3.5, в котором я разрешаю пользователям загружать изображения в формате jpeg, gif, bmp или png. Если размер загружаемого изображения больше 103 x 32, я хочу изменить размер загруженного изображения до 103 x 32. Я прочитал некоторые посты и статьи в блоге, а также попробовал некоторые примеры кода, но, похоже, ничего не работает. Кому-нибудь удалось это сделать?

Ответы [ 7 ]

41 голосов
/ 24 февраля 2010

Это код, который я использую. Он поддерживает вращение, а также устанавливает разрешение изображения в соответствии со стандартами JPEG 72dpi @ 24-bit color (по умолчанию GDI + сохраняет изображения с 96dpi @ 32-bit color). Это также устраняет проблему черной / серой границы, с которой некоторые люди сталкиваются при изменении размера изображений.

/// <summary>
/// Resizes and rotates an image, keeping the original aspect ratio. Does not dispose the original
/// Image instance.
/// </summary>
/// <param name="image">Image instance</param>
/// <param name="width">desired width</param>
/// <param name="height">desired height</param>
/// <param name="rotateFlipType">desired RotateFlipType</param>
/// <returns>new resized/rotated Image instance</returns>
public static Image Resize(Image image, int width, int height, RotateFlipType rotateFlipType)
{
    // clone the Image instance, since we don't want to resize the original Image instance
    var rotatedImage = image.Clone() as Image;
    rotatedImage.RotateFlip(rotateFlipType);
    var newSize = CalculateResizedDimensions(rotatedImage, width, height);

    var resizedImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format32bppArgb);
    resizedImage.SetResolution(72, 72);

    using (var graphics = Graphics.FromImage(resizedImage))
    {
        // set parameters to create a high-quality thumbnail
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.AntiAlias;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

        // use an image attribute in order to remove the black/gray border around image after resize
        // (most obvious on white images), see this post for more information:
        // http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx
        using (var attribute = new ImageAttributes())
        {
            attribute.SetWrapMode(WrapMode.TileFlipXY);

            // draws the resized image to the bitmap
            graphics.DrawImage(rotatedImage, new Rectangle(new Point(0, 0), newSize), 0, 0, rotatedImage.Width, rotatedImage.Height, GraphicsUnit.Pixel, attribute);
        }
    }

    return resizedImage;
}

/// <summary>
/// Calculates resized dimensions for an image, preserving the aspect ratio.
/// </summary>
/// <param name="image">Image instance</param>
/// <param name="desiredWidth">desired width</param>
/// <param name="desiredHeight">desired height</param>
/// <returns>Size instance with the resized dimensions</returns>
private static Size CalculateResizedDimensions(Image image, int desiredWidth, int desiredHeight)
{
    var widthScale = (double)desiredWidth / image.Width;
    var heightScale = (double)desiredHeight / image.Height;

    // scale to whichever ratio is smaller, this works for both scaling up and scaling down
    var scale = widthScale < heightScale ? widthScale : heightScale;

    return new Size
                   {
                       Width = (int) (scale * image.Width),
                       Height = (int) (scale * image.Height)
                   };
}
34 голосов
/ 23 февраля 2010

У меня была такая же проблема некоторое время назад, и я справился с ней следующим образом:

private Image RezizeImage(Image img, int maxWidth, int maxHeight)
{
    if(img.Height < maxHeight && img.Width < maxWidth) return img;
    using (img)
    {
        Double xRatio = (double)img.Width / maxWidth;
        Double yRatio = (double)img.Height / maxHeight;
        Double ratio = Math.Max(xRatio, yRatio);
        int nnx = (int)Math.Floor(img.Width / ratio);
        int nny = (int)Math.Floor(img.Height / ratio);
        Bitmap cpy = new Bitmap(nnx, nny, PixelFormat.Format32bppArgb);
        using (Graphics gr = Graphics.FromImage(cpy))
        {
            gr.Clear(Color.Transparent);

            // This is said to give best quality when resizing images
            gr.InterpolationMode = InterpolationMode.HighQualityBicubic;

            gr.DrawImage(img,
                new Rectangle(0, 0, nnx, nny),
                new Rectangle(0, 0, img.Width, img.Height),
                GraphicsUnit.Pixel);
        }
        return cpy;
    }

}

private MemoryStream BytearrayToStream(byte[] arr)
{
    return new MemoryStream(arr, 0, arr.Length);
}

private void HandleImageUpload(byte[] binaryImage)
{
    Image img = RezizeImage(Image.FromStream(BytearrayToStream(binaryImage)), 103, 32);
    img.Save("IMAGELOCATION.png", System.Drawing.Imaging.ImageFormat.Gif);
}

Я только что прочитал, что это был способ получить высшее качество.

2 голосов
/ 20 августа 2010

Код, связанный с фактическим изменением размера растрового изображения, выглядит следующим образом.

public static Bitmap ResizeBitmap( Bitmap originalBitmap, int requiredHeight, int requiredWidth )
{
   int[] heightWidthRequiredDimensions;

   // Pass dimensions to worker method depending on image type required
   heightWidthRequiredDimensions = WorkDimensions(originalBitmap.Height, originalBitmap.Width, requiredHeight, requiredWidth);


   Bitmap resizedBitmap = new Bitmap( heightWidthRequiredDimensions[1],
                                      heightWidthRequiredDimensions[0] );

   const float resolution = 72;

   resizedBitmap.SetResolution( resolution, resolution );

   Graphics graphic = Graphics.FromImage( (Image) resizedBitmap );

   graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
   graphic.DrawImage( originalBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height );

   graphic.Dispose();
   originalBitmap.Dispose();
   //resizedBitmap.Dispose(); // Still in use


   return resizedBitmap;
}


private static int[] WorkDimensions(int originalHeight, int originalWidth, int requiredHeight, int requiredWidth )
{
   int imgHeight = 0;
   int imgWidth = 0;

   imgWidth = requiredHeight;
   imgHeight = requiredWidth;


   int requiredHeightLocal = originalHeight;
   int requiredWidthLocal = originalWidth;

   double ratio = 0;

   // Check height first
   // If original height exceeds maximum, get new height and work ratio.
   if ( originalHeight > imgHeight )
   {
       ratio = double.Parse( ( (double) imgHeight / (double) originalHeight ).ToString() );
       requiredHeightLocal = imgHeight;
       requiredWidthLocal = (int) ( (decimal) originalWidth * (decimal) ratio );
   }

   // Check width second. It will most likely have been sized down enough
   // in the previous if statement. If not, change both dimensions here by width.
   // If new width exceeds maximum, get new width and height ratio.
   if ( requiredWidthLocal >= imgWidth )
   {
       ratio = double.Parse( ( (double) imgWidth / (double) originalWidth ).ToString() );
       requiredWidthLocal = imgWidth;
       requiredHeightLocal = (int) ( (double) originalHeight * (double) ratio );
   }

   int[] heightWidthDimensionArr = { requiredHeightLocal, requiredWidthLocal };

   return heightWidthDimensionArr;
}
}

Этот пост содержит полный исходный код для изменения размера изображения и сжатия (при необходимости)

http://blog.bombdefused.com/2010/08/bulk-image-optimizer-in-c-full-source.html

0 голосов
/ 29 марта 2019
   // Fixed Size Image Generate Code
 protected void btnUpload_Click(object sender, EventArgs e)
    {

 decimal size = Math.Round(((decimal)fUpload.PostedFile.ContentLength / (decimal)1024), 2);
        DirectoryInfo dir = new DirectoryInfo(MapPath("Images"));
        FileInfo[] files = dir.GetFiles();
         foreach (FileInfo info in files)
        {
              decimal size2 = Math.Round(((decimal)info.Length / (decimal)1024), 2);
              string Image_name = info.Name.ToString();
              string targetPath = Server.MapPath("Images/" + Image_name);
              string strm = Server.MapPath("Images/" + Image_name);
              var targetFile = targetPath;
              ReduceImageSize(0.5, strm, targetFile, Image_name);
         }
}

 public void ReduceImageSize(double scaleFactor, String sourcePath, string targetPath, string Image_name)
    {

 // Fixed Size Image Generate Code

       public void ReduceImageSize(double scaleFactor, String sourcePath, string targetPath, string Image_name)
    {
        using (var image = System.Drawing.Image.FromFile(sourcePath))
               {

            //var newWidth = (int)(image.Width  * scaleFactor);
            //var newHeight = (int)(image.Height * scaleFactor);
            var newWidth = (int)(500 * scaleFactor);
            var newHeight = (int)(500 * scaleFactor);
            var thumbnailImg = new Bitmap(newWidth, newHeight);
            var thumbGraph = Graphics.FromImage(thumbnailImg);
            thumbGraph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            thumbGraph.SmoothingMode = SmoothingMode.HighQuality;
            thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
            var imageRectangle = new System.Drawing.RectangleF (0, 0, newWidth, newHeight);
            thumbGraph.DrawImage(image, imageRectangle);


            MemoryStream s = new MemoryStream();
            thumbnailImg.Save(s, System.Drawing.Imaging.ImageFormat.Png);
            s.Position = 0;
            byte[] image2 = new byte[525000];// 512kb =525000  
            s.Read(image2, 0, image2.Length);

            Guid guid = Guid.NewGuid();
            string Server_MapPath = Server.MapPath("~/Image Compress/" + Image_name + guid.ToString() + ".PNG");//Your Compressor Image Save Path

            System.IO.FileStream fs = new System.IO.FileStream(Server_MapPath, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite);
            fs.Write(image2, 0, image2.Length);

        }
    }
0 голосов
/ 29 марта 2019
  decimal size = Math.Round(((decimal)fUpload.PostedFile.ContentLength / (decimal)1024), 2);
        DirectoryInfo dir = new DirectoryInfo(MapPath("Images"));
        FileInfo[] files = dir.GetFiles();
         foreach (FileInfo info in files)
        {
              decimal size2 = Math.Round(((decimal)info.Length / (decimal)1024), 2);
              string Image_name = info.Name.ToString();
              string targetPath = Server.MapPath("Images/" + Image_name);
              string strm = Server.MapPath("Images/" + Image_name);
              var targetFile = targetPath;
              ReduceImageSize(0.5, strm, targetFile, Image_name);
         }
0 голосов
/ 18 октября 2018
public static System.Drawing.Image ScaleImage(System.Drawing.Image image, int maxImageHeight)
    {
        /* we will resize image based on the height/width ratio by passing expected height as parameter. Based on Expected height and current image height, new ratio will be arrived and using the same we will do the resizing of image width. */

        var ratio = (double)maxImageHeight / image.Height;
        var newWidth = (int)(image.Width * ratio);
        var newHeight = (int)(image.Height * ratio);
        var newImage = new Bitmap(newWidth, newHeight);
        using (var g = Graphics.FromImage(newImage))
        {
            g.DrawImage(image, 0, 0, newWidth, newHeight);
        }
        return newImage;
    }
0 голосов
/ 23 февраля 2010

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

В моем случае мне нужно было сократить высоту и ширину изображения вдвое.

Вот что я сделал.

   private Image getImageFromBytes(byte[] myByteArray)
    {                        
        System.IO.MemoryStream newImageStream = new System.IO.MemoryStream(myByteArray, 0, myByteArray.Length);
        Image image = Image.FromStream(newImageStream, true);
        Bitmap resized = new Bitmap(image, image.Width / 2, image.Height / 2);
        image.Dispose();
        newImageStream.Dispose();
        return resized;
    }
...