Crea un'immagine in miniatura


96

Voglio visualizzare l'immagine in miniatura in una visualizzazione griglia dalla posizione del file. Come generare quello del .jpegfile? Sto usando il C#linguaggio con asp.net.


6
ImageResizer è una libreria sicura per il server progettata per fare esattamente ciò di cui hai bisogno. A differenza di GetThumbnailImage, produce risultati di alta qualità e, a differenza degli esempi di codice, non perde memoria come un setaccio. Potrebbe non interessarti ora, ma lo farai tra qualche mese quando sarai immerso fino alle ginocchia nei dump del core.
Lilith River



ImageResizer è fantastico, ma non è gratuito
Boban Stojanovski il

Risposte:


222

Devi usare il GetThumbnailImagemetodo nella Imageclasse:

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

Ecco un esempio approssimativo che prende un file immagine e ne crea un'immagine in miniatura, quindi lo salva di nuovo su disco.

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

Si trova nello spazio dei nomi System.Drawing (in System.Drawing.dll).

Comportamento:

Se l'immagine contiene un'immagine miniatura incorporata, questo metodo recupera la miniatura incorporata e la ridimensiona alla dimensione richiesta. Se l'immagine non contiene un'immagine in miniatura incorporata, questo metodo crea un'immagine in miniatura ridimensionando l'immagine principale.


Importante: la sezione delle note del collegamento Microsoft sopra segnala alcuni potenziali problemi:

Il GetThumbnailImagemetodo funziona bene quando l'immagine in miniatura richiesta ha una dimensione di circa 120 x 120 pixel. Se richiedi un'immagine in miniatura di grandi dimensioni (ad esempio, 300 x 300) da un'immagine che ha una miniatura incorporata, potrebbe esserci una notevole perdita di qualità nell'immagine in miniatura .

Potrebbe essere meglio ridimensionare l'immagine principale (invece di ridimensionare la miniatura incorporata) chiamando il DrawImagemetodo.


5
Può essere utilizzato solo su immagini JPG in generale. Se provi a ridimensionare un'immagine PNG come questa, riceverai questo errore.
HBlackorby

In realtà, l'ho usato per ottenere una miniatura 400x225 di una foto full hd e la dimensione della "miniatura" risultante era 200 kB (originale 350 kB). Questo metodo è qualcosa da evitare.
Vojtěch Dohnal

1
@NathanaelJones, dici sul serio? ImageResizer non è gratuito per le aziende.
Ciaran Gallagher

26

Il codice seguente scriverà un'immagine proporzionale alla risposta, puoi modificare il codice per il tuo scopo:

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

Ho fornito il percorso del file locale nel percorso della stringa. restituisce "il formato del percorso specificato non è supportato".
Gopal Palraj

ho dato in questo modo ... var path = @ "C: \ Users \ Gopal \ Desktop \ files.jpeg"; Bitmap srcBmp = nuovo Bitmap (percorso);
Gopal Palraj

Per coloro che utilizzano HttpResponseMessage:response.Content = new ByteArrayContent(memoryStream.ToArray());
Hp93

attenzione, questo codice presuppone che le immagini siano "orizzontali" (paesaggio)
Alex

8

Ecco un esempio completo di come creare un'immagine più piccola (miniatura). Questo frammento ridimensiona l'immagine, la ruota quando necessario (se il telefono era tenuto verticalmente) e riempie l'immagine se si desidera creare pollici quadrati. Questo frammento crea un JPEG, ma può essere facilmente modificato per altri tipi di file. Anche se l'immagine fosse più piccola della dimensione massima consentita, l'immagine verrà comunque compressa e la sua risoluzione modificata per creare immagini dello stesso dpi e livello di compressione.

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

Per gli utenti asp.net un piccolo esempio di come caricare un file, ridimensionarlo e visualizzare il risultato sulla pagina.

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

Mi è piaciuto questo esempio di codice e ho scelto di usarlo. Tuttavia, indipendentemente dalle modifiche apportate alle varie opzioni (imageResolution, compressionLevel, CompositingMode, CompositingQuality, SmoothingMode, InterpolationMode, PixelOffsetMode), le dimensioni del file immagine hanno ridotto solo una piccola quantità. E non ho mai visto alcuna differenza nell'immagine creata. Alla fine, ho scelto di salvare l'immagine in un file anziché nel flusso di memoria e sono stato in grado di vedere cambiamenti drastici. Per chiunque lo utilizzi, sembra che il salvataggio in un flusso di memoria non influisca sull'immagine restituita.
BLaminack

1

Ecco un esempio per convertire un'immagine ad alta risoluzione nella dimensione della 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;
}

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.