Frage

Ich möchte ein Bild in C# mit so gut wie Photoshop in C# skalieren. Gibt es eine C# Image -Verarbeitungsbibliothek für dieses Ding?

War es hilfreich?

Lösung

Hier ist eine gut kommentierte Bildmanipulationshelferklasse, die Sie sich ansehen und verwenden können. Ich habe es als Beispiel dafür geschrieben, wie bestimmte Bildmanipulationsaufgaben in C#ausgeführt werden können. Sie werden an der interessiert sein Bildgröße anpassen Funktion, die ein System nimmt.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;

namespace DoctaJonez.Drawing.Imaging
{
    /// <summary>
    /// Provides various image untilities, such as high quality resizing and the ability to save a JPEG.
    /// </summary>
    public static class ImageUtilities
    {    
        /// <summary>
        /// A quick lookup for getting image encoders
        /// </summary>
        private static Dictionary<string, ImageCodecInfo> encoders = null;

        /// <summary>
        /// A lock to prevent concurrency issues loading the encoders.
        /// </summary>
        private static object encodersLock = new object();

        /// <summary>
        /// A quick lookup for getting image encoders
        /// </summary>
        public static Dictionary<string, ImageCodecInfo> Encoders
        {
            //get accessor that creates the dictionary on demand
            get
            {
                //if the quick lookup isn't initialised, initialise it
                if (encoders == null)
                {
                    //protect against concurrency issues
                    lock (encodersLock)
                    {
                        //check again, we might not have been the first person to acquire the lock (see the double checked lock pattern)
                        if (encoders == null)
                        {
                            encoders = new Dictionary<string, ImageCodecInfo>();

                            //get all the codecs
                            foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders())
                            {
                                //add each codec to the quick lookup
                                encoders.Add(codec.MimeType.ToLower(), codec);
                            }
                        }
                    }
                }

                //return the lookup
                return encoders;
            }
        }

        /// <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 System.Drawing.Bitmap ResizeImage(System.Drawing.Image image, int width, int height)
        {
            //a holder for the result
            Bitmap result = new Bitmap(width, height);
            //set the resolutions the same to avoid cropping due to resolution differences
            result.SetResolution(image.HorizontalResolution, image.VerticalResolution);

            //use a graphics object to draw the resized image into the bitmap
            using (Graphics graphics = Graphics.FromImage(result))
            {
                //set the resize quality modes to high quality
                graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                //draw the image into the target bitmap
                graphics.DrawImage(image, 0, 0, result.Width, result.Height);
            }

            //return the resulting bitmap
            return result;
        }

        /// <summary> 
        /// Saves an image as a jpeg image, with the given quality 
        /// </summary> 
        /// <param name="path">Path to which the image would be saved.</param> 
        /// <param name="quality">An integer from 0 to 100, with 100 being the 
        /// highest quality</param> 
        /// <exception cref="ArgumentOutOfRangeException">
        /// An invalid value was entered for image quality.
        /// </exception>
        public static void SaveJpeg(string path, Image image, int quality)
        {
            //ensure the quality is within the correct range
            if ((quality < 0) || (quality > 100))
            {
                //create the error message
                string error = string.Format("Jpeg image quality must be between 0 and 100, with 100 being the highest quality.  A value of {0} was specified.", quality);
                //throw a helpful exception
                throw new ArgumentOutOfRangeException(error);
            }

            //create an encoder parameter for the image quality
            EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            //get the jpeg codec
            ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");

            //create a collection of all parameters that we will pass to the encoder
            EncoderParameters encoderParams = new EncoderParameters(1);
            //set the quality parameter for the codec
            encoderParams.Param[0] = qualityParam;
            //save the image using the codec and the parameters
            image.Save(path, jpegCodec, encoderParams);
        }

        /// <summary> 
        /// Returns the image codec with the given mime type 
        /// </summary> 
        public static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            //do a case insensitive search for the mime type
            string lookupKey = mimeType.ToLower();

            //the codec to return, default to null
            ImageCodecInfo foundCodec = null;

            //if we have the encoder, get it to return
            if (Encoders.ContainsKey(lookupKey))
            {
                //pull the codec from the lookup
                foundCodec = Encoders[lookupKey];
            }

            return foundCodec;
        } 
    }
}

Aktualisieren

Ein paar Leute haben in den Kommentaren nach Beispielen für die Verbrauch der ImageUtilities -Klasse gefragt, also gehen Sie hier.

//resize the image to the specified height and width
using (var resized = ImageUtilities.ResizeImage(image, 50, 100))
{
    //save the resized image as a jpeg with a quality of 90
    ImageUtilities.SaveJpeg(@"C:\myimage.jpeg", resized, 90);
}

Notiz

Denken Sie daran, dass Bilder verfügbar sind, sodass Sie das Ergebnis Ihrer Größenänderung einer Verwendung von Deklaration zuweisen müssen (oder Sie können schließlich einen Versuch verwenden und sicherstellen, dass Sie in Ihrem schließlich anrufen).

