Crear imagen en miniatura

96

Quiero mostrar una imagen en miniatura en una vista de cuadrícula desde la ubicación del archivo. ¿Cómo generar eso de .jpegarchivo? Estoy usando el C#lenguaje con asp.net.

Cisne rojo
fuente
6
ImageResizer es una biblioteca segura para el servidor diseñada para hacer exactamente lo que necesita. A diferencia de GetThumbnailImage, produce resultados de alta calidad y, a diferencia de las muestras de código, no pierde memoria como un tamiz. Es posible que ahora no le importe, pero lo hará en unos meses cuando esté sumergido hasta las rodillas.
Lilith River
Vea esto: docs.microsoft.com/en-us/dotnet/api/…
Md. Sabbir Ahamed
ImageResizer es genial, pero no es gratis
Boban Stojanovski

Respuestas:

222

Tienes que usar el GetThumbnailImagemétodo en la Imageclase:

https://msdn.microsoft.com/en-us/library/8t23aykb%28v=vs.110%29.aspx

Aquí hay un ejemplo aproximado que toma un archivo de imagen y crea una imagen en miniatura a partir de él, luego lo guarda en el disco.

Image image = Image.FromFile(fileName);
Image thumb = image.GetThumbnailImage(120, 120, ()=>false, IntPtr.Zero);
thumb.Save(Path.ChangeExtension(fileName, "thumb"));

Está en el espacio de nombres System.Drawing (en System.Drawing.dll).

Comportamiento:

Si la imagen contiene una imagen en miniatura incrustada, este método recupera la miniatura incrustada y la escala al tamaño solicitado. Si la imagen no contiene una imagen en miniatura incrustada, este método crea una imagen en miniatura escalando la imagen principal.


Importante: la sección de comentarios del enlace de Microsoft anterior advierte sobre ciertos problemas potenciales:

El GetThumbnailImagemétodo funciona bien cuando la imagen en miniatura solicitada tiene un tamaño de aproximadamente 120 x 120 píxeles. Si solicita una imagen en miniatura grande (por ejemplo, 300 x 300) de una imagen que tiene una miniatura incrustada, podría haber una pérdida notable de calidad en la imagen en miniatura .

Podría ser mejor escalar la imagen principal (en lugar de escalar la miniatura incrustada) llamando al DrawImagemétodo.

Russell Troywest
fuente
5
Generalmente, solo se puede utilizar en imágenes JPG. Si intenta cambiar el tamaño de una imagen PNG como esta, obtendrá este error.
HBlackorby
Realmente, usé esto para obtener una miniatura de 400x225 de una foto full hd y el tamaño de la "miniatura" resultante fue de 200 kB (original 350 kB). Este método es algo que debe evitarse.
Vojtěch Dohnal
1
@NathanaelJones, ¿hablas en serio? ImageResizer no es gratuito para empresas.
Ciaran Gallagher
26

El siguiente código escribirá una imagen proporcional a la respuesta, puede modificar el código para su propósito:

public void WriteImage(string path, int width, int height)
{
    Bitmap srcBmp = new Bitmap(path);
    float ratio = srcBmp.Width / srcBmp.Height;
    SizeF newSize = new SizeF(width, height * ratio);
    Bitmap target = new Bitmap((int) newSize.Width,(int) newSize.Height);
    HttpContext.Response.Clear();
    HttpContext.Response.ContentType = "image/jpeg";
    using (Graphics graphics = Graphics.FromImage(target))
    {
        graphics.CompositingQuality = CompositingQuality.HighSpeed;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.CompositingMode = CompositingMode.SourceCopy;
        graphics.DrawImage(srcBmp, 0, 0, newSize.Width, newSize.Height);
        using (MemoryStream memoryStream = new MemoryStream()) 
        {
            target.Save(memoryStream, ImageFormat.Jpeg);
            memoryStream.WriteTo(HttpContext.Response.OutputStream);
        }
    }
    Response.End();
}
Priyan R
fuente
Di mi ruta de archivo local en ruta de cadena. devuelve "el formato de ruta dado no es compatible".
Gopal Palraj
di así ... var path = @ "C: \ Users \ Gopal \ Desktop \ files.jpeg"; Mapa de bits srcBmp = nuevo mapa de bits (ruta);
Gopal Palraj
Para aquellos que usan HttpResponseMessage:response.Content = new ByteArrayContent(memoryStream.ToArray());
Hp93
cuidado, este código asume que las imágenes son "horizontales" (paisaje)
Alex
8

