Criar imagem em miniatura

96

Quero exibir a imagem em miniatura em um gridview do local do arquivo. Como gerar o .jpegarquivo? Estou usando uma C#linguagem com asp.net.

Cisne Vermelho
fonte
6
ImageResizer é uma biblioteca segura para o servidor projetada para fazer exatamente o que você precisa. Ao contrário de GetThumbnailImage, ele produz resultados de alta qualidade e, ao contrário dos exemplos de código, não vaza memória como uma peneira. Você pode não se importar agora, mas vai se importar em alguns meses, quando estiver afundado até os joelhos.
Lilith River
Visualizar: docs.microsoft.com/en-us/dotnet/api/…
Md. Sabbir Ahamed
ImageResizer é ótimo, mas não é grátis
Boban Stojanovski,

Respostas:

222

Você tem que usar o GetThumbnailImagemétodo na Imageclasse:

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

Aqui está um exemplo aproximado que pega um arquivo de imagem e cria uma imagem em miniatura a partir dele, depois salva de volta no disco.

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

Ele está no namespace System.Drawing (em System.Drawing.dll).

Comportamento:

Se a imagem contém uma imagem em miniatura incorporada, este método recupera a miniatura incorporada e dimensiona-a para o tamanho solicitado. Se a imagem não contiver uma imagem em miniatura incorporada, este método cria uma imagem em miniatura dimensionando a imagem principal.


Importante: a seção de comentários do link da Microsoft acima avisa sobre alguns problemas potenciais:

o GetThumbnailImage método funciona bem quando a imagem em miniatura solicitada tem um tamanho de cerca de 120 x 120 pixels. Se você solicitar uma imagem em miniatura grande (por exemplo, 300 x 300) de uma imagem que possui uma miniatura incorporada, pode haver uma perda perceptível de qualidade na imagem em miniatura .

Pode ser melhor dimensionar a imagem principal (em vez de dimensionar a miniatura incorporada) chamando o DrawImagemétodo.

Russell Troywest
fonte
5
Ele só pode ser usado em imagens JPG em geral. Se você tentar redimensionar uma imagem PNG dessa forma, receberá este erro.
HBlackorby
Na verdade, usei isso para obter miniaturas 400x225 de uma foto full hd e o tamanho da "miniatura" resultante foi de 200 kB (Original 350 kB). Este método deve ser evitado.
Vojtěch Dohnal
1
@NathanaelJones, você está falando sério? ImageResizer não é gratuito para empresas.
Ciaran Gallagher
26

O código a seguir escreverá uma imagem proporcional à resposta, você pode modificar o código para sua finalidade:

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
fonte
Eu dei meu caminho de arquivo local em caminho de string. ele retorna "o formato de caminho fornecido não é suportado".
Gopal Palraj
dei assim ... var path = @ "C: \ Users \ Gopal \ Desktop \ files.jpeg"; Bitmap srcBmp = novo Bitmap (caminho);
Gopal Palraj
Para quem usa HttpResponseMessage:response.Content = new ByteArrayContent(memoryStream.ToArray());
Hp93
cuidado, este código presume que as imagens são "horizontais" (paisagem)
Alex
8

Aqui está um exemplo completo de como criar uma imagem menor (miniatura). Este trecho redimensiona a imagem, gira quando necessário (se um telefone foi segurado verticalmente) e preenche a imagem se você deseja criar polegares quadrados. Este trecho cria um JPEG, mas pode ser facilmente modificado para outros tipos de arquivo. Mesmo que a imagem seja menor que o tamanho máximo permitido, a imagem ainda será compactada e sua resolução alterada para criar imagens com o mesmo dpi e nível de compactação.

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 os usuários do asp.net, um pequeno exemplo de como carregar um arquivo, redimensioná-lo e exibir o resultado na 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
fonte
Gostei deste exemplo de código e optei por usá-lo. No entanto, independentemente das alterações que fiz nas várias opções (imageResolution, compressionLevel, CompositingMode, CompositingQuality, SmoothingMode, InterpolationMode, PixelOffsetMode), o tamanho do arquivo de imagem apenas reduziu um pouco. E nunca vi diferença na imagem criada. Por fim, optei por salvar a imagem em um arquivo em vez de no fluxo de memória e pude ver mudanças drásticas. Para quem está usando isso, parece que salvar em um fluxo de memória não afeta a imagem retornada.
BLaminack
1

Aqui está um exemplo para converter imagem de alta resolução em tamanho 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;
}

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

kamalpreet
fonte