2016-02-03 22 views
6

Ich möchte eine Funktion, die die Bildgröße reduziert.Bildgröße in C reduzieren #

Die Funktion sollte die Bild-URL nehmen, prüfen ist Bild 4MB Größe oder größer und wenn es dann Größe zu Liebhaber dann 4MB und Rückkehr Bytes wird.

Ich habe nächste Methode:

public byte[] ResizeImage(string url) 
{ 
    var uri = new Uri(url); 
    var c = new WebClient(); 
    var oldImgStream = new MemoryStream(c.DownloadData(uri)); 

    if (oldImgStream.Length <= 4194304) 
    { 
     return oldImgStream.ToArray(); 
    } 

    using (var oldImage = new Bitmap(oldImgStream)) 
    using (var newImageStream = new MemoryStream()) 
    { 
     var format = oldImage.RawFormat; 
     float resizePercent = (float)4194304/oldImgStream.Length; 
     var newImage = ResizeImageByPercent(oldImage, resizePercent); 

     newImage.Save(newImageStream, format); 

     return newImageStream.ToArray(); 
    } 
} 

public static Bitmap ResizeImageByPercent(Bitmap image, float resizePercent) 
{ 
    //Set minimum resizePercentage to 80% 
    resizePercent = resizePercent > 0.8 ? (float)0.8 : resizePercent; 

    int newWidth = (int)(image.Width * resizePercent); 
    int newHeight = (int)(image.Height * resizePercent); 

    var newImage = new Bitmap(newWidth, newHeight); 
    using (var graphics = Graphics.FromImage(newImage)) 
    { 
     graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 
     graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 
     graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; 
     graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; 
     graphics.FillRectangle(Brushes.Transparent, 0, 0, newWidth, newHeight); 
     graphics.DrawImage(image, 0, 0, newWidth, newHeight); 
     return newImage; 
    } 
} 

Aber diese feine funktioniert nicht.

Ich habe ein JPG-Bild als Beispiel.

Die Bildgröße beträgt etwas mehr als 4 MB (4194587 Bytes). Auflösung des Bildes ist 2272 x 1704.

Also wenn ich versuche, dieses Bild mit meiner Methode oben zu skalieren. Es zuerst berechnen „resizePercentage“ wie:

float resizePercent = (float)4194304/oldImgStream.Length; 
resizePercent = (float)4194304/4194587; 
resizePercent = 0.9999325 //(99.99325%) 

Aber weil ich mindestens resizePercent gesetzt haben, wird es auf 0,8 (80%) eingestellt werden.

Dann wird mit diesem resizePercent neue Breite und Höhe berechnet.

Und neue Auflösung wird: 1817 x 1363 und Bild wird auf neue Auflösung geändert. Aber nachdem es in Stream gespeichert wird und es Bytes liest, gibt es noch größeres Bild zurück. Site des zurückgegebenen Bildes ist "5146056 Bytes" 5MB

So hat jemand Idee, wie dies zu implementieren, oder was ist das falsch meine Methode, so dass es größeres Bild zurückgibt sogar Auflösung wird reduziert.

soll ich in der Lage sein, eine Größe von Bildern zu reduzieren, png, jpg und gif

+0

Sie wissen nicht, die Qualität der angewandten jpg-Komprimierung, wenn Sie das Bild erhalten. Vielleicht speichern Sie das Bild mit einer höheren Qualität (d. H. Weniger Komprimierung) als das Originalbild. Bleibt das Problem bestehen, wenn Sie mit BMP-Bildern arbeiten? – wertzui

+0

Wenn Ihr Testbild ein JPEG ist, wurde es wahrscheinlich mit einer höheren Komprimierungsrate komprimiert als .NET standardmäßig verwendet. Da JPEGs eine verlustbehaftete Komprimierung verwenden, steht eine große Auswahl an Komprimierungsverhältnissen zur Verfügung. Sie bestimmen, wie körnig das resultierende Bild aussieht. Für PNGs, die verlustfrei sind, ist es immer noch möglich, dass das Originalbild durch einen besseren Algorithmus komprimiert wurde als das, was .NET verwendet. Und so weiter. – adv12

Antwort

1

Es gibt keine 12.59 Korrelation zwischen Bilddateigröße und Auflösung, wenn sie mit komprimierten Bitmaps handelt. Diese Korrelation existiert für eine echte Bitmap (zum Beispiel BMP), da 1 Pixel immer einer definierten Anzahl von Bytes entspricht (basierend auf dem Farbraum). Wenn jedoch über komprimierte Bitmaps, wie JPEG, gesprochen wird, basiert die Dateigröße auf der Effizienz der Komprimierung (wie viele Farben insgesamt codiert werden müssen, wie viele Pixel kombiniert werden können, je nachdem, ob sie die gleiche Farbe haben oder wie viel.) Dithering kann durchgeführt werden, um mehr Pixel der gleichen Farbe zu erzeugen, die kombiniert werden können). Das kann bei einem Bild mit niedrigerer Auflösung weniger sein, aber es könnte ebenso einfach unverändert bleiben oder sogar zunehmen, abhängig davon, wie effizient die ursprüngliche Komprimierung war und wie sich eine geringere Menge an Pixeln insgesamt auf die Effizienz der Komprimierung auswirkt .

Lange und kurze, Sie können nicht einfach eine einfache prozentuale Verringerung der Auflösung anwenden, um eine bestimmte Dateigröße zu gewährleisten. Das Beste, was Sie wirklich tun können, ist, die Auflösung schrittweise zu verringern und die Dateigröße mit jeder Iteration zu testen, bis sie unter Ihrem Schwellenwert liegt, vorausgesetzt, dass sie tatsächlich unter den Schwellenwert sinkt. Mit 4MB zu spielen, ist denkbar, eine bestimmte Auflösung, die definitiv darunter wäre, aber wo dieser Punkt liegt, ist praktisch unmöglich zu berechnen.

Darüber hinaus hängt dies von der Art des Bildformats ab. JPEG-Funktionen versuchen hauptsächlich, Farbe so weit wie möglich zu verteilen (Dithering). Dies ist der Grund, warum JPEGs mit geringerer Qualität Artefakte anzeigen.PNG und GIF sind jedoch meistens indexiert, wo versucht wird, die Gesamtmenge an Farben zu reduzieren (obwohl beide auch Dithering verwenden können). PNG verkompliziert die Sache noch dadurch, dass es auch verlustfreie PNGs geben kann, bei denen alle Farben und Pixel erhalten bleiben, aber eine einfache Komprimierung angewendet wird (ähnlich wie bei einem ZIP-Archiv), um die Dateigröße zu reduzieren. All dies wird sich voneinander und bei verschiedenen Auflösungen unterscheiden.

0

versuchen, die Qualität von InterpolationMode, SmoothingMode, CompositingQuality, PixelOffsetMode zu ändern. Sie können sehen, dass alle diese auf hohe Qualität eingestellt sind