Andere Tipps

Wenn Sie das Bild mit GDI+ zeichnen, skaliert es meiner Meinung nach recht gut. Sie können dies verwenden, um ein skaliertes Bild zu erstellen.

Wenn Sie Ihr Bild mit GDI+ skalieren möchten, können Sie so etwas tun:

Bitmap original = ...
Bitmap scaled = new Bitmap(new Size(original.Width * 4, original.Height * 4));
using (Graphics graphics = Graphics.FromImage(scaled)) {
  graphics.DrawImage(original, new Rectangle(0, 0, scaled.Width, scaled.Height));
}

Getestete Bibliotheken mögen Imagemagick und Gd sind für .NET verfügbar

Sie können sich auch über Dinge wie die bicubische Interpolation informieren und Ihre eigenen schreiben.

Verwenden Sie diese Bibliothek: http://imageresizing.net

Lesen Sie diesen Artikel des Bibliotheksautors: 20 Bildgrößen Fallstricke mit .NET

Versuchen Sie die verschiedenen Werte für Grafiken.InterpolationMode. In GDI+gibt es mehrere typische Skalierungsalgorithmen. Wenn eines davon für Ihr Bedürfnis ausreicht, können Sie diesen Weg gehen, anstatt sich auf eine externe Bibliothek zu verlassen.

Du kannst es versuchen Dotimage, eines der Produkte meines Unternehmens, das eine umfasst Objekt zum Resampling Bilder, die haben 18 Filtertypen für verschiedene Qualitätsniveaus.

Typische Verwendung ist:

// BiCubic is one technique available in PhotoShop
ResampleCommand resampler = new ResampleCommand(newSize, ResampleMethod.BiCubic);
AtalaImage newImage = resampler.Apply(oldImage).Image;

Darüber hinaus enthält Dotimage 140 einige seltsame Bildverarbeitungsbefehle, darunter viele Filter, die denen in Photoshop ähneln, wenn Sie das suchen.

Dies könnte helfen

    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;

    }

Beachten Sie das InterpolationMode.HighQualityBicubic -> Dies ist im Allgemeinen ein guter Kompromiss zwischen Leistung und Ergebnissen.

Probieren Sie diesen grundlegenden Code -Snippet aus:

private static Bitmap ResizeBitmap(Bitmap srcbmp, int width, int height )
{
    Bitmap newimage = new Bitmap(width, height);
    using (Graphics g = Graphics.FromImage(newimage))
           g.DrawImage(srcbmp, 0, 0, width, height);
    return newimage;
}

Dort ist ein Artikel über Codeprojekt Über die Verwendung von GDI+ für .NET, um beispielsweise eine bicubische Interpolation zu ändern.

Es gab auch einen weiteren Artikel zu diesem Thema in einem anderen Blog (MS -Mitarbeiter, glaube ich), aber ich kann den Link nirgendwo finden. :( Vielleicht kann es jemand anderes finden?

Sie könnten dies ausprobieren, wenn es sich um einen Lowres -CGI handelt2D -Bildfilter

Dies ist ein Artikel, von dem ich entdeckt wurde, dass er in Paint.nets Code für das Bild -Resampling verwiesen wird: Verschiedene einfache Bildverarbeitungstechniken Von Paul Bourke.

Du könntest es versuchen der magische Kernel. Es produziert weniger Pixel -Artefakte als das bicubische Resample beim Hochskalieren und liefert auch sehr gute Ergebnisse beim Abwärtsscalieren. Der Quellcode ist in C# auf der Website verfügbar.

Ich habe einige Verbesserungen für die Antwort von Doctor Jones.

Es funktioniert für die, wie man die Größe des Bildes proportional ändern wollte. Es wurde getestet und für mich funktioniert.

Die Methoden der Klasse I fügten hinzu:

public static System.Drawing.Bitmap ResizeImage(System.Drawing.Image image, Size size)
{
    return ResizeImage(image, size.Width, size.Height);
}


public static Size GetProportionedSize(Image image, int maxWidth, int maxHeight, bool withProportion)
{
    if (withProportion)
    {
        double sourceWidth = image.Width;
        double sourceHeight = image.Height;

        if (sourceWidth < maxWidth && sourceHeight < maxHeight)
        {
            maxWidth = (int)sourceWidth;
            maxHeight = (int)sourceHeight;
        }
        else
        {
            double aspect = sourceHeight / sourceWidth;

            if (sourceWidth < sourceHeight)
            {
                maxWidth = Convert.ToInt32(Math.Round((maxHeight / aspect), 0));
            }
            else
            {
                maxHeight = Convert.ToInt32(Math.Round((maxWidth * aspect), 0));
            }
        }
    }

    return new Size(maxWidth, maxHeight);
}

und neu mit diesen Codes erhältlich:

using (var resized = ImageUtilities.ResizeImage(image, ImageUtilities.GetProportionedSize(image, 50, 100)))
{
    ImageUtilities.SaveJpeg(@"C:\myimage.jpeg", resized, 90);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top