Jak zmienić rozmiar obrazu C #

288

A Size, Widthi Heightto Get()właściwości System.Drawing.Image;
Jak mogę zmienić rozmiar obiektu Image w czasie wykonywania w C #?

W tej chwili tworzę nowy Imageza pomocą:

// objImage is the original Image
Bitmap objBitmap = new Bitmap(objImage, new Size(227, 171));
inutan
źródło
2
Nieprawidłowy sposób ... używa niskiej jakości interpolacji i może spowodować, że oryginalny strumień pozostanie zablokowany na czas trwania nowego obrazu bitmapowego ... Przeczytaj listę pułapek zmiany rozmiaru obrazu przed wykonaniem własnego rozwiązania zmiany rozmiaru obrazu.
Lilith River,
2
Pozbądź się tego! Korzystanie z () {} działa!
Scott Coates
8
Jeśli te odpowiedzi są pomocne, rozważ zaznaczenie zaakceptowanej odpowiedzi.
Joel
3
Nie ma potrzeby korzystania z żadnej dodatkowej biblioteki. Kod opublikowany poniżej przez Marka działa idealnie.
Elmue,
9
Kim jest Mark? Nie udało mi się znaleźć jego odpowiedzi, ale są 3 komentarze, które odnoszą się do niej.
Sinatr

Odpowiedzi:

490

Spowoduje to wykonanie wysokiej jakości zmiany rozmiaru:

/// <summary>
/// Resize the image to the specified width and height.
/// </summary>
/// <param name="image">The image to resize.</param>
/// <param name="width">The width to resize to.</param>
/// <param name="height">The height to resize to.</param>
/// <returns>The resized image.</returns>
public static Bitmap ResizeImage(Image image, int width, int height)
{
    var destRect = new Rectangle(0, 0, width, height);
    var destImage = new Bitmap(width, height);

    destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

    using (var graphics = Graphics.FromImage(destImage))
    {
        graphics.CompositingMode = CompositingMode.SourceCopy;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.HighQuality;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

        using (var wrapMode = new ImageAttributes())
        {
            wrapMode.SetWrapMode(WrapMode.TileFlipXY);
            graphics.DrawImage(image, destRect, 0, 0, image.Width,image.Height, GraphicsUnit.Pixel, wrapMode);
        }
    }

    return destImage;
}
  • wrapMode.SetWrapMode(WrapMode.TileFlipXY) zapobiega duchom wokół granic obrazu - naiwna zmiana rozmiaru spowoduje próbkowanie przezroczystych pikseli poza granicami obrazu, ale poprzez odbicie lustrzane obrazu możemy uzyskać lepszą próbkę (to ustawienie jest bardzo zauważalne)
  • destImage.SetResolution utrzymuje DPI niezależnie od wielkości fizycznej - może poprawić jakość przy zmniejszaniu wymiarów obrazu lub podczas drukowania
  • Komponowanie kontroluje sposób mieszania pikseli z tłem - może nie być potrzebny, ponieważ rysujemy tylko jedną rzecz.
  • graphics.InterpolationMode określa sposób obliczania wartości pośrednich między dwoma punktami końcowymi
  • graphics.SmoothingMode określa, czy linie, krzywe i krawędzie wypełnionych obszarów używają wygładzania (zwanego również antyaliasingiem) - prawdopodobnie działa tylko na wektorach
  • graphics.PixelOffsetMode wpływa na jakość renderowania podczas rysowania nowego obrazu

Utrzymanie proporcji pozostawia się jako ćwiczenie dla czytelnika (właściwie nie sądzę, że zadaniem tej funkcji jest wykonanie tego za Ciebie).

Ponadto, jest to dobry artykuł opisujący niektóre z pułapek z zmiana rozmiaru obrazu. Powyższa funkcja obejmie większość z nich, ale nadal musisz martwić się o oszczędzanie .

