Condividi tramite


Trasformazione di un'immagine JPEG senza perdita di dati

Quando si comprime un'immagine JPEG, alcune delle informazioni nell'immagine vengono perse. Se si apre un file JPEG, modificare l'immagine e salvarla in un altro file JPEG, la qualità verrà ridotta. Se si ripete il processo molte volte, si noterà una riduzione sostanziale della qualità dell'immagine.

Poiché JPEG è uno dei formati di immagine più diffusi sul Web e poiché le persone spesso amano modificare le immagini JPEG, GDI+ fornisce le trasformazioni seguenti che possono essere eseguite nelle immagini JPEG senza perdita di informazioni:

  • Ruotare 90 gradi
  • Ruotare 180 gradi
  • Ruotare 270 gradi
  • Capovolgi orizzontalmente
  • Capovolgi verticalmente

È possibile applicare una delle trasformazioni visualizzate nell'elenco precedente quando si chiama il metodo Save di un oggetto Image . Se vengono soddisfatte le condizioni seguenti, la trasformazione procederà senza perdita di informazioni:

  • Il file usato per costruire l'oggetto Image è un file JPEG.
  • La larghezza e l'altezza dell'immagine sono entrambi più di 16.

Se la larghezza e l'altezza dell'immagine non sono entrambe più di 16, GDI+ farà il meglio per mantenere la qualità dell'immagine quando si applica una delle trasformazioni di rotazione o scorrimento visualizzate nell'elenco precedente.

Per trasformare un'immagine JPEG, inizializzare un oggetto EncoderParameters e passare l'indirizzo di tale oggetto al metodo Save della classe Image . Inizializzare l'oggetto EncoderParameters in modo che disponga di una matrice costituita da un oggetto EncoderParameter . Inizializzare l'oggetto EncoderParameter in modo che il relativo membro Value punti a una variabile ULONG che contiene uno degli elementi seguenti dell'enumerazione EncoderValue :

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

Impostare il membro Guid dell'oggetto EncoderParameter su EncoderTransformation.

L'applicazione console seguente crea un oggetto Image da un file JPEG e quindi salva l'immagine in un nuovo file. Durante il processo di salvataggio, l'immagine viene ruotata a 90 gradi. Se la larghezza e l'altezza dell'immagine sono entrambe più di 16, il processo di rotazione e salvataggio dell'immagine causa nessuna perdita di informazioni.

La funzione principale si basa sulla funzione helper GetEncoderClsid, visualizzata in Recupero dell'identificatore di classe per un codificatore.

#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;
}