共用方式為


JPEG 影像的無遺失轉換

當您壓縮 JPEG 影像時,影像中的部分信息會遺失。 如果您開啟 JPEG 檔案、改變影像,並將它儲存至另一個 JPEG 檔案,品質將會降低。 如果您重複該程式多次,您會看到影像品質大幅降低。

因為 JPEG 是網路上最受歡迎的影像格式之一,而且因為人們經常喜歡修改 JPEG 影像,GDI+ 提供下列轉換,可在 JPEG 映射上執行,而不會遺失資訊:

  • 旋轉 90 度
  • 旋轉 180 度
  • 旋轉 270 度
  • 水平翻轉
  • 垂直翻轉

當您呼叫 Image 物件的 Save 方法時,可以套用上述清單中的其中一個轉換。 如果符合下列條件,則轉換將會繼續,而不會遺失資訊:

  • 用來建構 Image 物件的檔案是 JPEG 檔案。
  • 影像的寬度和高度都是 16 的倍數。

如果影像的寬度和高度不是 16 的倍數,GDI+ 會在您套用上述清單中的其中一個旋轉或翻轉轉換時,盡最大努力保留影像品質。

若要轉換 JPEG 映射,請初始化 EncoderParameters 物件,並將該物件的地址傳遞至 Image 類別的 Save 方法。 初始化 EncoderParameters 物件,使其具有由一個 EncoderParameter 物件所組成的數位。 初始化一個 EncoderParameter 物件,使其 Value 成員指向 ULONG 變數,該變數會保存下列其中一個 EncoderValue 列舉元素:

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

EncoderParameter 物件的 Guid 成員設定為 EncoderTransformation。

下列主控台應用程式會從 JPEG 檔案建立 Image 物件,然後將映像儲存至新的檔案。 在儲存過程中,影像會旋轉 90 度。 如果影像的寬度和高度都是 16 的倍數,則旋轉和儲存影像的程式不會遺失資訊。

main 函式依賴 Helper 函式 GetEncoderClsid,其顯示在 擷取編碼器的類別標識碼中。

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