Supporto di JPEG YCbCr

A partire da Windows 8.1, il codec JPEG Windows Imaging Component (WIC) supporta la lettura e la scrittura di dati dell'immaginenel formato YCbC r nativo. Ilsupporto di WIC YCbC r può essere usato insieme a Direct2D per eseguire il rendering didati pixel YCbC r con un effetto immagine. Inoltre, il codec WIC JPEG può usare dati pixel YCbCr prodotti da determinati driver di fotocamera tramite Media Foundation.

I dati pixel YCbC r utilizzano una memoria significativamente inferiore rispetto ai formati di pixel BGRA standard. Inoltre, l'accessoai dati YCbC r consente di scaricare alcune fasi della pipeline di decodifica/codifica JPEG in Direct2D, che è accelerata dalla GPU. Usando YCbCr, l'app può ridurre il consumo di memoria JPEG e i tempi di caricamento per le stesse dimensioni e immagini di qualità. In alternativa, l'app può usare più immagini JPEG a risoluzione superiore senza soffrire di sanzioni sulle prestazioni.

Questo argomento descrive come funzionano i dati YCbCr e come usarli in WIC e Direct2D.

Informazioni sui dati JPEG YCbCr

Questa sezione illustra alcuni concetti chiave necessari per comprendere il funzionamento del supporto di YCbCr in WIC e i relativi vantaggi principali.

Modello di colore YCbCr

WiC in Windows 8 e versioni precedenti supporta quattro modelli di colore diversi, il più comune dei quali è RGB/BGR. Questo modello di colore definisce i dati dei colori usando componenti rossi, verdi e blu; un quarto componente alfa può essere usato anche.

Ecco un'immagine decomposta nei suoi componenti rossi, verdi e blu.

un'immagine scomposta nei suoi componenti rossi, verdi e blu.

YCbCr è un modello di colore alternativo che definisce i dati di colore usando un componente di luminanza (Y) e due componenti di luminanza (Cb e Cr). Viene comunemente usato negli scenari di immagine digitale e video. Il termine YCbCr viene spesso usato in modo intercambiabile con YUV, anche se i due sono tecnicamente distinti.

Esistono diverse varianti di YC b Cr che differiscono in spazi colori e definizioni di intervallo dinamico: WIC supporta in modo specificoi dati JFIFYCbC r JPEG. Per altre informazioni, vedere la specifica JPEG ITU-T81.

Ecco un'immagine decomposta nei componenti Y, Cb e Cr .

un'immagine scomposta nei suoi componenti y, cb e cr.

Layout di memoria planare rispetto ai layout di memoria interleaved

In questa sezione vengono descritte alcune differenze tra l'accesso e l'archiviazione dei dati dei pixel RGB in memoria rispetto ai dati di YCbCr .

I dati dei pixel RGB vengono in genere archiviati usando un layout di memoria interleaved. Ciò significa che i dati per un singolo componente di colore vengono interleavedi tra pixel e ogni pixel viene archiviato in modo contiguo in memoria.

Ecco una figura che mostra i dati dei pixel RGBA archiviati in un layout di memoria interleaved.

figura che mostra i dati rgba pixel archiviati in un layout di memoria interleaved.

I dati YCbCr vengono in genere archiviati usando un layout di memoria planare. Ciò significa che ogni componente di colore viene archiviato separatamente nel proprio piano contiguo, per un totale di tre piani. In un'altra configurazione comune, i componenti Cb e Cr vengono interleavedi e archiviati insieme, mentre il componente Y rimane nel proprio piano, per un totale di due piani.

Ecco una figura che mostra i dati di memoria Y planari e interleavedC b r pixel, un layout comunedi memoriaYCbC r.

figura che mostra i dati dei pixel cbcr planari e interleaved, un layout di memoria ycbcr comune.

