Vue d’ensemble de l’encodage

Important

Certaines informations portent sur la préversion du produit qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Un encodeur écrit des données d’image dans un flux. Les encodeurs peuvent compresser, chiffrer et modifier les pixels de l'image de différentes manières avant de les écrire dans le flux. L'utilisation de certains encodeurs entraîne des compromis ; par exemple, JPEG, qui sacrifie les informations sur les couleurs pour une meilleure compression. D’autres encodeurs n’entraînent pas de telles pertes, comme le bitmap (BMP). Comme de nombreux codecs utilisent une technologie propriétaire pour améliorer la compression et la fidélité de l'image, les détails de l'encodage d'une image dépendent du développeur du codec.

IWICBitmapEncoder

IWICBitmapEncoder est l’interface principale permettant l’encodage d’une image au format cible et utilisée pour sérialiser les composants d’une image, tels que la miniature (SetThumbnail) et les images (CreateNewFrame), dans le fichier image.

La manière et le moment de la sérialisation sont laissés à l’appréciation du développeur du codec. Chaque bloc de données individuel dans le format de fichier cible devrait pouvoir être défini indépendamment de l'ordre, mais là encore, c'est la décision du développeur du codec. Une fois la méthode Commit appelée toutefois, les modifications apportées à l’image ne doivent pas être autorisées et le flux doit être fermé.

IWICBitmapFrameEncode

IWICBitmapFrameEncode est l’interface permettant l’encodage des images individuelles d’une image. Il fournit des méthodes pour définir les composants individuels de l'image, tels que les vignettes et les cadres, ainsi que les dimensions de l'image, le DPI et les formats de pixels.

Les images individuelles peuvent être encodées avec des métadonnées spécifiques à l’image afin que IWICBitmapFrameEncode puisse accéder à un enregistreur de métadonnées via la méthode GetMetadataQueryWriter.

La méthode Commit de l’image valide toutes les modifications apportées à l’image individuelle et indique que les modifications apportées à ce frame ne doivent plus être acceptées.

Exemple d’encodage (TIFF)

Dans l’exemple suivant, une image TIFF (Tagged Image File Format) est encodée à l’aide de IWICBitmapEncoder et d’un IWICBitmapFrameEncode. La sortie TIFF est personnalisée à l’aide de WICTiffCompressionOption et le frame bitmap est initialisé à l’aide des options données. Une fois l’image créée à l’aide de WritePixels , le frame est validé par Commit et l’image est enregistrée à l’aide de 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;

Utilisation des options d’encodeur

Différents encodeurs pour différents formats doivent proposer différentes options pour le codage d'une image. Composant Imagerie Windows (WIC) fournit un mécanisme cohérent pour indiquer si des options d'encodage sont nécessaires, tout en permettant aux applications de travailler avec plusieurs encodeurs sans avoir besoin de connaître un format particulier. Pour ce faire, fournissez un paramètre IPropertyBag sur la méthode CreateNewFrame et la méthode Initialize.

La fabrique de composants fournit un point de création facile pour créer un panier de propriétés d'options d'encodeur. Les codecs peuvent utiliser ce service s'ils ont besoin de fournir un ensemble simple, intuitif et non conflictuel d'options de codage. Le panier de propriétés d'imagerie doit être initialisé lors de la création avec toutes les options d'encodage pertinentes pour ce codec. Pour les options d’encodeur de l’ensemble canonique, la plage de valeurs sera appliquée lors de l’écriture. Pour des besoins plus avancés, les codecs doivent écrire leur propre implémentation de panier de propriétés.

Une application reçoit le panier d'options de l'encodeur lors de la création de la trame et doit configurer toutes les valeurs avant d'initialiser la trame de l'encodeur. Pour une application pilotée par l'interface utilisateur, elle peut offrir une interface fixe pour les options de l'encodeur canonique et une vue avancée pour les options restantes. Les modifications peuvent être apportées une à une par la méthode Write et toute erreur sera signalée par IErrorLog. L'application de l'interface utilisateur doit toujours relire et afficher toutes les options après avoir effectué une modification, au cas où celle-ci entraînerait un effet de cascade. Une application doit être prête à gérer l'échec de l'initialisation de la trame pour les codecs qui ne fournissent qu'un rapport d'erreur minimal par le biais de leur panier de propriétés.

