Laden...

JPEG-Dateigröße beeinflussen?!

Erstellt von -acid- vor 19 Jahren Letzter Beitrag vor 19 Jahren 3.334 Views
-
-acid- Themenstarter:in
885 Beiträge seit 2004
vor 19 Jahren
JPEG-Dateigröße beeinflussen?!

Hallo Leute,

ich habe ein JPEG Bild von 20KB, welches ich gerne mit neuen Maßen kopieren möchte. Vorher war es 575 x 441 Pixel und wird auch jetzt schon mit 120 x 100 Pixel kopiert. Problem ist hierbei, dass das neue Bild, etwa ~4KB größer ist, als das Original. Da es aber von den Maßen her kleiner ist, soll es auch von der Dateigröße kleiner werden.

Wie kann ich das beeinflussen? Ich nehme an, dass hat was mit der Komprimierung zu tun...

Hier der Code:

Size newSize = new Size(120,100);
Bitmap NewImage = new Bitmap(Image.FromFile(Path), newSize);
NewImage.Save("D:\\Bilder\\Test\\Kopie.jpg");

Danke,
-acid-

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

gemacht habe ich das noch nicht, aber meine Suche in der .NET-Doku nach "image jpeg quality" hat genau einen Treffer zu Tage gefördert und der sieht passend aus:

---schnipp---
Ein Encoder-Objekt, das mit der GUID für die Qualitäts-Parameterkategorie initialisiert wird.

public static readonly Encoder Quality;

Im folgenden Beispiel wird ein Bitmap-Objekt aus einer BMP-Datei erstellt. Die Bitmap wird in drei JPEG-Dateien mit unterschiedlichem Qualitätsniveau gespeichert.


using System;
using System.Drawing;
using System.Drawing.Imaging;
class Example_SetJPEGQuality
{
   public static void Main()
   {
      Bitmap myBitmap;
      ImageCodecInfo myImageCodecInfo;
      Encoder myEncoder;
      EncoderParameter myEncoderParameter;
      EncoderParameters myEncoderParameters;
      // Create a Bitmap object based on a BMP file.
      myBitmap = new Bitmap("Shapes.bmp");
      // Get an ImageCodecInfo object that represents the JPEG codec.
      myImageCodecInfo = GetEncoderInfo("image/jpeg");
      // Create an Encoder object based on the GUID
      // for the Quality parameter category.
      myEncoder = Encoder.Quality;
      // Create an EncoderParameters object.
      // An EncoderParameters object has an array of EncoderParameter
      // objects. In this case, there is only one
      // EncoderParameter object in the array.
      myEncoderParameters = new EncoderParameters(1);
      // Save the bitmap as a JPEG file with quality level 25.
      myEncoderParameter = new EncoderParameter(myEncoder, 25L);
      myEncoderParameters.Param[0] = myEncoderParameter;
      myBitmap.Save("Shapes025.jpg", myImageCodecInfo, myEncoderParameters);
      // Save the bitmap as a JPEG file with quality level 50.
      myEncoderParameter = new EncoderParameter(myEncoder, 50L);
      myEncoderParameters.Param[0] = myEncoderParameter;
      myBitmap.Save("Shapes050.jpg", myImageCodecInfo, myEncoderParameters);
      // Save the bitmap as a JPEG file with quality level 75.
      myEncoderParameter = new EncoderParameter(myEncoder, 75L);
      myEncoderParameters.Param[0] = myEncoderParameter;
      myBitmap.Save("Shapes075.jpg", myImageCodecInfo, myEncoderParameters);
   }
   private static ImageCodecInfo GetEncoderInfo(String mimeType)
   {
      int j;
      ImageCodecInfo[] encoders;
      encoders = ImageCodecInfo.GetImageEncoders();
      for(j = 0; j < encoders.Length; ++j)
      {
         if(encoders[j].MimeType == mimeType)
            return encoders[j];
      }
      return null;
   }
}

---schnapp---

HTH

herbivore

-
-acid- Themenstarter:in
885 Beiträge seit 2004
vor 19 Jahren

Also ich bin ja baff g
Es hat funktioniert. Hab den Code etwas abgewandelt. Schade ist nur, dass ich überhaupt nicht verstehe für was die Funktion "GetEncoderInfo" ist und warum dieses "EncoderParameters" gebraucht wird.

