Создать миниатюру изображения


96

Я хочу отображать миниатюрное изображение в сетке из местоположения файла. Как сгенерировать тот .jpegфайл? Я использую C#язык с asp.net.


6
ImageResizer - это безопасная для сервера библиотека, предназначенная для того, чтобы делать именно то, что вам нужно. В отличие от GetThumbnailImage, он дает высококачественные результаты и, в отличие от примеров кода, не пропускает память, как решето. Возможно, сейчас вам все равно, но через несколько месяцев, когда вы будете по колено в свалках ядра, вам будет все равно.
Лилит Ривер



ImageResizer великолепен, но не бесплатен
Бобан Стояновски,

Ответы:


222

Вы должны использовать GetThumbnailImageметод в Imageклассе:

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

Вот примерный пример, который берет файл изображения и создает из него эскиз, а затем сохраняет его обратно на диск.

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

Он находится в пространстве имен System.Drawing (в System.Drawing.dll).

Поведение:

Если Image содержит внедренное изображение эскиза, этот метод извлекает внедренный эскиз и масштабирует его до требуемого размера. Если изображение не содержит встроенного эскиза изображения, этот метод создает эскизное изображение путем масштабирования основного изображения.


Важно: раздел примечаний по ссылке Microsoft выше предупреждает о некоторых потенциальных проблемах:

Этот GetThumbnailImageметод хорошо работает, когда запрошенное миниатюрное изображение имеет размер около 120 x 120 пикселей. Если вы запрашиваете изображение большого эскиза (например, 300 x 300) из изображения, которое имеет встроенный эскиз, это может привести к заметной потере качества изображения эскиза .

Возможно, было бы лучше масштабировать основное изображение (вместо масштабирования встроенного эскиза), вызвав DrawImageметод.


5
Обычно его можно использовать только с изображениями JPG. Если вы попытаетесь изменить размер изображения PNG таким образом, вы получите эту ошибку.
HBlackorby, 04

На самом деле, использовал это, чтобы получить миниатюру 400x225 фотографии в формате Full HD, и размер результирующей «миниатюры» составлял 200 кБ (Исходный 350 кБ). Этого метода следует избегать.
Vojtěch

1
@NathanaelJones, ты серьезно? ImageResizer не бесплатен для бизнеса.
Ciaran Gallagher

26

Следующий код запишет изображение пропорционально ответу, вы можете изменить код для своих целей:

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

Я указал путь к локальному файлу в виде строки. он возвращает «данный формат пути не поддерживается».
Гопал Палрадж 01

я дал вот так ... var path = @ "C: \ Users \ Gopal \ Desktop \ files.jpeg"; Bitmap srcBmp = new Bitmap (path);
Гопал Палрадж 01

Для тех, кто пользуется HttpResponseMessage:response.Content = new ByteArrayContent(memoryStream.ToArray());
Hp93

осторожно, этот код предполагает, что изображения являются «горизонтальными» (альбомными)
Alex

8

Вот полный пример того, как создать изображение меньшего размера (эскиз). Этот фрагмент изменяет размер изображения, поворачивает его при необходимости (если телефон держался вертикально) и дополняет изображение, если вы хотите создать квадратные пальцы. Этот фрагмент создает JPEG, но его можно легко изменить для других типов файлов. Даже если изображение будет меньше максимально допустимого размера, оно все равно будет сжато, а его разрешение будет изменено для создания изображений с тем же разрешением и уровнем сжатия.

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

Для пользователей asp.net небольшой пример того, как загрузить файл, изменить его размер и отобразить результат на странице.

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

Мне понравился этот пример кода, и я решил его использовать. Однако независимо от того, какие изменения я внес в различные параметры (imageResolution, CompressionLevel, CompositingMode, CompositingQuality, SmoothingMode, InterpolationMode, PixelOffsetMode), размер файла изображения уменьшился лишь незначительно. И я никогда не видел разницы в созданном изображении. Наконец, я решил сохранить изображение в файл, а не в поток памяти, и смог увидеть кардинальные изменения. Для всех, кто использует это, кажется, что сохранение в потоке памяти не влияет на возвращаемое изображение.
BLaminack

1

Вот пример преобразования изображения с высоким разрешением в размер эскиза:

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

Источник- http://iknowledgeboy.blogspot.in/2014/03/c-creating-thumbnail-of-large-image-by.html

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.