Verlustfreie Transformation eines JPEG-Bilds

Wenn Sie ein JPEG-Bild komprimieren, gehen einige der Informationen im Bild verloren. Wenn Sie eine JPEG-Datei öffnen, das Bild ändern und in einer anderen JPEG-Datei speichern, nimmt die Qualität ab. Wenn Sie diesen Prozess mehrmals wiederholen, wird die Bildqualität erheblich beeinträchtigt.

Da JPEG eines der beliebtesten Bildformate im Web ist und menschen gerne JPEG-Bilder ändern, bietet GDI+ die folgenden Transformationen, die auf JPEG-Bildern ohne Informationsverlust durchgeführt werden können:

  • Um 90 Grad drehen
  • Drehen um 180 Grad
  • Drehen um 270 Grad
  • Horizontales Kippen
  • Vertikales Kippen

Sie können eine der in der vorherigen Liste gezeigten Transformationen anwenden, wenn Sie die Save-Methode eines Image-Objekts aufrufen. Wenn die folgenden Bedingungen erfüllt sind, wird die Transformation ohne Informationsverlust fortgesetzt:

  • Die Zum Erstellen des Image-Objekts verwendete Datei ist eine JPEG-Datei.
  • Die Breite und Höhe des Bilds sind beide Vielfache von 16.

Wenn breite und höhe des Bilds nicht beide Vielfache von 16 sind, wird GDI+ sein Bestes tun, um die Bildqualität zu erhalten, wenn Sie eine der in der vorherigen Liste gezeigten Drehungs- oder Umdrehungstransformationen anwenden.

Um ein JPEG-Bild zu transformieren, initialisieren Sie ein EncoderParameters-Objekt , und übergeben Sie die Adresse dieses Objekts an die Save-Methode der Image-Klasse . Initialisieren Sie das EncoderParameters-Objekt , sodass es über ein Array verfügt, das aus einem EncoderParameter-Objekt besteht. Initialisieren Sie dieses EncoderParameter-Objekt , sodass sein Value-Element auf eine ULONG-Variable verweist, die eines der folgenden Elemente der EncoderValue-Enumeration enthält:

  • EncoderValueTransformRotate90,
  • EncoderValueTransformRotate180,
  • EncoderValueTransformRotate270,
  • EncoderValueTransformFlipHorizontal,
  • EncoderValueTransformFlipVertical

Legen Sie das Guid-Element des EncoderParameter-Objekts auf EncoderTransformation fest.

Die folgende Konsolenanwendung erstellt ein Image-Objekt aus einer JPEG-Datei und speichert das Bild dann in einer neuen Datei. Während des Speichervorgangs wird das Bild um 90 Grad gedreht. Wenn breite und höhe des Bilds beide Vielfache von 16 sind, führt das Drehen und Speichern des Bilds zu keinem Informationsverlust.

Die Standard-Funktion basiert auf der Hilfsfunktion GetEncoderClsid, die unter Abrufen des Klassenbezeichners für einen Encoder angezeigt wird.

#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;

INT GetEncoderClsid(const WCHAR* format, CLSID* pClsid);  // helper function

INT main()
{
   // Initialize GDI+.
   GdiplusStartupInput gdiplusStartupInput;
   ULONG_PTR gdiplusToken;
   GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

   CLSID             encoderClsid;
   EncoderParameters encoderParameters;
   ULONG             transformation;
   UINT              width;
   UINT              height;
   Status            stat;

   // Get a JPEG image from the disk.
   Image* image = new Image(L"Shapes.jpg");

   // Determine whether the width and height of the image 
   // are multiples of 16.
   width = image->GetWidth();
   height = image->GetHeight();

   printf("The width of the image is %u", width);
   if(width / 16.0 - width / 16 == 0)
      printf(", which is a multiple of 16.\n");
   else
      printf(", which is not a multiple of 16.\n");

   printf("The height of the image is %u", height);
   if(height / 16.0 - height / 16 == 0)
      printf(", which is a multiple of 16.\n");
   else
      printf(", which is not a multiple of 16.\n");

   // Get the CLSID of the JPEG encoder.
   GetEncoderClsid(L"image/jpeg", &encoderClsid);

   // Before we call Image::Save, we must initialize an
   // EncoderParameters object. The EncoderParameters object
   // has an array of EncoderParameter objects. In this
   // case, there is only one EncoderParameter object in the array.
   // The one EncoderParameter object has an array of values.
   // In this case, there is only one value (of type ULONG)
   // in the array. We will set that value to EncoderValueTransformRotate90.

   encoderParameters.Count = 1;
   encoderParameters.Parameter[0].Guid = EncoderTransformation;
   encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
   encoderParameters.Parameter[0].NumberOfValues = 1;

   // Rotate and save the image.
   transformation = EncoderValueTransformRotate90;
   encoderParameters.Parameter[0].Value = &transformation;
   stat = image->Save(L"ShapesR90.jpg", &encoderClsid, &encoderParameters);

   if(stat == Ok)
      wprintf(L"%s saved successfully.\n", L"ShapesR90.jpg");
   else
      wprintf(L"%d  Attempt to save %s failed.\n", stat, L"ShapesR90.jpg");

   delete image;
   GdiplusShutdown(gdiplusToken);
   return 0;
}