mpen
źródło
4
kod działał idealnie podczas zmiany rozmiaru obrazu, ale zwiększył rozmiar z 66 KB do 132 KB. Motyka, mogę to zmniejszyć
chamara,
3
@chamara Prawdopodobnie wynika to z jakości, którą wybrałeś. Zobacz msdn.microsoft.com/en-us/library/bb882583(v=vs.110).aspx Wypróbuj jakość = 90
za
3
@kstubs Jesteś pewien. Bitmapjest w zasadzie tylko nazwą klasy, którą możesz zapisać jako dowolny typ pliku, jaki ci się podoba.
mpen
5
@dotNetBlackBelt Prawdopodobnie musisz dodać odniesienie System.Drawingi dodaćusing System.Drawing.Imaging;
mpen
2
To nie utrzyma oryginalnego współczynnika proporcji, prawda?
Kasper Skov
148

Nie jestem pewien, co jest w tym takiego trudnego, zrób to, co robiłeś, użyj przeciążonego konstruktora bitmap, aby utworzyć obraz o zmienionym rozmiarze, jedyne, czego Ci brakowało, to rzutowanie z powrotem na typ danych Obraz:

    public static Image resizeImage(Image imgToResize, Size size)
    {
       return (Image)(new Bitmap(imgToResize, size));
    }

    yourImage = resizeImage(yourImage, new Size(50,50));
Matt
źródło
2
Czy nie powinieneś pozbyć się yourImageprzed przypisaniem go do nowego obrazu?
Nick Shaw
3
Możesz usunąć go ręcznie lub pozwolić, aby śmieciarz wykonał swoją pracę. Bez znaczenia.
Elmue,
23
Ten kod nie daje żadnej kontroli nad jakością zmiany rozmiaru, co jest bardzo ważne. Spójrz na odpowiedź Marka.
Elmue
43

w tym pytaniu będziesz miał kilka odpowiedzi, w tym moją:

public Image resizeImage(int newWidth, int newHeight, string stPhotoPath)
 {
     Image imgPhoto = Image.FromFile(stPhotoPath); 

     int sourceWidth = imgPhoto.Width;
     int sourceHeight = imgPhoto.Height;

     //Consider vertical pics
    if (sourceWidth < sourceHeight)
    {
        int buff = newWidth;

        newWidth = newHeight;
        newHeight = buff;
    }

    int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
    float nPercent = 0, nPercentW = 0, nPercentH = 0;

    nPercentW = ((float)newWidth / (float)sourceWidth);
    nPercentH = ((float)newHeight / (float)sourceHeight);
    if (nPercentH < nPercentW)
    {
        nPercent = nPercentH;
        destX = System.Convert.ToInt16((newWidth -
                  (sourceWidth * nPercent)) / 2);
    }
    else
    {
        nPercent = nPercentW;
        destY = System.Convert.ToInt16((newHeight -
                  (sourceHeight * nPercent)) / 2);
    }

    int destWidth = (int)(sourceWidth * nPercent);
    int destHeight = (int)(sourceHeight * nPercent);


    Bitmap bmPhoto = new Bitmap(newWidth, newHeight,
                  PixelFormat.Format24bppRgb);

    bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                 imgPhoto.VerticalResolution);

    Graphics grPhoto = Graphics.FromImage(bmPhoto);
    grPhoto.Clear(Color.Black);
    grPhoto.InterpolationMode =
        System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

    grPhoto.DrawImage(imgPhoto,
        new Rectangle(destX, destY, destWidth, destHeight),
        new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
        GraphicsUnit.Pixel);

    grPhoto.Dispose();
    imgPhoto.Dispose();
    return bmPhoto;
}
Vinzz
źródło
5
Zapomniałeś imgPhoto.Dispose (); plik jest w użyciu
shrutyzet 17.04.13
1
Jest to bardzo pomocne i używam tego w mojej aplikacji. Należy jednak pamiętać, że ten algorytm nie działa z przezroczystymi obrazami. Wszystkie przezroczyste piksele stają się czarne. Prawdopodobnie jest łatwy do naprawienia, ale jest to tylko informacja dla użytkowników. :)
meme
1
Czy nie chcesz zapisać obrazu? imgPhoto.Save ()?
Whiplash
@meme Czy możesz podać link, jak naprawić to czarne tło dla przezroczystego dokumentu.
Syed Mohamed
25

