Créer une image miniature

96

Je souhaite afficher une image miniature dans une vue en grille à partir de l'emplacement du fichier. Comment générer celui du .jpegfichier? J'utilise la C#langue avec asp.net.

Cygne rouge
la source
6
ImageResizer est une bibliothèque sécurisée pour le serveur conçue pour faire exactement ce dont vous avez besoin. Contrairement à GetThumbnailImage, il produit des résultats de haute qualité et, contrairement aux exemples de code, il ne perd pas de mémoire comme un tamis. Vous ne vous en souciez peut-être pas maintenant, mais vous le ferez dans quelques mois lorsque vous serez à genoux dans des décharges de troncature.
Lilith River
Voir ceci: docs.microsoft.com/en-us/dotnet/api/…
Md. Sabbir Ahamed
ImageResizer est génial, mais ce n'est pas gratuit
Boban Stojanovski

Réponses:

222

Vous devez utiliser la GetThumbnailImageméthode dans la Imageclasse:

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

Voici un exemple approximatif qui prend un fichier image et en fait une image miniature, puis l'enregistre sur le disque.

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

Il se trouve dans l'espace de noms System.Drawing (dans System.Drawing.dll).

Comportement:

Si l'image contient une image miniature incorporée, cette méthode récupère la miniature incorporée et la met à l'échelle à la taille demandée. Si l'image ne contient pas d'image miniature intégrée, cette méthode crée une image miniature en redimensionnant l'image principale.


Important: la section remarques du lien Microsoft ci-dessus met en garde contre certains problèmes potentiels:

La GetThumbnailImageméthode fonctionne bien lorsque l'image miniature demandée a une taille d'environ 120 x 120 pixels. Si vous demandez une grande image miniature (par exemple, 300 x 300) à partir d'une image qui a une miniature intégrée, il peut y avoir une perte de qualité notable dans l'image miniature .

Il peut être préférable de mettre à l'échelle l'image principale (au lieu de mettre à l'échelle la vignette intégrée) en appelant la DrawImageméthode.

Russell Troywest
la source
5
Il ne peut être utilisé que sur les images JPG en général. Si vous essayez de redimensionner une image PNG comme celle-ci, vous obtiendrez cette erreur.
HBlackorpar
Vraiment, utilisé ceci pour obtenir la vignette 400x225 d'une photo Full HD et la taille de la "vignette" résultante était de 200 Ko (Original 350 Ko). Cette méthode est quelque chose à éviter.
Vojtěch Dohnal
1
@NathanaelJones, êtes-vous sérieux? ImageResizer n'est pas gratuit pour les entreprises.
Ciaran Gallagher
26

Le code suivant écrira une image proportionnelle à la réponse, vous pouvez modifier le code selon vos besoins:

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
la source
J'ai donné mon chemin de fichier local dans le chemin de la chaîne. il renvoie "le format de chemin donné n'est pas pris en charge".
Gopal Palraj
j'ai donné comme ça ... var path = @ "C: \ Users \ Gopal \ Desktop \ files.jpeg"; Bitmap srcBmp = nouveau Bitmap (chemin);
Gopal Palraj
Pour ceux qui utilisent HttpResponseMessage:response.Content = new ByteArrayContent(memoryStream.ToArray());
Hp93
attention, ce code suppose que les images sont "horizontales" (paysage)
Alex
8

Voici un exemple complet de la façon de créer une image plus petite (miniature). Cet extrait redimensionne l'image, la fait pivoter si nécessaire (si un téléphone était tenu verticalement) et remplit l'image si vous souhaitez créer des pouces carrés. Cet extrait de code crée un JPEG, mais il peut facilement être modifié pour d'autres types de fichiers. Même si l'image est plus petite que la taille maximale autorisée, l'image sera toujours compressée et sa résolution sera modifiée pour créer des images de même dpi et niveau de compression.

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

Pour les utilisateurs d'asp.net, un petit exemple de la façon de télécharger un fichier, de le redimensionner et d'afficher le résultat sur la page.

//== 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
la source
J'ai aimé cet exemple de code et j'ai choisi de l'utiliser. Cependant, quels que soient les changements que j'ai apportés aux différentes options (imageResolution, compressionLevel, CompositingMode, CompositingQuality, SmoothingMode, InterpolationMode, PixelOffsetMode), la taille du fichier image n'a été réduite que légèrement. Et je n'ai jamais vu de différence dans l'image créée. Enfin, j'ai choisi d'enregistrer l'image dans un fichier au lieu du flux mémoire et j'ai pu voir des changements drastiques. Pour quiconque l'utilise, il semble que l'enregistrement dans un flux mémoire n'affecte pas l'image renvoyée.
BLaminack
1

Voici un exemple pour convertir une image haute résolution en taille de vignette-

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
la source