2010-02-23 38 views
33

Estoy desarrollando una aplicación web ASP.NET 3.5 en la que estoy permitiendo a mis usuarios subir imágenes jpeg, gif, bmp o png. Si las dimensiones de la imagen cargada son mayores que 103 x 32, quiero cambiar el tamaño de la imagen cargada a 103 x 32. He leído algunas publicaciones y artículos en el blog, y también he probado algunas muestras del código pero nada parece funcionar bien. ¿Alguien ha tenido éxito en hacer esto?Cambiar el tamaño de una imagen en asp.net sin perder la calidad de imagen

+1

enviar el código que está utilizando eso no funciona, y explicar de qué manera se No funciona. – RedFilter

+1

¿Quieres forzar 103x32? O mejor ajuste? – citronas

+0

'ImageBuilder.Current.Build (HttpPostedFile file, ruta de la cadena, nueva ResizeSettings (" width = 103 & height = 32 "))' 'Usando la [Image Resizer library] (http://imageresizing.net) –

Respuesta

30

que tenían el mismo problema hace un tiempo y se ocupó 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 manera de conseguir la más alta calidad.

+0

+1 Nice : "Doble relación = Math.Max ​​(xRatio, yRatio);" – Joop

+0

En una nueva versión, también tomo en cuenta que no extenderé las imágenes, pero debería ser bastante fácil de resolver :-P (sugerencia: 'ration = Math.Min (ration, 1.0);') – Alxandr

+0

Bien , hay unos [algunos ajustes más que ayudarán] (http://nathanaeljones.com/163/20-image-resizing-pitfalls/), como el desplazamiento de píxeles. –

0

He hecho esto con éxito creando un mapa de bits de la imagen y luego cambiando el tamaño del mapa de bits ... No estoy seguro de si esta es la mejor manera o la más eficiente de hacerlo, pero a mí me funciona.

En mi caso, necesitaba cortar el alto y el ancho de la imagen a la mitad.

Esto es lo que hice.

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

Este es el código que uso. Es compatible con la rotación y también establece la resolución de la imagen en los estándares JPEG de 72 ppp a 24 bits de color (por defecto, GDI + guarda imágenes a 96 ppp a color de 32 bits). También soluciona el problema de borde negro/gris que experimentan algunas personas al cambiar el tamaño de las imágenes.

/// <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

Gracias por señalar la solución al problema del borde gris. –

+0

Como arriba, gracias por la corrección del problema fronterizo. –

+0

¡Esta solución cambia el tamaño sin cambiar los colores de la imagen original! ¡Gran trabajo! – danyolgiax

2

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

Este blog contiene código fuente completo para una imagen de cambio de tamaño y compresión (si es necesario)

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

Cuestiones relacionadas