Dlaczego nie skorzystać z tej System.Drawing.Image.GetThumbnailImagemetody?

public Image GetThumbnailImage(
    int thumbWidth, 
    int thumbHeight, 
    Image.GetThumbnailImageAbort callback, 
    IntPtr callbackData)

Przykład:

Image originalImage = System.Drawing.Image.FromStream(inputStream, true, true);
Image resizedImage = originalImage.GetThumbnailImage(newWidth, (newWidth * originalImage.Height) / originalWidth, null, IntPtr.Zero);
resizedImage.Save(imagePath, ImageFormat.Png);

Źródło: http://msdn.microsoft.com/en-us/library/system.drawing.image.getthumbnailimage.aspx

Lino Silva
źródło
6
To nie jest właściwy sposób zmiany rozmiaru obrazu. Spowoduje to pobranie miniatury z pliku jpg, jeśli istnieje. Jeśli nie istnieje, nie masz kontroli nad jakością ani nowym obrazem. Również ten kod ma przecieki pamięci.
Robert Smith,
1
@ Bobrot Dlaczego spowoduje to wycieki pamięci?
użytkownik
2
Wszystko w bibliotece GDI nadal działa niezarządzane. Bez użycia instrukcji using lub późniejszego usuwania obiektów może to zająć dużo czasu, zanim system usunie te obiekty i ponownie udostępni pamięć.
Robert Smith
9
Jest tak, jak mówisz: może to zająć dużo czasu. Ale to NIE jest wyciek pamięci. Byłoby wyciek pamięci, gdyby pamięć NIGDY nie została uwolniona. Ale jest to NORMALNE zachowanie modułu wyrzucającego śmieci, który zwalnia pamięć, gdy procesor jest bezczynny. Instrukcja using () nie zapobiega wyciekom pamięci. Po prostu zwalnia pamięć natychmiast, a śmieciarz uwalnia pamięć, gdy ma na to czas. To jedyna różnica w tym konkretnym przypadku.
Elmue
Zobacz pułapki zmiany rozmiaru obrazu: nathanaeljones.com/blog/2009/20-image-resizing-pitfalls "Korzystanie z GetThumbnailImage (). GetThumbnailImage () wydaje się oczywistym wyborem, a wiele artykułów zaleca jego użycie. Niestety zawsze pobiera osadzony plik JPEG miniatura, jeśli jest obecna. Niektóre zdjęcia mają te, niektóre nie - zwykle zależy to od aparatu. Zastanawiacie się, dlaczego GetThumbnailImage działa dobrze na niektórych zdjęciach, ale na innych jest strasznie niewyraźne. GetThumbnailImage () nie jest wiarygodny w przypadku zdjęć większych z tego powodu niż 10 na 10 pikseli ”.
Nick Painter
12

Możesz wypróbować net-vips , wiązanie C # dla libvips . Jest to leniwa, strumieniowa biblioteka przetwarzania obrazu sterowana na żądanie, dzięki czemu może wykonywać takie operacje bez konieczności ładowania całego obrazu.

Na przykład jest wyposażony w poręczną miniaturkę obrazu:

Image image = Image.Thumbnail("image.jpg", 300, 300);
image.WriteToFile("my-thumbnail.jpg");

Obsługuje również inteligentne przycinanie, sposób inteligentnego określania najważniejszej części obrazu i utrzymywania ostrości podczas przycinania obrazu. Na przykład:

Image image = Image.Thumbnail("owl.jpg", 128, crop: "attention");
image.WriteToFile("tn_owl.jpg");

Gdzie owl.jpgjest kompozycja niecentralna:

Sowa

Daje ten wynik:

Sowa inteligentne uprawy

