Condividi tramite


Panoramica della codifica

Importante

Alcune informazioni riguardano un prodotto in versione preliminare che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Un codificatore scrive i dati dell'immagine in un flusso. I codificatori possono comprimere, crittografare e modificare i pixel dell'immagine in diversi modi prima di scriverli nel flusso. L'uso di alcuni codificatori comporta compromessi, ad esempio JPEG, che impedisce informazioni sul colore per una migliore compressione. Altri codificatori non comportano tali perdite, ad esempio bitmap (BMP). Poiché molti codec usano la tecnologia proprietaria per ottenere una migliore compressione e fedeltà delle immagini, i dettagli sul modo in cui un'immagine viene codificata spetta allo sviluppatore di codec.

IWICBitmapEncoder

IWICBitmapEncoder è l'interfaccia principale per la codifica di un'immagine nel formato di destinazione e usata per serializzare i componenti di un'immagine, ad esempio l'anteprima (SetThumbnail) e i frame (CreateNewFrame) nel file di immagine.

Come e quando si verifica la serializzazione viene lasciata allo sviluppatore di codec. Ogni singolo blocco di dati all'interno del formato di file di destinazione deve essere in grado di impostare indipendentemente dall'ordine, ma anche in questo caso, si tratta della decisione dello sviluppatore di codec. Dopo aver chiamato il metodo Commit , tuttavia, le modifiche apportate all'immagine non devono essere consentite e il flusso deve essere chiuso.

IWICBitmapFrameEncode

IWICBitmapFrameEncode è l'interfaccia per codificare i singoli fotogrammi di un'immagine. Fornisce metodi per impostare singoli componenti dell'immagine dei fotogrammi, ad esempio anteprime e fotogrammi, nonché dimensioni dell'immagine, DPI e formati pixel.

I singoli fotogrammi possono essere codificati con metadati specifici del frame in modo che IWICBitmapFrameEncode fornisca l'accesso a un writer di metadati tramite il metodo GetMetadataQueryWriter.

Il metodo Commit del frame esegue il commit di tutte le modifiche apportate al singolo frame e indica che le modifiche apportate a tale frame non devono più essere accettate.

Esempio di codifica (TIFF)

Nell'esempio seguente un'immagine TIFF (Tagged Image File Format) viene codificata usando IWICBitmapEncoder e IWICBitmapFrameEncode. L'output TIFF viene personalizzato usando WICTiffCompressionOption e il frame bitmap viene inizializzato usando le opzioni specificate. Dopo aver creato l'immagine usando WritePixels, il commit del frame viene eseguito tramite commit e l'immagine viene salvata usando 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;

Utilizzo delle opzioni del codificatore

I codificatori diversi per formati diversi devono esporre diverse opzioni per la codifica di un'immagine. Windows Imaging Component (WIC) fornisce un meccanismo coerente per esprimere se sono necessarie opzioni di codifica, consentendo comunque alle applicazioni di lavorare con più codificatori senza richiedere la conoscenza di un particolare formato. A tale scopo, fornire un parametro IPropertyBag nel metodo CreateNewFrame e nel metodo Initialize.

La factory dei componenti offre un semplice punto di creazione per la creazione di un contenitore di proprietà delle opzioni del codificatore. I codec possono usare questo servizio se devono fornire un set semplice, intuitivo e non in conflitto di opzioni del codificatore. Il contenitore delle proprietà di imaging deve essere inizializzato durante la creazione con tutte le opzioni del codificatore rilevanti per tale codec. Per le opzioni del codificatore dal set canonico, l'intervallo di valori verrà applicato in scrittura. Per esigenze più avanzate, i codec devono scrivere la propria implementazione del contenitore delle proprietà.