Options d’encodeur

Une application peut s’attendre à rencontrer l’ensemble suivant d’options d’encodeur. Les options de l'encodeur reflètent les capacités d'un encodeur et du format de conteneur sous-jacent, et ne sont donc pas, de par leur nature, réellement agnostiques par rapport au codec. Dans la mesure du possible, les nouvelles options doivent être normalisées afin de pouvoir être appliquées aux nouveaux codecs qui apparaissent.

Nom de la propriété VARTYPE Valeur Codecs applicables
BitmapTransform VT_UI1 WICBitmapTransformOptions JPEG, HEIF
CompressionQuality VT_R4 0-1.0 TIFF
HeifCompressionMethod WICHeifCompressionOption various HEIF
ImageQuality VT_R4 0-1.0 JPEG, HDPhoto, HEIF
Lossless VT_BOOL TRUE, FALSE HDPhoto

Une qualité d'image de 0,0 signifie que le rendu est le moins fidèle possible et 1,0 signifie que le rendu est le plus fidèle possible, ce qui peut également signifier sans perte en fonction du codec.

CompressionQuality de 0,0 signifie que le schéma de compression disponible est le moins efficace, ce qui se traduit généralement par un encodage rapide mais une sortie plus volumineuse. Une valeur de 1,0 correspond au schéma le plus efficace disponible, qui prend généralement plus de temps à encoder mais produit un résultat plus petit. Selon les capacités du codec, cette plage peut être mise en correspondance avec un ensemble discret de méthodes de compression disponibles.

Sans perte signifie que le codec encode l’image sans perte de données. Si l’option Lossless est activée, ImageQuality est ignorée.

En plus des options génériques d'encodage ci-dessus, les codecs fournis avec le WIC supportent les options suivantes. Si un codec doit prendre en charge une option conforme à l'usage des codecs fournis, il est encouragé à le faire.

Nom de la propriété VARTYPE Valeur Codecs applicables
InterlaceOption VT_BOOL Activé/désactivé PNG
FilterOption VT_UI1 WICPngFilterOption PNG
TiffCompressionMethod VT_UI1 WICTiffCompressionOption TIFF
Luminance VT_UI4/VT_ARRAY 64 entrées (DCT) JPEG
Chrominance VT_UI4/VT_ARRAY 64 entrées (DCT) JPEG
JpegYCrCbSubsampling VT_UI1 WICJpegYCrCbSubsamplingOption JPEG
SuppressApp0 VT_BOOL JPEG
EnableV5Header32bppBGRA VT_BOOL Activé/désactivé BMP

Utilisez VT_EMPTY pour indiquer *not set* comme valeur par défaut. Si des propriétés supplémentaires sont définies mais ne sont pas prises en charge, le codeur doit les ignorer ; cela permet aux applications de coder moins de logique si elles veulent une capacité qui peut être présente ou non.

Exemple d’options d’encodeur

Dans l’exemple d’encodage TIFF ci-dessus, une option d’encodeur spécifique est définie. Le membre pstrName de la structure PROPBAG2 est défini sur le nom de propriété approprié, et le VARIANT est défini sur le VARTYPE correspondant et la valeur souhaitée, dans ce cas, un membre de l’énumération 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);
    }
}

Pour utiliser les options d'encodage par défaut, il suffit d'initialiser le cadre bitmap avec le panier de propriétés renvoyé lors de la création du cadre.

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

if (SUCCEEDED(hr))
{        
    // Accept the default encoder options.
    if (SUCCEEDED(hr))
    {
        hr = piBitmapFrame->Initialize(pPropertybag);
    }
}

Il est également possible d'éliminer le panier de propriétés lorsqu'aucune option de codeur n'est envisagée.

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

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