Najpierw zmniejsza obraz, aby uzyskać oś pionową do 128 pikseli, a następnie przycina do 128 pikseli za pomocą attentionstrategii. Ten przeszukuje obraz w poszukiwaniu funkcji, które mogą przyciągnąć ludzkie oko, zobacz Smartcrop()szczegóły.

kleisauke
źródło
Twoje powiązanie z libvips wydaje się świetne. Na pewno spojrzę na twoją bibliotekę. Dziękujemy za udostępnienie tego C # Developer!
FrenchTastic
To jest wspaniałe! Nie miałem pojęcia, że ​​biblioteka do przetwarzania obrazów może wyglądać tak dobrze.
dalvir
miły! lepszy niż ciężki ImageMagick
Moshe L
10

To będzie -

  • Zmień szerokość i wysokość bez potrzeby używania pętli
  • Nie przekracza oryginalnych wymiarów zdjęć

//////////////

private void ResizeImage(Image img, double maxWidth, double maxHeight)
{
    double resizeWidth = img.Source.Width;
    double resizeHeight = img.Source.Height;

    double aspect = resizeWidth / resizeHeight;

    if (resizeWidth > maxWidth)
    {
        resizeWidth = maxWidth;
        resizeHeight = resizeWidth / aspect;
    }
    if (resizeHeight > maxHeight)
    {
        aspect = resizeWidth / resizeHeight;
        resizeHeight = maxHeight;
        resizeWidth = resizeHeight * aspect;
    }

    img.Width = resizeWidth;
    img.Height = resizeHeight;
}
Dominik
źródło
11
OP pytał o System.Drawing.Image, w którym twój kod nie będzie działał, ponieważ właściwości „Szerokość” i „Wysokość” nie można ustawić. Będzie jednak działał dla System.Windows.Controls.Image.
mmmdreg
10
public static Image resizeImage(Image image, int new_height, int new_width)
{
    Bitmap new_image = new Bitmap(new_width, new_height);
    Graphics g = Graphics.FromImage((Image)new_image );
    g.InterpolationMode = InterpolationMode.High;
    g.DrawImage(image, 0, 0, new_width, new_height);
    return new_image;
}
NeoSvet
źródło
Zapomniałeś pozbyć się grafiki. Wygląda na tę samą zasadę, co nowa mapa bitowa (obraz, szerokość, wysokość) z lepszym trybem interpolacji. Jestem ciekawy co to jest Default ? Czy to nawet gorzej Low?
Sinatr
9

Ten kod jest taki sam, jak wysłany z jednej z powyższych odpowiedzi ... ale przekształci przezroczysty piksel na biały zamiast czarnego ... Dzięki :)

    public Image resizeImage(int newWidth, int newHeight, string stPhotoPath)
    {
        Image imgPhoto = Image.FromFile(stPhotoPath);

        int sourceWidth = imgPhoto.Width;
        int sourceHeight = imgPhoto.Height;

        //Consider vertical pics
        if (sourceWidth < sourceHeight)
        {
            int buff = newWidth;

            newWidth = newHeight;
            newHeight = buff;
        }

        int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
        float nPercent = 0, nPercentW = 0, nPercentH = 0;

        nPercentW = ((float)newWidth / (float)sourceWidth);
        nPercentH = ((float)newHeight / (float)sourceHeight);
        if (nPercentH < nPercentW)
        {
            nPercent = nPercentH;
            destX = System.Convert.ToInt16((newWidth -
                      (sourceWidth * nPercent)) / 2);
        }
        else
        {
            nPercent = nPercentW;
            destY = System.Convert.ToInt16((newHeight -
                      (sourceHeight * nPercent)) / 2);
        }

        int destWidth = (int)(sourceWidth * nPercent);
        int destHeight = (int)(sourceHeight * nPercent);


        Bitmap bmPhoto = new Bitmap(newWidth, newHeight,
                      PixelFormat.Format24bppRgb);

        bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                     imgPhoto.VerticalResolution);

        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.Clear(Color.White);
        grPhoto.InterpolationMode =
            System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

        grPhoto.DrawImage(imgPhoto,
            new Rectangle(destX, destY, destWidth, destHeight),
            new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
            GraphicsUnit.Pixel);

        grPhoto.Dispose();
        imgPhoto.Dispose();

        return bmPhoto;
    }
