Преобразование JPEG-изображения без потерь
При сжатии изображения JPEG некоторые сведения на изображении теряются. Если открыть JPEG-файл, изменить изображение и сохранить его в другой JPEG-файл, качество снизится. Если вы повторяете этот процесс много раз, вы увидите значительное снижение качества изображения.
Так как JPEG является одним из самых популярных форматов изображений в Интернете, и поскольку людям часто нравится изменять изображения JPEG, GDI+ предоставляет следующие преобразования, которые можно выполнять с изображениями JPEG без потери информации:
- Повернуть на 90 градусов
- Поворот на 180 градусов
- Поворот на 270 градусов
- Переворачивание по горизонтали
- Переворачивание по вертикали
При вызове метода Save объекта Image можно применить одно из преобразований, показанных в предыдущем списке. Если выполняются следующие условия, преобразование будет продолжаться без потери информации:
- Файл, используемый для создания объекта Image , является jpeg-файлом.
- Ширина и высота изображения кратны 16.
Если ширина и высота изображения не кратны 16, GDI+ сделает все возможное, чтобы сохранить качество изображения при применении одного из преобразований поворота или перелистывания, показанных в предыдущем списке.
Чтобы преобразовать изображение JPEG, инициализируйте объект EncoderParameters и передайте адрес этого объекта методу Save класса Image . Инициализируйте объект EncoderParameters , чтобы он был массивом, состоящим из одного объекта EncoderParameter . Инициализируйте один объект EncoderParameter , чтобы его член Value указывал на переменную ULONG , содержащую один из следующих элементов перечисления EncoderValue :
- EncoderValueTransformRotate90,
- EncoderValueTransformRotate180,
- EncoderValueTransformRotate270,
- EncoderValueTransformFlipHorizontal,
- EncoderValueTransformFlipVertical
Задайте для элемента Guid объекта EncoderParameter значение EncoderTransformation.
Следующее консольное приложение создает объект Image из JPEG-файла, а затем сохраняет изображение в новый файл. Во время сохранения изображение поворачивается на 90 градусов. Если ширина и высота изображения кратны 16, процесс поворота и сохранения изображения не приводит к потере информации.
Функция main использует вспомогающую функцию 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;
}