Aquí hay un ejemplo completo de cómo crear una imagen más pequeña (miniatura). Este fragmento cambia el tamaño de la imagen, la gira cuando es necesario (si se sostuvo un teléfono verticalmente) y rellena la imagen si desea crear pulgares cuadrados. Este fragmento crea un archivo JPEG, pero se puede modificar fácilmente para otros tipos de archivos. Incluso si la imagen fuera más pequeña que el tamaño máximo permitido, la imagen seguirá comprimida y su resolución alterada para crear imágenes del mismo nivel de compresión y ppp.

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

//set the resolution, 72 is usually good enough for displaying images on monitors
float imageResolution = 72;

//set the compression level. higher compression = better quality = bigger images
long compressionLevel = 80L;


public Image resizeImage(Image image, int maxWidth, int maxHeight, bool padImage)
{
    int newWidth;
    int newHeight;

    //first we check if the image needs rotating (eg phone held vertical when taking a picture for example)
    foreach (var prop in image.PropertyItems)
    {
        if (prop.Id == 0x0112)
        {
            int orientationValue = image.GetPropertyItem(prop.Id).Value[0];
            RotateFlipType rotateFlipType = getRotateFlipType(orientationValue);
            image.RotateFlip(rotateFlipType);
            break;
        }
    }

    //apply the padding to make a square image
    if (padImage == true)
    {
        image = applyPaddingToImage(image, Color.Red);
    }

    //check if the with or height of the image exceeds the maximum specified, if so calculate the new dimensions
    if (image.Width > maxWidth || image.Height > maxHeight)
    {
        double ratioX = (double)maxWidth / image.Width;
        double ratioY = (double)maxHeight / image.Height;
        double ratio = Math.Min(ratioX, ratioY);

        newWidth = (int)(image.Width * ratio);
        newHeight = (int)(image.Height * ratio);
    }
    else
    {
        newWidth = image.Width;
        newHeight = image.Height;
    }

    //start the resize with a new image
    Bitmap newImage = new Bitmap(newWidth, newHeight);

    //set the new resolution
    newImage.SetResolution(imageResolution, imageResolution);

    //start the resizing
    using (var graphics = Graphics.FromImage(newImage))
    {
        //set some encoding specs
        graphics.CompositingMode = CompositingMode.SourceCopy;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.SmoothingMode = SmoothingMode.HighQuality;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

        graphics.DrawImage(image, 0, 0, newWidth, newHeight);
    }

    //save the image to a memorystream to apply the compression level
    using (MemoryStream ms = new MemoryStream())
    {
        EncoderParameters encoderParameters = new EncoderParameters(1);
        encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, compressionLevel);

        newImage.Save(ms, getEncoderInfo("image/jpeg"), encoderParameters);

        //save the image as byte array here if you want the return type to be a Byte Array instead of Image
        //byte[] imageAsByteArray = ms.ToArray();
    }

    //return the image
    return newImage;
}


//=== image padding
public Image applyPaddingToImage(Image image, Color backColor)
{
    //get the maximum size of the image dimensions
    int maxSize = Math.Max(image.Height, image.Width);
    Size squareSize = new Size(maxSize, maxSize);

    //create a new square image
    Bitmap squareImage = new Bitmap(squareSize.Width, squareSize.Height);

    using (Graphics graphics = Graphics.FromImage(squareImage))
    {
        //fill the new square with a color
        graphics.FillRectangle(new SolidBrush(backColor), 0, 0, squareSize.Width, squareSize.Height);

        //put the original image on top of the new square
        graphics.DrawImage(image, (squareSize.Width / 2) - (image.Width / 2), (squareSize.Height / 2) - (image.Height / 2), image.Width, image.Height);
    }

    //return the image
    return squareImage;
}


//=== get encoder info
private ImageCodecInfo getEncoderInfo(string mimeType)
{
    ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();

    for (int j = 0; j < encoders.Length; ++j)
    {
        if (encoders[j].MimeType.ToLower() == mimeType.ToLower())
        {
            return encoders[j];
        }
    }

    return null;
}