Rajesz
źródło
7

W aplikacji podjąłem konieczność utworzenia funkcji z wieloma opcjami. Jest dość duży, ale zmienia rozmiar obrazu, może zachować proporcje i może przycinać krawędzie, aby zwrócić tylko środek obrazu:

/// <summary>
    /// Resize image with a directory as source
    /// </summary>
    /// <param name="OriginalFileLocation">Image location</param>
    /// <param name="heigth">new height</param>
    /// <param name="width">new width</param>
    /// <param name="keepAspectRatio">keep the aspect ratio</param>
    /// <param name="getCenter">return the center bit of the image</param>
    /// <returns>image with new dimentions</returns>
    public Image resizeImageFromFile(String OriginalFileLocation, int heigth, int width, Boolean keepAspectRatio, Boolean getCenter)
    {
        int newheigth = heigth;
        System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(OriginalFileLocation);

        // Prevent using images internal thumbnail
        FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
        FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);

        if (keepAspectRatio || getCenter)
        {
            int bmpY = 0;
            double resize = (double)FullsizeImage.Width / (double)width;//get the resize vector
            if (getCenter)
            {
                bmpY = (int)((FullsizeImage.Height - (heigth * resize)) / 2);// gives the Y value of the part that will be cut off, to show only the part in the center
                Rectangle section = new Rectangle(new Point(0, bmpY), new Size(FullsizeImage.Width, (int)(heigth * resize)));// create the section to cut of the original image
                //System.Console.WriteLine("the section that will be cut off: " + section.Size.ToString() + " the Y value is minimized by: " + bmpY);
                Bitmap orImg = new Bitmap((Bitmap)FullsizeImage);//for the correct effect convert image to bitmap.
                FullsizeImage.Dispose();//clear the original image
                using (Bitmap tempImg = new Bitmap(section.Width, section.Height))
                {
                    Graphics cutImg = Graphics.FromImage(tempImg);//              set the file to save the new image to.
                    cutImg.DrawImage(orImg, 0, 0, section, GraphicsUnit.Pixel);// cut the image and save it to tempImg
                    FullsizeImage = tempImg;//save the tempImg as FullsizeImage for resizing later
                    orImg.Dispose();
                    cutImg.Dispose();
                    return FullsizeImage.GetThumbnailImage(width, heigth, null, IntPtr.Zero);
                }
            }
            else newheigth = (int)(FullsizeImage.Height / resize);//  set the new heigth of the current image
        }//return the image resized to the given heigth and width
        return FullsizeImage.GetThumbnailImage(width, newheigth, null, IntPtr.Zero);
    }

Aby ułatwić dostęp do funkcji, można dodać niektóre przeciążone funkcje:

/// <summary>
    /// Resize image with a directory as source
    /// </summary>
    /// <param name="OriginalFileLocation">Image location</param>
    /// <param name="heigth">new height</param>
    /// <param name="width">new width</param>
    /// <returns>image with new dimentions</returns>
    public Image resizeImageFromFile(String OriginalFileLocation, int heigth, int width)
    {
        return resizeImageFromFile(OriginalFileLocation, heigth, width, false, false);
    }

    /// <summary>
    /// Resize image with a directory as source
    /// </summary>
    /// <param name="OriginalFileLocation">Image location</param>
    /// <param name="heigth">new height</param>
    /// <param name="width">new width</param>
    /// <param name="keepAspectRatio">keep the aspect ratio</param>
    /// <returns>image with new dimentions</returns>
    public Image resizeImageFromFile(String OriginalFileLocation, int heigth, int width, Boolean keepAspectRatio)
    {
        return resizeImageFromFile(OriginalFileLocation, heigth, width, keepAspectRatio, false);
    }

