Enumerar parámetros y valores para todos los codificadores
En la siguiente aplicación de consola se enumeran todos los parámetros admitidos por los distintos codificadores instalados en el equipo. La función principal llama a GetImageEncoders para detectar qué codificadores están disponibles. Para cada codificador disponible, la función principal llama a la función auxiliar ShowAllEncoderParameters.
La función ShowAllEncoderParameters llama al método Image::GetEncoderParameterList para detectar qué parámetros admite un codificador determinado. Para cada parámetro admitido, la función enumera la categoría, el tipo de datos y el número de valores. La función ShowAllEncoderParameters se basa en dos funciones auxiliares: EncoderParameterCategoryFromGUID y ValueTypeFromULONG.
#include <windows.h>
#include <gdiplus.h>
#include <strsafe.h>
using namespace Gdiplus;
// Helper functions
void ShowAllEncoderParameters(ImageCodecInfo*);
HRESULT EncoderParameterCategoryFromGUID(GUID guid, WCHAR* category, UINT maxChars);
HRESULT ValueTypeFromULONG(ULONG index, WCHAR* strValueType, UINT maxChars);
INT main()
{
// Initialize GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
UINT num; // Number of image encoders
UINT size; // Size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo;
// How many encoders are there?
// How big (in bytes) is the array of all ImageCodecInfo objects?
GetImageEncodersSize(&num, &size);
// Create a buffer large enough to hold the array of ImageCodecInfo
// objects that will be returned by GetImageEncoders.
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
// GetImageEncoders creates an array of ImageCodecInfo objects
// and copies that array into a previously allocated buffer.
// The third argument, imageCodecInfos, is a pointer to that buffer.
GetImageEncoders(num, size, pImageCodecInfo);
// For each ImageCodecInfo object in the array, show all parameters.
for(UINT j = 0; j < num; ++j)
{
ShowAllEncoderParameters(&(pImageCodecInfo[j]));
}
GdiplusShutdown(gdiplusToken);
return 0;
}
/////////////////////////////////////////////////
// Helper functions
VOID ShowAllEncoderParameters(ImageCodecInfo* pImageCodecInfo)
{
CONST MAX_CATEGORY_LENGTH = 50;
CONST MAX_VALUE_TYPE_LENGTH = 50;
WCHAR strParameterCategory[MAX_CATEGORY_LENGTH] = L"";
WCHAR strValueType[MAX_VALUE_TYPE_LENGTH] = L"";
wprintf(L"\n\n%s\n", pImageCodecInfo->MimeType);
// Create a Bitmap (inherited from Image) object so that we can call
// GetParameterListSize and GetParameterList.
Bitmap bitmap(1, 1);
// How big (in bytes) is the encoder's parameter list?
UINT listSize = 0;
listSize = bitmap.GetEncoderParameterListSize(&pImageCodecInfo->Clsid);
printf(" The parameter list requires %d bytes.\n", listSize);
if(listSize == 0)
return;
// Allocate a buffer large enough to hold the parameter list.
EncoderParameters* pEncoderParameters = NULL;
pEncoderParameters = (EncoderParameters*)malloc(listSize);
if(pEncoderParameters == NULL)
return;
// Get the parameter list for the encoder.
bitmap.GetEncoderParameterList(
&pImageCodecInfo->Clsid, listSize, pEncoderParameters);
// pEncoderParameters points to an EncoderParameters object, which
// has a Count member and an array of EncoderParameter objects.
// How many EncoderParameter objects are in the array?
printf(" There are %d EncoderParameter objects in the array.\n",
pEncoderParameters->Count);
// For each EncoderParameter object in the array, list the
// parameter category, data type, and number of values.
for(UINT k = 0; k < pEncoderParameters->Count; ++k)
{
EncoderParameterCategoryFromGUID(
pEncoderParameters->Parameter[k].Guid, strParameterCategory, MAX_CATEGORY_LENGTH);
ValueTypeFromULONG(
pEncoderParameters->Parameter[k].Type, strValueType, MAX_VALUE_TYPE_LENGTH);
printf(" Parameter[%d]\n", k);
wprintf(L" The category is %s.\n", strParameterCategory);
wprintf(L" The data type is %s.\n", strValueType);
printf(" The number of values is %d.\n",
pEncoderParameters->Parameter[k].NumberOfValues);
} // for
free(pEncoderParameters);
} // ShowAllEncoderParameters
HRESULT EncoderParameterCategoryFromGUID(GUID guid, WCHAR* category, UINT maxChars)
{
HRESULT hr = E_FAIL;
if(guid == EncoderCompression)
hr = StringCchCopyW(category, maxChars, L"Compression");
else if(guid == EncoderColorDepth)
hr = StringCchCopyW(category, maxChars, L"ColorDepth");
else if(guid == EncoderScanMethod)
hr = StringCchCopyW(category, maxChars, L"ScanMethod");
else if(guid == EncoderVersion)
hr = StringCchCopyW(category, maxChars, L"Version");
else if(guid == EncoderRenderMethod)
hr = StringCchCopyW(category, maxChars, L"RenderMethod");
else if(guid == EncoderQuality)
hr = StringCchCopyW(category, maxChars, L"Quality");
else if(guid == EncoderTransformation)
hr = StringCchCopyW(category, maxChars, L"Transformation");
else if(guid == EncoderLuminanceTable)
hr = StringCchCopyW(category, maxChars, L"LuminanceTable");
else if(guid == EncoderChrominanceTable)
hr = StringCchCopyW(category, maxChars, L"ChrominanceTable");
else if(guid == EncoderSaveFlag)
hr = StringCchCopyW(category, maxChars, L"SaveFlag");
else
hr = StringCchCopyW(category, maxChars, L"Unknown category");
return hr;
} // EncoderParameterCategoryFromGUID
HRESULT ValueTypeFromULONG(ULONG index, WCHAR* strValueType, UINT maxChars)
{
HRESULT hr = E_FAIL;
WCHAR* valueTypes[] = {
L"Nothing", // 0
L"ValueTypeByte", // 1
L"ValueTypeASCII", // 2
L"ValueTypeShort", // 3
L"ValueTypeLong", // 4
L"ValueTypeRational", // 5
L"ValueTypeLongRange", // 6
L"ValueTypeUndefined", // 7
L"ValueTypeRationalRange"}; // 8
hr = StringCchCopyW(strValueType, maxChars, valueTypes[index]);
return hr;
} // ValueTypeFromULONG
Al ejecutar la aplicación de consola anterior, obtendrá una salida similar a la siguiente:
image/bmp
The parameter list requires 0 bytes.
image/jpeg
The parameter list requires 172 bytes.
There are 4 EncoderParameter objects in the array.
Parameter[0]
The category is Transformation.
The data type is Long.
The number of values is 5.
Parameter[1]
The category is Quality.
The data type is LongRange.
The number of values is 1.
Parameter[2]
The category is LuminanceTable.
The data type is Short.
The number of values is 0.
Parameter[3]
The category is ChrominanceTable.
The data type is Short.
The number of values is 0.
image/gif
The parameter list requires 0 bytes.
image/tiff
The parameter list requires 160 bytes.
There are 3 EncoderParameter objects in the array.
Parameter[0]
The category is Compression.
The data type is Long.
The number of values is 5.
Parameter[1]
The category is ColorDepth.
The data type is Long.
The number of values is 5.
Parameter[2]
The category is SaveFlag.
The data type is Long.
The number of values is 1.
image/png
The parameter list requires 0 bytes.
Puede extraer las siguientes conclusiones examinando la salida del programa anterior:
- El codificador JPEG admite las categorías de parámetros Transformation, Quality, LuminanceTable y ChrominanceTable.
- El codificador TIFF admite las categorías de parámetros Compression, ColorDepth y SaveFlag.
También puede ver el número de valores aceptables para cada categoría de parámetros. Por ejemplo, puede ver que la categoría de parámetro ColorDepth (códec TIFF) tiene cinco valores de tipo ULONG. En el código siguiente se enumeran esos cinco valores. Supongamos que pEncoderParameters es un puntero a un objeto EncoderParameters que representa el codificador TIFF.
ULONG* pUlong = (ULONG*)(pEncoderParameters->Parameter[1].Value);
ULONG numVals = pEncoderParameters->Parameter[1].NumberOfValues;
printf("\nThe allowable values for ColorDepth are\n");
for(ULONG k = 0; k < numVals; ++k)
{
printf(" %u\n", pUlong[k]);
}
Este código anterior genera el siguiente resultado:
The allowable values for ColorDepth are
1
4
8
24
32
Nota
En algunos casos, los valores de un objeto EncoderParameter son los valores numéricos de los elementos de la enumeración EncoderValue . Sin embargo, los números de la lista anterior no se relacionan con la enumeración EncoderValue . Los números significan 1 bit por píxel, 2 bits por píxel, etc.
Si escribe código similar al ejemplo anterior para investigar los valores permitidos para las otras categorías de parámetros, obtendrá un resultado similar al siguiente.
Parámetro del codificador JPEG | Valores permitidos |
---|---|
Transformación | EncoderValueTransformRotate90 EncoderValueTransformRotate180 EncoderValueTransformRotate270 EncoderValueTransformFlipHorizontal EncoderValueTransformFlipVertical |
Calidad | De 0 a 100 |
Parámetro del codificador TIFF | Valores permitidos |
---|---|
Compresión | EncoderValueCompressionLZW EncoderValueCompressionCCITT3 EncoderValueCompressionCCITT4 EncoderValueCompressionRle EncoderValueCompressionNone |
ColorDepth | 1, 4, 8, 24, 32 |
SaveFlag | EncoderValueMultiFrame |
Nota
Si el ancho y el alto de una imagen JPEG son múltiplos de 16, puede aplicar cualquiera de las transformaciones permitidas por la categoría de parámetros EncoderTransformation (por ejemplo, rotación de 90 grados) sin pérdida de información.