在asp.net中调整图像大小而不丢失图像质量

时间:2022-03-20 21:49:27

I am developing an ASP.NET 3.5 web application in which I am allowing my users to upload either jpeg,gif,bmp or png images. If the uploaded image dimensions are greater then 103 x 32 the I want to resize the uploaded image to 103 x 32. I have read some blog posts and articles, and have also tried some of the code samples but nothing seems to work right. Has anyone succeed in doing this?

我正在开发ASP。NET 3.5 web应用程序,允许我的用户上传jpeg、gif、bmp或png图像。如果上传的图像尺寸大于103x32,我想把上传的图像调整到103x32。我读过一些博客和文章,也尝试过一些代码示例,但似乎没有什么是正确的。有人成功地做到这一点吗?

4 个解决方案

#1


31  

I had the same problem a while back and dealt with it this way:

我以前也遇到过同样的问题,我是这样处理的:

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

I just read that this was the the way to get highest quality.

我刚刚读到,这是获得最高质量的方法。

#2


41  

This is the code I use. It supports rotation, and also sets the image resolution to the JPEG standards of 72dpi@24-bit color (by default GDI+ saves images at 96dpi@32-bit color). It also fixes the black/gray border problem that some people experience when resizing images.

这是我使用的代码。它支持旋转,并将图像分辨率设置为JPEG标准的72dpi@24位颜色(默认情况下GDI+将图像保存为96dpi@32位颜色)。它还解决了一些人在调整图像大小时遇到的黑/灰边界问题。

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

#3


2  

The code associated with the actual resizing of the bitmap is as follows.

与位图的实际大小相关的代码如下所示。

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

This blog post contains full source code for image resizing, and compression (if required)

这篇博文包含了图像大小调整和压缩的完整源代码(如果需要的话)

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

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

#4


0  

I've successfully done this by creating a bitmap of the image and then resizing the bitmap...I'm not sure if this is the best or most efficient way of doing this, but it works for me.

通过创建图像的位图,然后调整位图的大小,我成功地做到了这一点。我不确定这是最好的还是最有效的方法,但它对我很有效。

In my case, I needed to cut the height and width of the image by half.

在我的例子中,我需要将图像的高度和宽度减半。

Here's what I did.

这是我所做的。

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

#1


31  

I had the same problem a while back and dealt with it this way:

我以前也遇到过同样的问题,我是这样处理的:

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

I just read that this was the the way to get highest quality.

我刚刚读到,这是获得最高质量的方法。

#2


41  

This is the code I use. It supports rotation, and also sets the image resolution to the JPEG standards of 72dpi@24-bit color (by default GDI+ saves images at 96dpi@32-bit color). It also fixes the black/gray border problem that some people experience when resizing images.

这是我使用的代码。它支持旋转,并将图像分辨率设置为JPEG标准的72dpi@24位颜色(默认情况下GDI+将图像保存为96dpi@32位颜色)。它还解决了一些人在调整图像大小时遇到的黑/灰边界问题。

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

#3


2  

The code associated with the actual resizing of the bitmap is as follows.

与位图的实际大小相关的代码如下所示。

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

This blog post contains full source code for image resizing, and compression (if required)

这篇博文包含了图像大小调整和压缩的完整源代码(如果需要的话)

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

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

#4


0  

I've successfully done this by creating a bitmap of the image and then resizing the bitmap...I'm not sure if this is the best or most efficient way of doing this, but it works for me.

通过创建图像的位图,然后调整位图的大小,我成功地做到了这一点。我不确定这是最好的还是最有效的方法,但它对我很有效。

In my case, I needed to cut the height and width of the image by half.

在我的例子中,我需要将图像的高度和宽度减半。

Here's what I did.

这是我所做的。

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