Teraz ostatnie dwa booleany są opcjonalne do ustawienia. Wywołaj funkcję w ten sposób:

System.Drawing.Image ResizedImage = resizeImageFromFile(imageLocation, 800, 400, true, true);
Quispie
źródło
6
public string CreateThumbnail(int maxWidth, int maxHeight, string path)
{

    var image = System.Drawing.Image.FromFile(path);
    var ratioX = (double)maxWidth / image.Width;
    var ratioY = (double)maxHeight / image.Height;
    var ratio = Math.Min(ratioX, ratioY);
    var newWidth = (int)(image.Width * ratio);
    var newHeight = (int)(image.Height * ratio);
    var newImage = new Bitmap(newWidth, newHeight);
    Graphics thumbGraph = Graphics.FromImage(newImage);

    thumbGraph.CompositingQuality = CompositingQuality.HighQuality;
    thumbGraph.SmoothingMode = SmoothingMode.HighQuality;
    //thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;

    thumbGraph.DrawImage(image, 0, 0, newWidth, newHeight);
    image.Dispose();

    string fileRelativePath = "newsizeimages/" + maxWidth + Path.GetFileName(path);
    newImage.Save(Server.MapPath(fileRelativePath), newImage.RawFormat);
    return fileRelativePath;
}

Kliknij tutaj http://bhupendrasinghsaini.blogspot.in/2014/07/resize-image-in-c.html

bhupendra singh
źródło
6

To jest kod, który opracowałem dla konkretnego wymagania, tj .: cel jest zawsze w proporcji poziomej. To powinno dać ci dobry początek.

public Image ResizeImage(Image source, RectangleF destinationBounds)
{
    RectangleF sourceBounds = new RectangleF(0.0f,0.0f,(float)source.Width, (float)source.Height);
    RectangleF scaleBounds = new RectangleF();

    Image destinationImage = new Bitmap((int)destinationBounds.Width, (int)destinationBounds.Height);
    Graphics graph = Graphics.FromImage(destinationImage);
    graph.InterpolationMode =
        System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

    // Fill with background color
    graph.FillRectangle(new SolidBrush(System.Drawing.Color.White), destinationBounds);

    float resizeRatio, sourceRatio;
    float scaleWidth, scaleHeight;

    sourceRatio = (float)source.Width / (float)source.Height;

    if (sourceRatio >= 1.0f)
    {
        //landscape
        resizeRatio = destinationBounds.Width / sourceBounds.Width;
        scaleWidth = destinationBounds.Width;
        scaleHeight = sourceBounds.Height * resizeRatio;
        float trimValue = destinationBounds.Height - scaleHeight;
        graph.DrawImage(source, 0, (trimValue / 2), destinationBounds.Width, scaleHeight);
    }
    else
    {
        //portrait
        resizeRatio = destinationBounds.Height/sourceBounds.Height;
        scaleWidth = sourceBounds.Width * resizeRatio;
        scaleHeight = destinationBounds.Height;
        float trimValue = destinationBounds.Width - scaleWidth;
        graph.DrawImage(source, (trimValue / 2), 0, scaleWidth, destinationBounds.Height);
    }

    return destinationImage;

}
Leslie Marshall
źródło
Niesamowite!!! Miałem kłopoty z obrazem portretowym i po wypróbowaniu wielu rozwiązań poszukiwanych w Internecie, TYLKO TO BYŁO IDEALNE! DZIĘKUJĘ BARDZO!
Fábio
3

Jeśli pracujesz z BitmapSource:

var resizedBitmap = new TransformedBitmap(
    bitmapSource,
    new ScaleTransform(scaleX, scaleY));

Jeśli chcesz mieć lepszą kontrolę nad jakością, uruchom najpierw:

RenderOptions.SetBitmapScalingMode(
    bitmapSource,
    BitmapScalingMode.HighQuality);