In WIC e Direct2D ogni piano di colore viene considerato come un oggetto distinto ( un'immagine IWICBitmapSource o ID2D1Bitmap) e collettivamente questi piani formano i dati di backup per un'immagine YCbCr .

Mentre WIC supporta l'accessoai dati YCbC r nelle configurazioni del piano 2 e 3, Direct2D supporta solo l'ex (Ye C cr). Pertanto, quando si usa WIC e Direct2D insieme, è consigliabile usare semprela configurazione YCbC r del piano 2.

Sottocampionamento Chroma

Il modellodi colore YCbC r è adatto per scenari di immagine digitale perché può sfruttare determinati aspetti del sistema visivo umano. In particolare, gli esseri umani sono più sensibili ai cambiamenti nella luminanza (luminosità) di un'immagine e meno sensibili alla dominanza (colore). Suddividendo i dati del colore in componenti di luminanza e luminanza separati, è possibile comprimere in modo selettivo solo i componenti della dominanza per ottenere risparmi sullo spazio con una perdita minima di qualità.

Una tecnica per eseguire questa operazione è denominata sottocampionamento chroma. I piani Ce Cr sono sottocampionati (ridimensionati) in una o entrambe le dimensioni orizzontali e verticali. Per motivi cronologici, ogni sottocampionamento di croma viene comunemente fatto riferimento all'uso di un rapporto J:a:b di tre parti.

Modalità sub-ampling Ridimensionamento orizzontale Ridimensionamento verticale Bit per pixel*
4:4:4 1x 1x 24
4:2:2 2x 1x 16
4:4:0 1x 2x 16
4:2:0 2x 2x 12

 

* Include dati Y.

Dalla tabella precedente, se si usa YCbCr per archiviare i dati dell'immagine non compressi, è possibile ottenere un risparmio di memoria pari al 25% al 62,5% rispetto a 32 bit per pixel dati RGBA, a seconda della modalità di subampling di chroma.

Utilizzo JPEG di YCbCr

A livello generale, la pipeline di decompressione JPEG è costituita dalle fasi seguenti:

  1. Eseguire entropia (ad esempio Huffman) decompressione
  2. Eseguire la dequantizzazione
  3. Eseguire una trasformazione cosina discreta inversa
  4. Eseguire l'upsampling chroma nei dati CbCr
  5. Convertirei dati YCbC r in RGBA (se necessario)

Se il codec JPEG produce dati YCbCr , è possibile evitare i due passaggi finali del processo di decodifica o rinviarli alla GPU. Oltre ai risparmi di memoria elencati nella sezione precedente, questo riduce notevolmente il tempo complessivo necessario per decodificare l'immagine. Lo stesso risparmio si applica quando si codificano i dati YCbCr .

Uso di dati JPEG YCbCr

Questa sezione illustra come usare WIC e Direct2D per operare sui dati YCbCr .

Per visualizzare le indicazioni di questo documento usato in pratica, vedere le ottimizzazioni JPEG YCbCr nell'esempio Direct2D e WIC che illustra tutti i passaggi necessari per decodificare e eseguire il renderingdel contenuto YCbC r in un'app Direct2D.

Uso delleimmagini JPEG di YCbC

La maggior parte delle immagini JPEG viene archiviata come YCbCr. Alcuni JPEG contengono dati cmYK o scala grigia e non usano YCbCr. Ciò significa che in genere, ma non sempre, può usare direttamente contenuto JPEG pre-esistente senza modifiche.

WIC e Direct2D non supportano tutte le possibili configurazioni YCbCr e il supporto YCbCr in Direct2D dipende dall'hardware e dal driver grafici sottostanti. Per questo motivo, una pipeline di creazione di immagini per utilizzo generico deve essere affidabile per le immagini che non usano YCbCr (inclusi altri formati di immagine comuni, ad esempio PNG o BMP) o nei casi in cui il supporto di YCbCr non è disponibile. È consigliabile mantenere la pipeline di creazione di immagini basata su BGRA esistente e abilitare YCbCr come ottimizzazione delle prestazioni quando disponibile.

API del componente Windows Imaging

WiC in Windows 8.1 aggiunge tre nuove interfacce per fornire l'accesso ai dati JPEG YCbCr.

IWICPlanarBitmapSourceTransform

IWICPlanarBitmapSourceTransform è analogo a IWICBitmapSourceTransform, ad eccezione del fatto che produce pixel in una configurazione planare, inclusi i dati YCbCr . È possibile ottenere questa interfaccia chiamando QueryInterface su un'implementazione di IWICBitmapSource che supporta l'accesso planare. Ciò include l'implementazione del codec JPEG di IWICBitmapFrameDecode e IWICBitmapScaler, IWICBitmapFlipRotator e IWICColorTransform.

IWICPlanarBitmapFrameEncode

IWICPlanarBitmapFrameEncode offre la possibilità di codificare i dati dei pixel planari, inclusi i dati YCbCr . È possibile ottenere questa interfaccia chiamando QueryInterface nell'implementazione del codec JPEG di IWICBitmapFrameEncode.

IWICPlanarFormatConverter

IWICPlanarFormatConverter consente a IWICFormatConverter di utilizzare dati pixel planari, tra cui YCbCr, e convertirli in un formato pixel interleaved. Non espone la possibilità di convertire i dati in pixel interleaved in un formato planare. È possibile ottenere questa interfaccia chiamando QueryInterface nell'implementazione fornita da Windows di IWICFormatConverter.

API Direct2D

Direct2D in Windows 8.1 supporta i dati inpixel planari YCbC con il nuovo effetto immagine YCbCr . Questo effetto consente di eseguire il rendering dei dati YCbCr . L'effetto assume come input due interfacce ID2D1Bitmap : una contenente dati Y planari nel formato DXGI_FORMAT_R8_UNORM e una contenente i dati CbCr interleaved nel formato DXGI_FORMAT_R8G8_UNORM. In genere si usa questo effetto al posto di ID2D1Bitmap che contiene dati in pixel BGRA.

L'effetto immagine YCbCr deve essere usato insieme alle API WIC YCbCr che forniscono i dati YCbCr . Ciò agisce in modo efficace per eseguire l'offload di parte del lavoro di decodifica dalla CPU alla GPU, in cui può essere elaborato molto più rapidamente e in parallelo.

Determinare se la configurazione di YCbCr è supportata

Come indicato in precedenza, l'app deve essere affidabile nei casi in cui il supporto di YCbCr non è disponibile. Questa sezione illustra le condizioni che l'app deve verificare. Se uno dei controlli seguenti ha esito negativo, l'app deve eseguire il fallback a una pipeline standard basata su BGRA.

Il componente WIC supporta l'accesso ai dati YCbCr ?

Solo il codec JPEG fornito da Windows e alcune trasformazioni WIC supportano l'accesso ai dati YCbCr . Per un elenco completo, vedere la sezione API del componente windows imaging .

Per ottenere una delle interfacce YCbCr planari, chiamare QueryInterface sull'interfaccia originale. Questo errore avrà esito negativo se il componente non supporta l'accesso ai dati YCbCr .

La trasformazione WIC richiesta è supportata per YCbCr?

Dopo aver ottenuto un IWICPlanarBitmapSourceTransform, devi prima chiamare DoesSupportTransform. Questo metodo accetta come parametri di input il set completo di trasformazioni che si desidera applicare ai dati planari YCbCr e restituisce un valore Boolean che indica il supporto, nonché le dimensioni più vicine alle dimensioni richieste che possono essere restituite. È necessario controllare tutti e tre i valori prima di accedere ai dati pixel con IWICPlanarBitmapSourceTransform::CopyPixels.

Questo modello è simile al modo in cui viene usato IWICBitmapSourceTransform .

Il driver grafico supporta le funzionalità necessarie per usare YCbCr con Direct2D?

Questo controllo è necessario solo se si usa l'effetto Direct2D YCbCr per eseguire il rendering del contenuto YCbCr . Direct2D archivia i dati YCbCr usando i formati DXGI_FORMAT_R8_UNORM e DXGI_FORMAT_R8G8_UNORM pixel, che non sono disponibili da tutti i driver di grafica.

Prima di usare l'effetto immagine YCbCr , devi chiamare ID2D1DeviceContext::IsDxgiFormatSupported per assicurarsi che entrambi i formati siano supportati dal driver.

Codice di esempio

Di seguito è riportato un esempio di codice che illustra i controlli consigliati. Questo esempio è stato tratto dalle ottimizzazioni JPEG YCbCr nell'esempio Direct2D e WIC.

bool DirectXSampleRenderer::DoesWicSupportRequestedYCbCr()
{
    ComPtr<IWICPlanarBitmapSourceTransform> wicPlanarSource;
    HRESULT hr = m_wicScaler.As(&wicPlanarSource);
    if (SUCCEEDED(hr))
    {
        BOOL isTransformSupported;
        uint32 supportedWidth = m_cachedBitmapPixelWidth;
        uint32 supportedHeight = m_cachedBitmapPixelHeight;
        DX::ThrowIfFailed(
            wicPlanarSource->DoesSupportTransform(
                &supportedWidth,
                &supportedHeight,
                WICBitmapTransformRotate0,
                WICPlanarOptionsDefault,
                SampleConstants::WicYCbCrFormats,
                m_planeDescriptions,
                SampleConstants::NumPlanes,
                &isTransformSupported
                )
            );

        // The returned width and height may be larger if IWICPlanarBitmapSourceTransform does not
        // exactly support what is requested.
        if ((isTransformSupported == TRUE) &&
            (supportedWidth == m_cachedBitmapPixelWidth) &&
            (supportedHeight == m_cachedBitmapPixelHeight))
        {
            return true;
        }
    }

    return false;
}

bool DirectXSampleRenderer::DoesDriverSupportYCbCr()
{
    auto d2dContext = m_deviceResources->GetD2DDeviceContext();

    return (d2dContext->IsDxgiFormatSupported(DXGI_FORMAT_R8_UNORM)) &&
        (d2dContext->IsDxgiFormatSupported(DXGI_FORMAT_R8G8_UNORM));
}

Decodifica dei dati pixel YCbCR

Se vuoi otteneredati pixel YCbC, devi chiamare IWICPlanarBitmapSourceTransform::CopyPixels. Questo metodo copia i dati pixel in una matrice di strutture WICBitmapPlane compilate, una per ogni piano di dati desiderato ,ad esempio Y e CbC r. WiCBitmapPlane contiene informazioni sui dati pixel e punta al buffer di memoria che riceverà i dati.

Se vuoi usare i dati pixel YCbCr con altre API WIC, devi creare un IWICBitmap configurato in modo appropriato, chiamare Lock per ottenere il buffer di memoria sottostante e associare il buffer a WICBitmapPlane usato per ricevere i dati pixel YCbCr . È quindi possibile usare normalmente IWICBitmap .

Infine, se si desidera eseguire il rendering dei dati YCbCr in Direct2D, è necessario creare un ID2D1Bitmap da ogni IWICBitmap e usarli come origine per l'effetto immagine YCbCr . WiC consente di richiedere più configurazioni planari. Quando si interagisce con Direct2D, è necessario richiedere due piani, uno usando GUID_WICPixelFormat8bppY e l'altro usando GUID_WICPixelFormat16bppCbCr, in quanto questa è la configurazione prevista da Direct2D.

Codice di esempio

Di seguito è riportato un esempio di codice che illustra i passaggi per decodificare ed eseguire il rendering dei dati YCbCr in Direct2D. Questo esempio è stato tratto dalle ottimizzazioni JPEG YCbCr nell'esempio Direct2D e WIC.

void DirectXSampleRenderer::CreateYCbCrDeviceResources()
{
    auto wicFactory = m_deviceResources->GetWicImagingFactory();
    auto d2dContext = m_deviceResources->GetD2DDeviceContext();

    ComPtr<IWICPlanarBitmapSourceTransform> wicPlanarSource;
    DX::ThrowIfFailed(
        m_wicScaler.As(&wicPlanarSource)
        );

    ComPtr<IWICBitmap> bitmaps[SampleConstants::NumPlanes];
    ComPtr<IWICBitmapLock> locks[SampleConstants::NumPlanes];
    WICBitmapPlane planes[SampleConstants::NumPlanes];

    for (uint32 i = 0; i < SampleConstants::NumPlanes; i++)
    {
        DX::ThrowIfFailed(
            wicFactory->CreateBitmap(
                m_planeDescriptions[i].Width,
                m_planeDescriptions[i].Height,
                m_planeDescriptions[i].Format,
                WICBitmapCacheOnLoad,
                &bitmaps[i]
                )
            );

        LockBitmap(bitmaps[i].Get(), WICBitmapLockWrite, nullptr, &locks[i], &planes[i]);
    }

    DX::ThrowIfFailed(
        wicPlanarSource->CopyPixels(
            nullptr, // Copy the entire source region.
            m_cachedBitmapPixelWidth,
            m_cachedBitmapPixelHeight,
            WICBitmapTransformRotate0,
            WICPlanarOptionsDefault,
            planes,
            SampleConstants::NumPlanes
            )
        );

    DX::ThrowIfFailed(d2dContext->CreateEffect(CLSID_D2D1YCbCr, &m_d2dYCbCrEffect));

    ComPtr<ID2D1Bitmap1> d2dBitmaps[SampleConstants::NumPlanes];
    for (uint32 i = 0; i < SampleConstants::NumPlanes; i++)
    {
        // IWICBitmapLock must be released before using the IWICBitmap.
        locks[i] = nullptr;

        // First ID2D1Bitmap1 is DXGI_FORMAT_R8 (Y), second is DXGI_FORMAT_R8G8 (CbCr).
        DX::ThrowIfFailed(d2dContext->CreateBitmapFromWicBitmap(bitmaps[i].Get(), &d2dBitmaps[i]));
        m_d2dYCbCrEffect->SetInput(i, d2dBitmaps[i].Get());
    }
}

void DirectXSampleRenderer::LockBitmap(
    _In_ IWICBitmap *pBitmap,
    DWORD bitmapLockFlags,
    _In_opt_ const WICRect *prcSource,
    _Outptr_ IWICBitmapLock **ppBitmapLock,
    _Out_ WICBitmapPlane *pPlane
    )
{
    // ComPtr guarantees the IWICBitmapLock is released if an exception is thrown.
    ComPtr<IWICBitmapLock> lock;
    DX::ThrowIfFailed(pBitmap->Lock(prcSource, bitmapLockFlags, &lock));
    DX::ThrowIfFailed(lock->GetStride(&pPlane->cbStride));
    DX::ThrowIfFailed(lock->GetDataPointer(&pPlane->cbBufferSize, &pPlane->pbBuffer));
    DX::ThrowIfFailed(lock->GetPixelFormat(&pPlane->Format));
    *ppBitmapLock = lock.Detach();
}

Trasformazione dei dati pixel YCbCr

La trasformazione dei dati YCbCr è quasi identica alla decodifica, poiché entrambi coinvolgono IWICPlanarBitmapSourceTransform. L'unica differenza è l'oggetto WIC da cui hai ottenuto l'interfaccia. Lo strumento di ridimensionamento, la rotazione capovolgimento e la trasformazione del colore di Windows supportano tutti l'accesso YCbCr .

Concatenamento delle trasformazioni

WIC supporta la nozione di concatenamento di più trasformazioni. Ad esempio, è possibile creare la pipeline WIC seguente:

diagramma di una pipeline wic che inizia con un decodificatore jpeg.

È quindi possibile chiamare QueryInterface in IWICColorTransform per ottenere IWICPlanarBitmapSourceTransform. La trasformazione del colore può comunicare con le trasformazioni precedenti e può esporre le funzionalità di aggregazione di ogni fase della pipeline. WIC garantisce che i dati YCbCr vengano mantenuti tramite l'intero processo. Questo concatenamento funziona solo quando si usano componenti che supportano l'accesso YCbCr .

Ottimizzazioni codec JPEG

Analogamente all'implementazione della decodifica dei frame JPEG di IWICBitmapSourceTransform, l'implementazione del decodifica frame JPEG di IWICPlanarBitmapSourceTransform supporta il ridimensionamento e la rotazione del dominio JPEG nativi. È possibile richiedere una potenza di due ridimensionamento o una rotazione direttamente dal decodificatore JPEG. Ciò comporta in genere una qualità e prestazioni superiori rispetto all'uso delle trasformazioni discrete.

Inoltre, quando concatena una o più trasformazioni WIC dopo il decodificatore JPEG, può sfruttare la scalabilità e la rotazione JPEG native per soddisfare l'operazione richiesta di aggregazione.

Conversioni di formato

Usare IWICPlanarFormatConverter per convertire i dati pixel YCbCr planari in un formato pixel interleaved, ad esempio GUID_WICPixelFormat32bppPBGRA. WiC in Windows 8.1 non offre la possibilità di eseguire la conversione in un formato pixel YCb Cr planare.

Codifica dei dati pixel YCbCr

Usare IWICPlanarBitmapFrameEncode per codificare i dati pixel YCbCr nel codificatore JPEG. La codifica dei dati YCbCrIWICPlanarBitmapFrameEncode è simile ma non identica alla codifica dei dati interleaved usando IWICBitmapFrameEncode. L'interfaccia planare espone solo la possibilità di scrivere dati dell'immagine del frame planare ed è consigliabile continuare a usare l'interfaccia di codifica dei fotogrammi per impostare metadati o un'anteprima e per eseguire il commit alla fine dell'operazione.

Per il caso tipico, è necessario seguire questa procedura:

  1. Ottenere IWICBitmapFrameEncode come di consueto . Se si vuole configurare il sottocampionamento chroma, impostare l'opzione codificatore JpegYCrCbSubsampling durante la creazione del frame.
  2. Se è necessario impostare metadati o un'anteprima, eseguire questa operazione usando IWICBitmapFrameEncode come di consueto .
  3. QueryInterface per IWICPlanarBitmapFrameEncode.
  4. Impostare i dati pixel YCbCusandoIWICPlanarBitmapFrameEncode::WriteSource o IWICPlanarBitmapFrameEncode::WritePixels. A differenza delle controparti IWICBitmapFrameEncode , questi metodi vengono forniti con una matrice di IWICBitmapSource o WICBitmapPlane che contengono i piani pixel YCbCr .
  5. Al termine, chiamare IWICBitmapFrameEncode::Commit.

Decodifica dei dati pixel YCbCR in Windows 10

A partire da Windows 10 build 1507, Direct2D fornisce ID2D1ImageSourceFromWic, un modo più semplice per decodificare i JPEG in Direct2D sfruttando le ottimizzazioni YCbCr. ID2D1ImageSourceFromWic esegue automaticamente tutti i controlli di funzionalità YCbCr necessari; usa il percorso di codice ottimizzato quando possibile e usa un fallback in caso contrario. Abilita anche nuove ottimizzazioni, ad esempio la memorizzazione nella cache solo delle sottoregioni dell'immagine necessarie alla volta.

Per altre informazioni sull'uso di ID2D1ImageSourceFromWic, vedere l'esempio Direct2D Photo Adjustment SDK.