A un'applicazione viene assegnato il contenitore delle opzioni del codificatore durante la creazione dei fotogrammi e deve configurare tutti i valori prima di inizializzare il frame del codificatore. Per un'applicazione guidata dall'interfaccia utente, può offrire un'interfaccia utente fissa per le opzioni del codificatore canonico e una visualizzazione avanzata per le opzioni rimanenti. Le modifiche possono essere apportate una alla volta tramite il metodo Write e qualsiasi errore verrà segnalato tramite IErrorLog. L'applicazione dell'interfaccia utente deve sempre rileggere e visualizzare tutte le opzioni dopo aver apportato una modifica nel caso in cui la modifica ha causato un effetto a catena. Un'applicazione deve essere preparata per gestire l'inizializzazione dei fotogrammi non riuscita per i codec che forniscono solo segnalazioni di errori minime tramite il contenitore delle proprietà.

Opzioni del codificatore

Un'applicazione può prevedere di riscontrare il set di opzioni del codificatore seguente. Le opzioni del codificatore riflettono le funzionalità di un codificatore e il formato del contenitore sottostante e pertanto non sono realmente indipendenti dal codec. Quando possibile, le nuove opzioni devono essere normalizzate in modo che possano essere applicate ai nuovi codec che emergono.

Nome proprietà VARTYPE Valore Codec applicabili
BitmapTransform VT_UI1 WICBitmapTransformOptions JPEG, HEIF
CompressionQuality VT_R4 0-1.0 TIFF
HeifCompressionMethod WICHeifCompressionOption vari HEIF
ImageQuality VT_R4 0-1.0 JPEG, HDPhoto, HEIF
Lossless VT_BOOL TRUE, FAL edizione Standard HDPhoto

ImageQualty di 0,0 indica il rendering più basso possibile di fedeltà e 1,0 indica la massima fedeltà, che può anche implicare perdita di dati a seconda del codec.

CompressionQuality pari a 0,0 indica lo schema di compressione meno efficiente disponibile, con conseguente codifica rapida ma output più grande. Il valore 1,0 indica lo schema più efficiente disponibile, in genere richiede più tempo per codificare ma produrre output più piccolo. A seconda delle funzionalità del codec, questo intervallo può essere mappato a un set discreto di metodi di compressione disponibili.

Senza perdita di dati significa che il codec codifica l'immagine come senza perdita di dati senza perdita di dati immagine. Se l'opzione Lossless è abilitata, ImageQuality viene ignorata.

Oltre alle opzioni del codificatore generico precedenti, i codec forniti con WIC supportano le opzioni seguenti. Se un codec deve supportare un'opzione coerente con l'utilizzo in questi codec forniti, è consigliabile farlo.

Nome proprietà VARTYPE Valore Codec applicabili
InterlaceOption VT_BOOL Attivato/Disattivato PNG
FilterOption VT_UI1 WICPngFilterOption PNG
TiffCompressionMethod VT_UI1 WICTiffCompressionOption TIFF
Luminanza VT_UI4/VT_ARRAY 64 voci (DCT) JPEG
Crominanza VT_UI4/VT_ARRAY 64 voci (DCT) JPEG
JpegYCrCbSubsampling VT_UI1 WICJpegYCrCbSubsamplingOption JPEG
SuppressApp0 VT_BOOL JPEG
EnableV5Header32bppBGRA VT_BOOL Attivato/Disattivato BMP

Usare VT_EMPTY per indicare *not set* come valore predefinito. Se sono impostate proprietà aggiuntive ma non supportate, il codificatore deve ignorarli; In questo modo, le applicazioni possono scrivere codice senza logica se vogliono una funzionalità che potrebbe essere presente o meno.

Esempi di opzioni del codificatore

Nell'esempio di codifica TIFF precedente viene impostata un'opzione del codificatore specifica. Il membro pstrName della struttura PROPBAG2 viene impostato sul nome della proprietà appropriato e variant viene impostato sul valore VARTYPE e sul valore desiderato, in questo caso un membro dell'enumerazione 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);
    }
}

Per usare le opzioni del codificatore predefinite, è sufficiente inizializzare il frame bitmap con il contenitore delle proprietà restituito al momento della creazione del frame.

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

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

È anche possibile eliminare il contenitore delle proprietà quando non vengono prese in considerazione opzioni di codificatore.

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

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