(Domyślnie jest BitmapScalingMode.Linearto odpowiednik BitmapScalingMode.LowQuality.)

Mateen Ulhaq
źródło
3

Używam ImageProcessorCore, głównie dlatego, że działa .Net Core.

I ma więcej opcji, takich jak konwersja typów, przycinanie zdjęć i więcej

http://imageprocessor.org/imageprocessor/

topolm
źródło
1
Szukałem i to nie obsługuje .NET Core. Jest zbudowany w oparciu o pełne ramy.
chrisdrobison
1

Zmień rozmiar i zapisz obraz, aby zmieścił się poniżej szerokości i wysokości, podobnie jak płótno, zachowując proporcje obrazu

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

namespace Infra.Files
{
    public static class GenerateThumb
    {
        /// <summary>
        /// Resize and save an image to fit under width and height like a canvas keeping things proportional
        /// </summary>
        /// <param name="originalImagePath"></param>
        /// <param name="thumbImagePath"></param>
        /// <param name="newWidth"></param>
        /// <param name="newHeight"></param>
        public static void GenerateThumbImage(string originalImagePath, string thumbImagePath, int newWidth, int newHeight)
        {
            Bitmap srcBmp = new Bitmap(originalImagePath);
            float ratio = 1;
            float minSize = Math.Min(newHeight, newHeight);

            if (srcBmp.Width > srcBmp.Height)
            {
                ratio = minSize / (float)srcBmp.Width;
            }
            else
            {
                ratio = minSize / (float)srcBmp.Height;
            }

            SizeF newSize = new SizeF(srcBmp.Width * ratio, srcBmp.Height * ratio);
            Bitmap target = new Bitmap((int)newSize.Width, (int)newSize.Height);

            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(thumbImagePath);
                }
            }
        }
    }
}
Andrew Paes
źródło
1

Użyj funkcji poniżej z poniższym przykładem zmiany rozmiaru obrazu:

//Example : 
System.Net.Mime.MediaTypeNames.Image newImage = System.Net.Mime.MediaTypeNames.Image.FromFile("SampImag.jpg");
System.Net.Mime.MediaTypeNames.Image temImag = FormatImage(newImage, 100, 100);

//image size modification unction   
public static System.Net.Mime.MediaTypeNames.Image FormatImage(System.Net.Mime.MediaTypeNames.Image img, int outputWidth, int outputHeight)
{

    Bitmap outputImage = null;
    Graphics graphics = null;
    try
    {
         outputImage = new Bitmap(outputWidth, outputHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
         graphics = Graphics.FromImage(outputImage);
         graphics.DrawImage(img, new Rectangle(0, 0, outputWidth, outputHeight),
         new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);

         return outputImage;
     }
     catch (Exception ex)
     {
           return img;
     }
}
Prasad KM
źródło
2
W powyższej odpowiedzi zastanów się nad wyjaśnieniem, jak korzystać z tego kodu, co robi kod i jak rozwiązuje problem w pierwotnym pytaniu.
Tim Visée,
Dodałem także przypadek użycia. Użyj powyższej funkcji z poniższym przykładem. Obraz newImage = Image.FromFile („SampImag.jpg”); TemImag obrazu = FormatImage (newImage, 100, 100);
Prasad KM
0

Uwaga: nie będzie to działać z ASP.Net Core, ponieważ WebImage zależy od System.Web, ale od poprzednich wersji ASP.Net korzystałem z tego fragmentu wiele razy i był on użyteczny.

String ThumbfullPath = Path.GetFileNameWithoutExtension(file.FileName) + "80x80.jpg";
var ThumbfullPath2 = Path.Combine(ThumbfullPath, fileThumb);
using (MemoryStream stream = new MemoryStream(System.IO.File.ReadAllBytes(fullPath)))
{
      var thumbnail = new WebImage(stream).Resize(80, 80);
      thumbnail.Save(ThumbfullPath2, "jpg");
}
JoshYates1980
źródło