Saltar al contenido

Cambiar el tamaño de una imagen en asp.net sin perder la calidad de la imagen

Eva, miembro de nuestro staff, nos ha hecho el favor de escribir este enunciado ya que controla muy bien dicho tema.

Solución:

Este es el código que utilizo. Admite la rotación y también establece la resolución de la imagen según los estándares JPEG de [email protected] color (por defecto, GDI + guarda imágenes en [email protected] color). También soluciona el problema del borde negro / gris que algunas personas experimentan al cambiar el tamaño de las imágenes.

/// 
/// Resizes and rotates an image, keeping the original aspect ratio. Does not dispose the original
/// Image instance.
/// 
/// Image instance
/// desired width
/// desired height
/// desired RotateFlipType
/// new resized/rotated Image instance
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;


/// 
/// Calculates resized dimensions for an image, preserving the aspect ratio.
/// 
/// Image instance
/// desired width
/// desired height
/// Size instance with the resized dimensions
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)
                   ;

Tuve el mismo problema hace un tiempo y lo resolví de esta manera:

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

Acabo de leer que esta era la forma de obtener la máxima calidad.

El código asociado con el cambio de tamaño real del mapa de bits es el siguiente.

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;

}

Esta publicación de blog contiene el código fuente completo para el cambio de tamaño de la imagen y la compresión (si es necesario)

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

Si crees que ha resultado de utilidad nuestro artículo, sería de mucha ayuda si lo compartieras con el resto programadores y nos ayudes a dar difusión a este contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *