Utwórz obraz miniatury


96

Chcę wyświetlić miniaturę w widoku siatki z lokalizacji pliku. Jak wygenerować .jpegplik? Używam C#języka z asp.net.


6
ImageResizer to bezpieczna dla serwera biblioteka zaprojektowana tak, aby robić dokładnie to, czego potrzebujesz. W przeciwieństwie do GetThumbnailImage, daje wyniki wysokiej jakości iw przeciwieństwie do próbek kodu, nie przecieka pamięci jak sito. Możesz nie przejmować się teraz, ale za kilka miesięcy będziesz po kolana w głębokim depresji.
Lilith River



ImageResizer jest świetny, ale nie jest darmowy
Boban Stojanovski

Odpowiedzi:


222

Musisz użyć GetThumbnailImagemetody w Imageklasie:

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

Oto przybliżony przykład, który pobiera plik obrazu i tworzy z niego miniaturę, a następnie zapisuje go z powrotem na dysku.

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

Znajduje się w przestrzeni nazw System.Drawing (w System.Drawing.dll).

Zachowanie:

Jeśli Image zawiera osadzony obraz miniatury, ta metoda pobiera osadzoną miniaturę i skaluje ją do żądanego rozmiaru. Jeśli obraz nie zawiera osadzonego obrazu miniatury, ta metoda tworzy obraz miniatury przez skalowanie obrazu głównego.


Ważne: sekcja uwag powyższego łącza Microsoft ostrzega o pewnych potencjalnych problemach:

GetThumbnailImageMetoda działa dobrze, gdy żądana miniatura ma wymiary około 120 x 120 pikseli. Jeśli zażądasz dużej miniatury (na przykład 300 x 300) z obrazu, który ma osadzoną miniaturę, może wystąpić zauważalna utrata jakości obrazu miniatury .

Lepiej byłoby przeskalować główny obraz (zamiast skalować osadzoną miniaturę) przez wywołanie DrawImagemetody.


5
Można go używać tylko w przypadku obrazów JPG. Jeśli spróbujesz zmienić rozmiar obrazu PNG w ten sposób, pojawi się ten błąd.
HBlackorby

Naprawdę, użyłem tego do uzyskania miniatury 400x225 zdjęcia full HD, a rozmiar wynikowej „miniatury” to 200 kB (oryginał 350 kB). Tej metody należy unikać.
Vojtěch Dohnal

1
@NathanaelJones, mówisz poważnie? ImageResizer nie jest darmowy dla firm.
Ciaran Gallagher

26

Poniższy kod zapisze obraz proporcjonalnie do odpowiedzi, możesz zmodyfikować kod do swoich celów:

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

Podałem ścieżkę do pliku lokalnego w ścieżce ciągu. zwraca „podany format ścieżki nie jest obsługiwany”.
Gopal Palraj

podałem w ten sposób ... var path = @ "C: \ Users \ Gopal \ Desktop \ files.jpeg"; Bitmap srcBmp = new Bitmap (ścieżka);
Gopal Palraj

Dla tych, którzy używają HttpResponseMessage:response.Content = new ByteArrayContent(memoryStream.ToArray());
Hp93

ostrożnie, ten kod zakłada, że ​​obrazy są „poziome” (krajobraz)
Alex,

8

Oto kompletny przykład tworzenia mniejszego obrazu (miniatury). Ten fragment zmienia rozmiar obrazu, obraca go w razie potrzeby (jeśli telefon był trzymany pionowo) i wypełnia obraz, jeśli chcesz utworzyć kwadratowe kciuki. Ten fragment tworzy plik JPEG, ale można go łatwo zmodyfikować dla innych typów plików. Nawet jeśli obraz byłby mniejszy niż maksymalny dozwolony rozmiar, nadal będzie kompresowany, a jego rozdzielczość zostanie zmieniona w celu utworzenia obrazów o tej samej rozdzielczości i poziomie kompresji.

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

Dla użytkowników asp.net mały przykład przekazywania pliku, zmiany jego rozmiaru i wyświetlania wyniku na stronie.

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

Podobał mi się ten przykład kodu i zdecydowałem się go użyć. Jednak bez względu na to, jakie zmiany wprowadziłem w różnych opcjach (imageResolution, compressLevel, CompositingMode, CompositingQuality, SmoothingMode, InterpolationMode, PixelOffsetMode) rozmiar pliku obrazu zmniejszył się tylko nieznacznie. I nigdy nie widziałem żadnej różnicy w utworzonym obrazie. Wreszcie zdecydowałem się zapisać obraz do pliku zamiast strumienia pamięci i byłem w stanie zobaczyć drastyczne zmiany. Dla każdego, kto to używa, wydaje się, że zapisywanie w strumieniu pamięci nie wpływa na zwracany obraz.
BLaminack

1

Oto przykład konwersji obrazu o wysokiej rozdzielczości na rozmiar miniatury-

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

Źródło- http://iknowledgeboy.blogspot.in/2014/03/c-creating-thumbnail-of-large-image-by.html

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.