Condividi tramite


Trasformazione senza perdita di dati di un'immagine JPEG

Quando si comprime un'immagine JPEG, alcune delle informazioni nell'immagine andranno perse. Se si apre un file JPEG, modificare l'immagine e salvarla in un altro file JPEG, la qualità diminuisce. Se si ripete questo 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é spesso gli utenti amano modificare immagini JPEG, GDI+ fornisce le trasformazioni seguenti che possono essere eseguite su 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 utilizzato per costruire l'oggettoImageè un file JPEG.
  • La larghezza e l'altezza dell'immagine sono entrambi multipli di 16.

Se la larghezza e l'altezza dell'immagine non sono entrambi multipli di 16, GDI+ farà del suo meglio per mantenere la qualità dell'immagine quando si applica una delle trasformazioni di rotazione o capovolgimento visualizzate nell'elenco precedente.

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

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

Impostare il membro guid dell'oggettoEncoderParametersu EncoderTransformation.

L'applicazione console seguente crea un oggettoimageda un file JPEG e quindi salva l'immagine in un nuovo file. Durante il processo di salvataggio, l'immagine viene ruotata di 90 gradi. Se la larghezza e l'altezza dell'immagine sono entrambi multipli di 16, il processo di rotazione e salvataggio dell'immagine non causa alcuna perdita di informazioni.

La funzione principale si basa sulla funzione helper GetEncoderClsid, illustrata 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;
}