Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Un codificador escribe datos de imagen en una secuencia. Los codificadores pueden comprimir, cifrar y modificar los píxeles de imagen de varias maneras antes de escribirlos en la secuencia. El uso de algunos codificadores da lugar a inconvenientes, por ejemplo, JPEG, que intercambia información de color para mejorar la compresión. Otros codificadores no producen tales pérdidas, por ejemplo, mapa de bits (BMP). Dado que muchos códecs usan tecnología propietaria para lograr una mejor compresión e fidelidad de imagen, los detalles sobre cómo se codifica una imagen están hasta el desarrollador de códecs.
IWICBitmapEncoder
IWICBitmapEncoder es la interfaz principal para codificar una imagen en el formato de destino y se usa para serializar los componentes de una imagen, como miniatura (SetThumbnail) y marcos (CreateNewFrame) en el archivo de imagen.
Cómo y cuándo se produce la serialización se deja al desarrollador del códec. Cada bloque individual de datos dentro del formato de archivo de destino debe ser capaz de establecer independientemente del orden, pero de nuevo, esta es la decisión del desarrollador del códec. Sin embargo, una vez que se llama al método Commit , no se deben permitir los cambios en la imagen y se debe cerrar la secuencia.
IWICBitmapFrameEncode
IWICBitmapFrameEncode es la interfaz para codificar los fotogramas individuales de una imagen. Proporciona métodos para establecer componentes individuales de imágenes de fotogramas, como miniaturas y marcos, así como dimensiones de imagen, PPP y formatos de píxel.
Los fotogramas individuales se pueden codificar con metadatos específicos del marco, por lo que IWICBitmapFrameEncode proporciona acceso a un escritor de metadatos a través del método GetMetadataQueryWriter .
El método Commit del marco confirma todos los cambios en el marco individual e indica que ya no se deben aceptar los cambios en ese marco.
Ejemplo de codificación (TIFF)
En el ejemplo siguiente, se codifica una imagen con formato de archivo de imagen etiquetada (TIFF) mediante IWICBitmapEncoder y IWICBitmapFrameEncode. La salida de TIFF se personaliza mediante WICTiffCompressionOption y el marco de mapa de bits se inicializa mediante las opciones especificadas. Una vez creada la imagen mediante WritePixels, el marco se confirma mediante Commit y la imagen se guarda mediante Commit.
IWICImagingFactory *piFactory = NULL;
IWICBitmapEncoder *piEncoder = NULL;
IWICBitmapFrameEncode *piBitmapFrame = NULL;
IPropertyBag2 *pPropertybag = NULL;
IWICStream *piStream = NULL;
UINT uiWidth = 640;
UINT uiHeight = 480;
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*) &piFactory);
if (SUCCEEDED(hr))
{
hr = piFactory->CreateStream(&piStream);
}
if (SUCCEEDED(hr))
{
hr = piStream->InitializeFromFilename(L"output.tif", GENERIC_WRITE);
}
if (SUCCEEDED(hr))
{
hr = piFactory->CreateEncoder(GUID_ContainerFormatTiff, NULL, &piEncoder);
}
if (SUCCEEDED(hr))
{
hr = piEncoder->Initialize(piStream, WICBitmapEncoderNoCache);
}
if (SUCCEEDED(hr))
{
hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}
if (SUCCEEDED(hr))
{
// This is how you customize the TIFF output.
PROPBAG2 option = { 0 };
option.pstrName = L"TiffCompressionMethod";
VARIANT varValue;
VariantInit(&varValue);
varValue.vt = VT_UI1;
varValue.bVal = WICTiffCompressionZIP;
hr = pPropertybag->Write(1, &option, &varValue);
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Initialize(pPropertybag);
}
}
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->SetSize(uiWidth, uiHeight);
}
WICPixelFormatGUID formatGUID = GUID_WICPixelFormat24bppBGR;
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->SetPixelFormat(&formatGUID);
}
if (SUCCEEDED(hr))
{
// We're expecting to write out 24bppRGB. Fail if the encoder cannot do it.
hr = IsEqualGUID(formatGUID, GUID_WICPixelFormat24bppBGR) ? S_OK : E_FAIL;
}
if (SUCCEEDED(hr))
{
UINT cbStride = (uiWidth * 24 + 7)/8/***WICGetStride***/;
UINT cbBufferSize = uiHeight * cbStride;
BYTE *pbBuffer = new BYTE[cbBufferSize];
if (pbBuffer != NULL)
{
for (UINT i = 0; i < cbBufferSize; i++)
{
pbBuffer[i] = static_cast<BYTE>(rand());
}
hr = piBitmapFrame->WritePixels(uiHeight, cbStride, cbBufferSize, pbBuffer);
delete[] pbBuffer;
}
else
{
hr = E_OUTOFMEMORY;
}
}
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Commit();
}
if (SUCCEEDED(hr))
{
hr = piEncoder->Commit();
}
if (piFactory)
piFactory->Release();
if (piEncoder)
piEncoder->Release();
if (piBitmapFrame)
piBitmapFrame->Release();
if (pPropertybag)
pPropertybag->Release();
if (piStream)
piStream->Release();
return hr;
Uso de las opciones del codificador
Los diferentes codificadores para diferentes formatos deben exponer diferentes opciones para cómo se codifica una imagen. El componente de imágenes de Windows (WIC) proporciona un mecanismo coherente para expresar si se requieren opciones de codificación, a la vez que se permite que las aplicaciones funcionen con varios codificadores sin necesidad de conocer un formato determinado. Esto se logra proporcionando un parámetro IPropertyBag en el método CreateNewFrame y el método Initialize .
El generador de componentes proporciona un punto sencillo para la creación de un conjunto de propiedades de opciones del codificador. Los códecs pueden usar este servicio si necesitan proporcionar un conjunto simple, intuitivo y no conflictante de opciones de codificador. El contenedor de propiedades de imágenes debe inicializarse al crearse con todas las opciones del codificador relevantes para el códec. En el caso de las opciones del codificador del conjunto canónico, el intervalo de valores será aplicado durante la escritura. Para necesidades más avanzadas, los códecs deben desarrollar su propia implementación de la bolsa de propiedades.
Una aplicación recibe el contenedor de opciones del codificador durante la creación del marco y debe configurar cualquier valor antes de inicializar el marco del codificador. Para una aplicación controlada por la interfaz de usuario, puede ofrecer una interfaz de usuario fija para las opciones del codificador canónico y una vista avanzada para las opciones restantes. Los cambios se pueden realizar de uno a uno a través del método Write y cualquier error se notificará a través de IErrorLog. La aplicación de interfaz de usuario siempre debe volver a leer y mostrar todas las opciones después de realizar un cambio en caso de que el cambio provocara un efecto en cascada. Una aplicación debe estar preparada para manejar la inicialización fallida de fotogramas para los códecs que solo proporcionan informes de errores mínimos a través de su contenedor de propiedades.
Opciones del codificador
Una aplicación puede esperar encontrar el siguiente conjunto de opciones de codificador. Las opciones del codificador reflejan las funcionalidades de un codificador y el formato de contenedor subyacente y, por tanto, no son por su naturaleza realmente independientes del códec. Cuando sea posible, se deben normalizar nuevas opciones para que se puedan aplicar a nuevos códecs que surjan.
Nombre de propiedad | VARTYPE | Importancia | Códecs aplicables |
---|---|---|---|
BitmapTransform | VT_UI1 | WICBitmapTransformOptions | JPEG, JPEG XL, HEIF |
Calidad de Compresión | VT_R4 | 0-1.0 | TIFF, JPEG XL |
HeifCompressionMethod | VT_UI1 | WICHeifCompressionOption | HEIF |
ImageQuality | VT_R4 | 0-1.0 | JPEG, JPEG XL, HDPhoto, HEIF |
Sin pérdida | VT_BOOL | TRUE, FALSE | JPEG XL, HDPhoto |
ImageQuality de 0,0 indica la representación de fidelidad más baja posible, mientras que 1,0 indica la fidelidad más alta, lo que también puede implicar la ausencia de pérdida de calidad, dependiendo del códec.
La calidad de compresión de 0,0 significa el esquema de compresión menos eficaz disponible, lo que suele dar lugar a una codificación rápida pero con un tamaño de salida mayor. Un valor de 1.0 significa que el esquema más eficaz disponible, normalmente tarda más tiempo en codificar, pero genera una salida más pequeña. Dependiendo de las funcionalidades del códec, este intervalo se puede asignar a un conjunto discreto de métodos de compresión disponibles.
Sin pérdida significa que el códec codifica la imagen sin pérdida alguna. Si Lossless está habilitado, se omite ImageQuality.
Además de las opciones de codificador genérico anteriores, los códecs proporcionados con WIC admiten las siguientes opciones. Si un códec tiene una necesidad de admitir una opción que sea coherente con el uso de estos códecs proporcionados, se recomienda hacerlo.
Nombre de propiedad | VARTYPE | Importancia | Códecs aplicables |
---|---|---|---|
InterlaceOption | VT_BOOL | Activar/desactivar | PNG |
Opción de filtro | VT_UI1 | WICPngFilterOption | PNG |
Método de compresión TIFF | VT_UI1 | WICTiffCompressionOption | TIFF |
Luminancia | VT_UI4/VT_ARRAY | 64 Entradas (DCT) | JPEG |
Crominancia | VT_UI4/VT_ARRAY | 64 Entradas (DCT) | JPEG |
JpegYCrCbSubsampling | VT_UI1 | WICJpegYCrCbSubsamplingOption | JPEG |
SuppressApp0 | VT_BOOL | JPEG | |
EnableV5Header32bppBGRA | VT_BOOL | Activar/desactivar | BMP |
Use VT_EMPTY para indicar *no establecido* como valor predeterminado. Si se establecen propiedades adicionales pero no se admiten, el codificador debe omitirlas; esto permite a las aplicaciones codificar menos lógica si quieren una funcionalidad que puede estar presente o no.
Ejemplos de opciones del codificador
En el ejemplo de codificación TIFF anterior, se establece una opción de codificador específica. El miembro pstrName de la estructura PROPBAG2 se establece en el nombre de propiedad adecuado, y el VARIANT se establece en el correspondiente VARTYPE y en el valor deseado, que en este caso es un miembro de la enumeración WICTiffCompressionOption.
if (SUCCEEDED(hr))
{
hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}
if (SUCCEEDED(hr))
{
// This is how you customize the TIFF output.
PROPBAG2 option = { 0 };
option.pstrName = L"TiffCompressionMethod";
VARIANT varValue;
VariantInit(&varValue);
varValue.vt = VT_UI1;
varValue.bVal = WICTiffCompressionZIP;
hr = pPropertybag->Write(1, &option, &varValue);
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Initialize(pPropertybag);
}
}
Para usar las opciones predeterminadas del codificador, basta con inicializar el marco de mapa de bits con el contenedor de propiedades devuelto cuando se creó el marco.
if (SUCCEEDED(hr))
{
hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}
if (SUCCEEDED(hr))
{
// Accept the default encoder options.
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Initialize(pPropertybag);
}
}
También es posible eliminar el contenedor de propiedades cuando no se tienen en cuenta las opciones del codificador.
if (SUCCEEDED(hr))
{
hr = piEncoder->CreateNewFrame(&piBitmapFrame, 0);
}
if (SUCCEEDED(hr))
{
// No encoder options.
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Initialize(0);
}
}