Ändern der Größe eines Bildes ohne Qualitätsverlust [geschlossen]

108

Wie kann ich die Größe eines Bildes ändern, ohne dass die Bildqualität beeinträchtigt wird?

öffentliche statische
quelle
Können Sie uns weitere Einzelheiten mitteilen? Wie groß sind Ihre Bilder und wie groß müssen sie sein?
Mark Ransom
6
imageresizing.net - Diese Bibliothek produziert die qualitativ hochwertigsten Bilder, die Sie mit .NET
Lilith River

Antworten:

217

Wie rcar sagt, kann man nicht ohne Qualitätsverlust das Beste, was man in c # tun kann, ist:

Bitmap newImage = new Bitmap(newWidth, newHeight);
using (Graphics gr = Graphics.FromImage(newImage))
{
    gr.SmoothingMode = SmoothingMode.HighQuality;
    gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
    gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
    gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
}
Kris Erickson
quelle
2
Ich könnte hinzufügen, dass der Benutzer (wenn möglich) mit einem Bitmap-Bild beginnen sollte, das beispielsweise doppelt so groß ist, wie es sein muss, und dann verkleinern sollte. Das resultierende Bild sollte ziemlich glatt sein.
Brezel
2
gr.SmoothingMode = SmoothingMode.HighQuality ist besserer Code. Derzeit sind HighQuality und AntiAlias ​​dasselbe, aber vielleicht wird Microsoft in Zukunft etwas Neues erfinden. HighQuality sollte immer ein Alias ​​für die Besten sein.
Eyal
4
Die Methode 'System.Drawing.Image.Save (String-Dateiname, ImageFormat-Format)' speichert JPGs mit der Qualität 75. Das Bild war verschwommen und vom Client nicht akzeptabel. Das Qualitätsproblem wurde behoben, indem stattdessen Save (String-Dateiname, ImageCodecInfo-Encoder, EncoderParameters encoderParams) verwendet und ein Qualitätswert angegeben wurde, der näher an 100 liegt.
Riga,
3
Dies hinterlässt manchmal Artefakte am Rand des Bildes ...
jjxtra
1
Ich hatte Artefakte an der Grenze, als ich das benutzte. Irgendwelche Vorschläge?
Gopichandar
32

Wenn Sie keine Vektorgrafiken erstellen, können Sie die Größe eines Bildes nicht ändern, ohne die Bildqualität zu verlieren.

Geil
quelle
1
es sei denn, Sie erweitern es ...
Blair Conrad
Sie können es erweitern, ohne Informationen zu verlieren, aber es gibt verschiedene Arten von Filtern, die unterschiedliche Ergebnisse liefern können - Halten nullter Ordnung, Tiefpass usw.
Adam Rosenfield,
24
private static Image resizeImage(Image imgToResize, Size size)
{
    int sourceWidth = imgToResize.Width;
    int sourceHeight = imgToResize.Height;

    float nPercent = 0;
    float nPercentW = 0;
    float nPercentH = 0;

    nPercentW = ((float)size.Width / (float)sourceWidth);
    nPercentH = ((float)size.Height / (float)sourceHeight);

    if (nPercentH < nPercentW)
        nPercent = nPercentH;
    else
        nPercent = nPercentW;

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

    Bitmap b = new Bitmap(destWidth, destHeight);
    Graphics g = Graphics.FromImage((Image)b);
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;

    g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
    g.Dispose();

    return (Image)b;
}

von hier

ozba
quelle
Dies funktioniert, liefert jedoch die gleiche Qualität wie Kris Ericksos Antwort. Schön zu sehen, Größe verwendet obwohl ...
Sam Jones
3

Wenn Sie die Größe nicht ändern, können Sie dies nicht mit Rastergrafiken tun.

Mit einer guten Filterung und Glättung können Sie die Größe ändern, ohne die Qualität zu beeinträchtigen.

Sie können auch die DPI-Metadaten des Bildes ändern (vorausgesetzt, es enthält einige), die genau die gleiche Pixelanzahl beibehalten, aber die Einstellung der Bildbearbeiter bei Messungen in der realen Welt ändern.

Und um alle Grundlagen abzudecken: Wenn Sie wirklich nur die Dateigröße des Bildes und nicht die tatsächlichen Bildabmessungen gemeint haben, schlage ich vor, dass Sie sich eine verlustfreie Codierung der Bilddaten ansehen. Mein Vorschlag hierfür wäre, das Bild als PNG-Datei erneut zu speichern (ich verwende normalerweise Farbe als kostenlosen Transcoder für Bilder in Windows. Laden Sie das Bild in Farbe, speichern Sie es wie im neuen Format).

workmad3
quelle
3

Sie können die Größe eines Bildes nicht ändern, ohne an Qualität zu verlieren, einfach weil Sie die Anzahl der Pixel reduzieren.

Reduzieren Sie die Größe auf der Clientseite nicht, da Browser die Größe von Bildern nicht gut ändern können.

