Share via


Información general sobre la codificación

Importante

Parte de la información hace referencia a un producto de versión preliminar que puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

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 sacrifica información de color para mejorar la compresión). Otros codificadores no generan este tipo de pérdidas (por ejemplo, mapa de bits (BMP)). Dado que muchos códecs usan tecnología propietaria para lograr una mejor compresión y fidelidad de imagen, los detalles sobre cómo se codifica una imagen dependen del 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) al archivo de la imagen.

La manera y el momento en que se produce la serialización se deja en manos del desarrollador de códecs. Cada bloque individual de datos dentro del formato de archivo de destino debe poder establecerse independientemente del orden, pero, de nuevo, se trata de la decisión del desarrollador de códecs. 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 de creación de imágenes de marco individuales, como miniaturas y marcos, así como dimensiones de imagen, ppp y formatos de píxel.

Los marcos 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 cuáles de ellos deben dejar de aceptarse.

Ejemplo de codificación (TIFF)

En el ejemplo siguiente, se codifica una imagen con formato de archivo de imagen etiquetada (TIFF) mediante IWICBitmapEncoder e IWICBitmapFrameEncode. La salida TIFF se personaliza mediante WICTiffCompressionOption y el marco del mapa de bits se inicializa mediante las opciones especificadas. Una vez creada la imagen con WritePixels, el marco se confirma por medio de 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 opciones del codificador

Diferentes codificadores para distintos formatos deben exponer diversas opciones relativas a cómo se codifica una imagen. Windows Imaging Component (WIC) proporciona un mecanismo coherente para expresar si se requieren opciones de codificación al tiempo que permite a las aplicaciones funcionar con varios codificadores sin necesidad de conocer un formato determinado. Esto se logra proporcionando un parámetro IPropertyBag en los métodos CreateNewFrame e Initialize.

La fábrica de componentes proporciona un punto de creación sencillo para crear una bolsa de propiedades de opciones del codificador. Los códecs pueden usar este servicio si necesitan proporcionar un conjunto simple, intuitivo y no conflictivo de opciones del codificador. La bolsa de propiedades de creación de imágenes debe inicializarse durante la creación con todas las opciones del codificador pertinentes para ese códec. En el caso de las opciones del codificador del conjunto canónico, el intervalo de valores se aplicará durante la escritura. Para las necesidades más avanzadas, los códecs deben escribir su propia implementación de la bolsa de propiedades.

Una aplicación recibe la bolsa de opciones del codificador durante la creación de marcos y debe configurar cualquier valor antes de inicializar el marco del codificador. En el caso de una aplicación controlada por UI, puede ofrecer una interfaz de usuario fija para las opciones del codificador canónicas y una vista avanzada para las opciones restantes. Los cambios se pueden realizar de uno en uno a través del método Write y cualquier error se notificará a través de IErrorLog. La aplicación de la 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 controlar la inicialización de marcos con errores para los códecs que solo proporcionan informes de errores mínimos a través de su bolsa de propiedades.

Opciones del codificador

Una aplicación puede esperar encontrar el siguiente conjunto de opciones del codificador. Las opciones del codificador reflejan las funcionalidades de un codificador y el formato de contenedor subyacente y, por tanto, por su naturaleza, son 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 Value Códecs aplicables
BitmapTransform VT_UI1 WICBitmapTransformOptions JPEG, HEIF
CompressionQuality VT_R4 0-1,0 TIFF
HeifCompressionMethod WICHeifCompressionOption varios HEIF
ImageQuality VT_R4 0-1,0 JPEG, HDPhoto, HEIF
Lossless VT_BOOL TRUE, FALSE HDPhoto

ImageQualty de 0,0 es la representación de fidelidad más baja posible y 1,0 es la fidelidad más alta, lo que también puede implicar la ausencia de pérdidas dependiendo del códec.

CompressionQuality de 0,0 es el esquema de compresión menos eficaz disponible, lo que suele dar lugar a una codificación rápida, pero una salida mayor. Un valor de 1,0 es 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 como sin pérdida, es decir, que no se han perdido datos de imagen. Si Sin pérdida está habilitado, se omite ImageQuality.

Además de las opciones de codificador genéricas anteriores, los códecs proporcionados con WIC admiten las siguientes opciones. Si un códec tiene la necesidad de admitir una opción que sea coherente con el uso en estos códecs proporcionados, se recomienda hacerlo.

Nombre de propiedad VARTYPE Value Códecs aplicables
InterlaceOption VT_BOOL Activar/desactivar PNG
FilterOption VT_UI1 WICPngFilterOption PNG
TiffCompressionMethod VT_UI1 WICTiffCompressionOption TIFF
Luminancia VT_UI4/VT_ARRAY 64 entradas (DCT) JPEG
Chrominance 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 *sin establecer* 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 de TIFF anterior, se establece una opción del codificador específica. El miembro pstrName de la estructura PROPBAG2 se establece en el nombre de propiedad adecuado, mientras que VARIANT lo hace en el VARTYPE correspondiente y el valor deseado (en este caso, 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 del mapa de bits con la bolsa de propiedades devuelta al crearse 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 la bolsa de propiedades si no se tiene en cuenta ninguna opción del codificador.

if (SUCCEEDED(hr))
{
    hr = piEncoder->CreateNewFrame(&piBitmapFrame, 0);
}

if (SUCCEEDED(hr))
{        
    // No encoder options.
    if (SUCCEEDED(hr))
    {
        hr = piBitmapFrame->Initialize(0);
    }
}