Hier mal mein Code, den ich gerne noch etwas optimieren will, deswegen die Fragen. Denn ich möchte auch verstehen was ich wo "abgeschrieben" habe. Vielleicht könnt ihr mir ja etwas unter die Arme kreifen.

//-Thumbnail erstellen-//
Size NewImageSize = new Size(Convert.ToInt16(NewImageWidth), Convert.ToInt16(NewImageHeight));
Bitmap NewImage = new Bitmap(Image.FromFile(Path + File), NewImageSize);

ImageCodecInfo MyImageCodecInfo = GetEncoderInfo("image/jpeg");
Encoder MyEncoder = Encoder.Quality;
EncoderParameters MyEncoderParameters = new EncoderParameters(1);
			
// Speichert das Bitmap als JPEG-Datei mit Qualitätsstufe 50
EncoderParameter MyEncoderParameter = new EncoderParameter(MyEncoder, 50L);
MyEncoderParameters.Param[0] = MyEncoderParameter;
NewImage.Save(Path + "\\" + Folder[3] + "\\" + File, MyImageCodecInfo, MyEncoderParameters);
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

fangen wir mal hinten an:

Das Bild soll gespeichert werden:


NewImage.Save(Path + "\\" + Folder[3] + "\\" + File, myImageCodecInfo, myEncoderParameters);

Nun gibt es ja viele Bildformate wie BMP, JPG, GIF, PNG und noch viele mehr. Also muss man dem Bild (Image) sagen, in welchem Format es gespeichert werden soll. Das passiert mit der ImageCodecInfo.


myImageCodecInfo = GetEncoderInfo("image/jpeg");

Zu jedem Bildformat, gibt es eine Reihe von Unterformaten, im einfachsten Fall ist das für eine BMP eine Unterscheidung nach Anzahl der Bits pro Pixel (z.b. 1Bit = 2 Farben, 4Bit = 16 Farben, 8Bit = 256 Farben, 16Bit = 65536 Farben, 24Bit = 16 Mio Farben), bei GIFs z.B. statische oder animierte Bilder und bei JPEG z.B. die Kompressionsrate (das ist nicht 100% präzise, aber ich denke, es hilft dem Verständnis). JPEGs kann man z.B. auch noch im progressiven Format speichern, dann wird beim Laden über langsame Verbindungen im Browser zuerst eine unscharfe Version angezeigt, die langsam immer schärfer wird. Klar das die Daten in einer anderen Reihenfolge (in einem anderen Unterformat) gespeichert werden müssen, als in einem "normalen" JPEG, das sich von oben nach unten aufbaut.

Diese Informationen werden über myEncoderParameters zur Verfügung gestellt. Dabei ist


EncoderParameters myEncoderParameters = new EncoderParameters(1);

nichts weiter als ein Array, dass in diesem Fall nur 1 Element enthält. Aber nach dem oben gesagten könnten weitere Informationen notwendig werden, z.B. wenn man das JPEG auch noch progressiv speichern möchte. Dann bräuchte man entsprechend mehr Array-Elemente.

Dir geht es aber hier nur um die Qualität, also muss die Qualität dem Speicheralgorithmus als EncoderParameter übergeben werden,


Encoder myEncoder = Encoder.Quality;
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);

was klarer (und kürzer) wird, wenn man gleich schreibt:


EncoderParameter myEncoderParameter = new EncoderParameter(Encoder.Quality, 50L);

Jetzt haben wir einen Parameter, der sagt, das die Qualität (Encoder.Quality) fünfzig (50L) betragen soll.

Nun müssen wird den Parameter noch in das EncoderParameters-Array packen


myEncoderParameters.Param[0] = myEncoderParameter;

und schon kann man die Parameter (myEncoderParameter) an die Save-Methode übergeben (s.o.), die damit jetzt alle Informationen hat, um das Bild im gewünschten Format speichern zu können.

HTH

herbivore

-
-acid- Themenstarter:in
885 Beiträge seit 2004
vor 19 Jahren

ok jetzt ist mir einiges klarer geworden... danke für die aufklärung 🙂