Sie können die Größe programmgesteuert ändern, bevor Sie sie rendern oder wenn ein Benutzer sie hochlädt.

In diesem Artikel wird eine Möglichkeit erläutert, dies in c # zu tun: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx

AaronS
quelle
"Browser können die Größe von Bildern nicht gut ändern" - dies mag im Jahr 2008 der Fall gewesen sein, aber zum Glück sind wir in diesem Bereich jetzt meilenweit voraus (zu einem großen Teil, da alte IE-Versionen langsam verblassen).
Camilo Martin
2

Überprüfen Sie, ob Ihnen die Bildgrößenänderungsqualität dieses Open Source-ASP.NET-Moduls gefällt . Es gibt eine Live-Demo, mit der Sie selbst herumspielen können. Es liefert Ergebnisse, die (für mich) nicht von der Photoshop-Ausgabe zu unterscheiden sind. Es hat auch ähnliche Dateigrößen - MS hat gute Arbeit mit ihrem JPEG-Encoder geleistet.


quelle
JPEG ist ein relativ einfaches Format. Es gibt nicht viel, was Sie tun können, um Referenzimplementierungen in Bezug auf Qualität / Dateigröße zu übertreffen, da es sich am Ende nur um DCT-Koeffizienten mit generischer Komprimierung handelt.
Camilo Martin
1

Es gibt etwas da draußen, kontextabhängige Größenänderung, ich weiß nicht, ob Sie es verwenden können, aber es lohnt sich, es sich anzusehen, das ist sicher

Eine schöne Video-Demo (Vergrößerung erscheint in der Mitte) http://www.youtube.com/watch?v=vIFCV2spKtg

Hier könnte es Code geben. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/

War das übertrieben? Vielleicht gibt es einige einfache Filter, die Sie auf ein vergrößertes Bild anwenden können, um die Pixel ein wenig zu verwischen. Sie könnten sich das ansehen.

Sieger
quelle
Ich vermute, es hat nichts mit der ursprünglichen Frage zu tun, aber ich liebe diese Technik.
Matt Cruikshank
1

Ändern Sie die Größe größer oder kleiner? Um einen kleinen Prozentsatz oder um einen größeren Faktor wie 2x, 3x? Was verstehen Sie unter Qualität für Ihre Bewerbung? Und welche Art von Bildern - Fotografien, scharfkantige Strichzeichnungen oder was? Schreiben Sie Ihren eigenen Pixel-Schleifcode auf niedriger Ebene oder versuchen Sie, dies so weit wie möglich mit vorhandenen Bibliotheken (.net oder was auch immer) zu tun?

Zu diesem Thema gibt es eine große Menge an Wissen. Das Schlüsselkonzept ist die Interpolation.

Browsing-Empfehlungen:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* für C #: https: //secure.codeproject.com/KB/GDI-plus/imageprocessing4.aspx?display=PrintAll&fid=3657&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&select=629945 * Dies ist Java-spezifisch, kann aber lehrreich sein - http: //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

DarenW
quelle
1

Hier finden Sie auch Wasserzeichencodes in dieser Klasse:

public class ImageProcessor
    {
        public Bitmap Resize(Bitmap image, int newWidth, int newHeight, string message)
        {
            try
            {
                Bitmap newImage = new Bitmap(newWidth, Calculations(image.Width, image.Height, newWidth));

                using (Graphics gr = Graphics.FromImage(newImage))
                {
                    gr.SmoothingMode = SmoothingMode.AntiAlias;
                    gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    gr.DrawImage(image, new Rectangle(0, 0, newImage.Width, newImage.Height));

                    var myBrush = new SolidBrush(Color.FromArgb(70, 205, 205, 205));

                    double diagonal = Math.Sqrt(newImage.Width * newImage.Width + newImage.Height * newImage.Height);

                    Rectangle containerBox = new Rectangle();

                    containerBox.X = (int)(diagonal / 10);
                    float messageLength = (float)(diagonal / message.Length * 1);
                    containerBox.Y = -(int)(messageLength / 1.6);

                    Font stringFont = new Font("verdana", messageLength);

                    StringFormat sf = new StringFormat();

                    float slope = (float)(Math.Atan2(newImage.Height, newImage.Width) * 180 / Math.PI);

                    gr.RotateTransform(slope);
                    gr.DrawString(message, stringFont, myBrush, containerBox, sf);
                    return newImage;
                }
            }
            catch (Exception exc)
            {
                throw exc;
            }
        }

        public int Calculations(decimal w1, decimal h1, int newWidth)
        {
            decimal height = 0;
            decimal ratio = 0;


            if (newWidth < w1)
            {
                ratio = w1 / newWidth;
                height = h1 / ratio;

                return height.To<int>();
            }

            if (w1 < newWidth)
            {
                ratio = newWidth / w1;
                height = h1 * ratio;
                return height.To<int>();
            }

            return height.To<int>();
        }

    }
cagin
quelle