//=== determine image rotation
private RotateFlipType getRotateFlipType(int rotateValue)
{
    RotateFlipType flipType = RotateFlipType.RotateNoneFlipNone;

    switch (rotateValue)
    {
        case 1:
            flipType = RotateFlipType.RotateNoneFlipNone;
            break;
        case 2:
            flipType = RotateFlipType.RotateNoneFlipX;
            break;
        case 3:
            flipType = RotateFlipType.Rotate180FlipNone;
            break;
        case 4:
            flipType = RotateFlipType.Rotate180FlipX;
            break;
        case 5:
            flipType = RotateFlipType.Rotate90FlipX;
            break;
        case 6:
            flipType = RotateFlipType.Rotate90FlipNone;
            break;
        case 7:
            flipType = RotateFlipType.Rotate270FlipX;
            break;
        case 8:
            flipType = RotateFlipType.Rotate270FlipNone;
            break;
        default:
            flipType = RotateFlipType.RotateNoneFlipNone;
            break;
    }

    return flipType;
}


//== convert image to base64
public string convertImageToBase64(Image image)
{
    using (MemoryStream ms = new MemoryStream())
    {
        //convert the image to byte array
        image.Save(ms, ImageFormat.Jpeg);
        byte[] bin = ms.ToArray();

        //convert byte array to base64 string
        return Convert.ToBase64String(bin);
    }
}

Para los usuarios de asp.net, un pequeño ejemplo de cómo cargar un archivo, cambiar su tamaño y mostrar el resultado en la página.

//== the button click method
protected void Button1_Click(object sender, EventArgs e)
{
    //check if there is an actual file being uploaded
    if (FileUpload1.HasFile == false)
    {
        return;
    }

    using (Bitmap bitmap = new Bitmap(FileUpload1.PostedFile.InputStream))
    {
        try
        {
            //start the resize
            Image image = resizeImage(bitmap, 256, 256, true);

            //to visualize the result, display as base64 image
            Label1.Text = "<img src=\"data:image/jpg;base64," + convertImageToBase64(image) + "\">";

            //save your image to file sytem, database etc here
        }
        catch (Exception ex)
        {
            Label1.Text = "Oops! There was an error when resizing the Image.<br>Error: " + ex.Message;
        }
    }
}
VDWWD
fuente
Me gustó este ejemplo de código y elegí usarlo. Sin embargo, independientemente de los cambios que hice en las diversas opciones (imageResolution, compressingLevel, CompositingMode, CompositingQuality, SmoothingMode, InterpolationMode, PixelOffsetMode), el tamaño del archivo de imagen solo se redujo una pequeña cantidad. Y nunca vi ninguna diferencia en la imagen creada. Finalmente, elegí guardar la imagen en un archivo en lugar del flujo de memoria y pude ver cambios drásticos. Para cualquiera que use esto, parece que guardar en una secuencia de memoria no afecta la imagen devuelta.
BLaminack
1

Aquí hay un ejemplo para convertir una imagen de alta resolución en tamaño de miniatura:

protected void Button1_Click(object sender, EventArgs e)
{
    //----------        Getting the Image File
    System.Drawing.Image img = System.Drawing.Image.FromFile(Server.MapPath("~/profile/Avatar.jpg"));

    //----------        Getting Size of Original Image
    double imgHeight = img.Size.Height;
    double imgWidth = img.Size.Width;

    //----------        Getting Decreased Size
    double x = imgWidth / 200;
    int newWidth = Convert.ToInt32(imgWidth / x);
    int newHeight = Convert.ToInt32(imgHeight / x);

    //----------        Creating Small Image
    System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
    System.Drawing.Image myThumbnail = img.GetThumbnailImage(newWidth, newHeight, myCallback, IntPtr.Zero);

    //----------        Saving Image
    myThumbnail.Save(Server.MapPath("~/profile/NewImage.jpg"));
}
public bool ThumbnailCallback()
{
    return false;
}

Fuente: http://iknowledgeboy.blogspot.in/2014/03/c-creating-thumbnail-of-large-image-by.html

Kamalpreet
fuente