Dela via


Stöd för JPEG YCbCr

Från och med Windows 8.1 har Windows Imaging Component (WIC) JPEG codec stöd för läsning och skrivning av bilddata i sitt ursprungliga YC-bCr formulär. Stöd för WIC YCbCr kan användas tillsammans med Direct2D- för att återge YCbCr pixeldata med bildeffekt. Dessutom kan WIC JPEG-codec använda YCbCr pixeldata som produceras av vissa kameradrivrutiner via Media Foundation.

YCbCr pixeldata förbrukar betydligt mindre minne än standardformat för BGRA-bildpunkter. Genom att komma åt YC-bCr data kan du dessutom avlasta vissa steg i JPEG-avkodningspipelinen till Direct2D som är GPU-accelererad. Genom att använda YCbCrkan appen minska JPEG-minnesförbrukningen och inläsningstiderna för samma storlek och kvalitet. Eller så kan din app använda fler JPEG-bilder med högre upplösning utan att drabbas av prestandapåföljder.

Det här avsnittet beskriver hur YCbCr data fungerar och hur du använder dem i WIC och Direct2D.

Om JPEG YCbCr Data

I det här avsnittet beskrivs några viktiga begrepp som behövs för att förstå hur YCbCr stöd i WIC fungerar och dess viktigaste fördelar.

YCbCr färgmodell

WIC i Windows 8 och tidigare har stöd för fyra olika färgmodeller, varav den vanligaste är RGB/BGR. Den här färgmodellen definierar färgdata med hjälp av röda, gröna och blå komponenter. en fjärde alfakomponent kan också användas.

Här är en bild som delas upp i dess röda, gröna och blå komponenter.

en bild delas upp i dess röda, gröna och blå komponenter.

YCbCr är en alternativ färgmodell som definierar färgdata med hjälp av en luminanskomponent (Y) och två krominancekomponenter (Cb och Cr). Det används ofta i scenarier med digital avbildning och video. Termen YCbCr används ofta omväxlande med YUV, även om de två är tekniskt distinkta.

Det finns flera varianter av YCbCr som skiljer sig åt i färgrymd och definitioner för dynamiskt intervall – WIC stöder specifikt JPEG JFIF YCbCr data. Mer information finns i JPEG-ITU-T81-specifikationen.

Här är en bild som delas upp i komponenterna Y, Cboch Cr.

en bild som delas upp i dess komponenter y, cb och cr.

Planar kontra mellanlagrade minneslayouter

I det här avsnittet beskrivs vissa skillnader mellan att komma åt och lagra RGB-pixeldata i minnet jämfört med YC-bCr data.

RGB-pixeldata lagras vanligtvis med hjälp av en interfolierad minneslayout. Det innebär att data för en enskild färgkomponent interfolieras mellan bildpunkter och att varje pixel lagras sammanhängande i minnet.

Här är en bild som visar RGBA-pixeldata som lagras i en interfolierad minneslayout.

en bild som visar rgba pixeldata som lagras i en interfolierad minneslayout.

YC-bCr data lagras vanligtvis med hjälp av en planarminneslayout. Det innebär att varje färgkomponent lagras separat i sitt eget sammanhängande plan, för totalt tre plan. I en annan gemensam konfiguration är komponenterna Cb och Cr interleaved och lagrade tillsammans, medan Y-komponenten förblir i sitt eget plan, för totalt två plan.

Här är en bild som visar planar Y och interleaved CbCr pixeldata, en vanlig YC-bCr minneslayout.

en bild som visar planar y och interleaved cbcr pixel data, en vanlig ycbcr minneslayout.

I både WIC och Direct2D behandlas varje färgplan som ett eget distinkt objekt (antingen ett IWICBitmapSource- eller ID2D1Bitmap), och tillsammans bildar dessa plan bakgrundsdata för en YC-bCr bild.

Även om WIC stöder åtkomst till YC-bCr data i både 2- och 3-plankonfigurationerna, stöder Direct2D endast den tidigare (Y och CbCr). När du använder WIC och Direct2D tillsammans bör du därför alltid använda konfigurationen 2-plan YCbCr.

Chroma-delsampling

YC-bCr färgmodell passar bra för scenarier med digital avbildning eftersom den kan dra nytta av vissa aspekter av det mänskliga visuella systemet. I synnerhet är människor mer känsliga för förändringar i luminansen (ljusstyrkan) i en bild och mindre känsliga för krominans (färg). Genom att dela upp färgdata i separata komponenter för luminans och krominans kan vi selektivt komprimera bara krominanskomponenterna för att uppnå utrymmesbesparingar med minimal kvalitetsförlust.

En teknik för att göra detta kallas chroma subsampling. Planen Cb och Cr är delskalade (nedskalade) i en eller båda av de vågräta och lodräta dimensionerna. Av historiska skäl kallas varje chroma-undersamplingsläge ofta för att använda ett J:a:b-förhållande i tre delar.

Undersamplingsläge Vågrät nedskala Lodrät nedskalning Bitar 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

 

* Innehåller Y-data.

Om du använder YCbCr för att lagra okomprimerade bilddata kan du uppnå en minnesbesparing på 25% till 62,5% jämfört med 32 bitar per pixel RGBA-data, beroende på vilket kromaundersamplingsläge som används.

JPEG-användning av YCbCr

På hög nivå består JPEG-dekomprimeringspipelinen av följande steg:

  1. Utför entropi (t.ex. Huffman) dekomprimering
  2. Utföra dequantization
  3. Utföra invertera diskret cosinintransformering
  4. Utför kromuppsampling på CbCr data
  5. Konvertera YC-bCr data till RGBA (om det behövs)

Genom att låta JPEG-codec producera YC-bCr data kan vi undvika de två sista stegen i avkodningsprocessen eller skjuta upp dem till GPU:n. Förutom de minnesbesparingar som anges i föregående avsnitt minskar detta avsevärt den totala tid som krävs för att avkoda bilden. Samma besparingar gäller vid kodning av YC-bCr data.

Använda JPEG YCbCr Data

I det här avsnittet beskrivs hur du använder WIC och Direct2D för att arbeta på YCbCr data.

Om du vill se vägledningen från det här dokumentet som används i praktiken kan du läsa JPEG YCbCr-optimeringar i Direct2D- och WIC-exempel som visar alla steg som krävs för att avkoda och återge YC-bCr innehåll i en Direct2D-app.

Använda YCbCr JPEG-bilder

De allra flesta JPEG-bilder lagras som YCbCr. Vissa JPEG:er innehåller CMYK- eller gråskaledata och använder inte YCbCr. Det innebär att du vanligtvis, men inte alltid, direkt kan använda befintligt JPEG-innehåll utan några ändringar.

WIC och Direct2D stöder inte alla möjliga YC-bCr konfiguration och YCbCr stöd i Direct2D är beroende av den underliggande grafikmaskinvaran och drivrutinen. På grund av detta måste en allmän bildpipeline vara robust för bilder som inte använder YCbCr (inklusive andra vanliga bildformat som PNG eller BMP) eller i fall där YCbCr stöd inte är tillgängligt. Vi rekommenderar att du behåller din befintliga BGRA-baserade avbildningspipeline och aktiverar YCbCr som en prestandaoptimering när det är tillgängligt.

API:er för Windows Imaging-komponent

WIC i Windows 8.1 lägger till tre nya gränssnitt för att ge åtkomst till JPEG YC-bCr data.

IWICPlanarBitmapSourceTransform

IWICPlanarBitmapSourceTransform liknar IWICBitmapSourceTransform, förutom att den producerar pixlar i en planar-konfiguration, inklusive YCbCr data. Du kan hämta det här gränssnittet genom att anropa QueryInterface för en implementering av IWICBitmapSource- som stöder planar-åtkomst. Detta inkluderar JPEG-codec-implementeringen av IWICBitmapFrameDecode samt IWICBitmapScaler, IWICBitmapFlipRotatoroch IWICColorTransform.

IWICPlanarBitmapFrameEncode

IWICPlanarBitmapFrameEncode ger möjlighet att koda planar pixeldata, inklusive YCbCr data. Du kan hämta det här gränssnittet genom att anropa QueryInterface på JPEG-codec-implementeringen av IWICBitmapFrameEncode.

IWICPlanarFormatConverter

IWICPlanarFormatConverter tillåter IWICFormatConverter att använda planar pixeldata, inklusive YCbCr, och konvertera dem till ett interfolierat pixelformat. Det visar inte möjligheten att konvertera interfolierade pixeldata till ett planarformat. Du kan hämta det här gränssnittet genom att anropa QueryInterface på den Windows-implementering av IWICFormatConverter.

Direct2D-API:er

Direct2D i Windows 8.1 stöder YC-bCr planar pixeldata med nya YC-bCr bildeffekt . Den här effekten ger möjlighet att återge YC-bCr data. Effekten tar som indata två ID2D1Bitmap--gränssnitt: ett som innehåller planar Y-data i DXGI_FORMAT_R8_UNORM-format och ett som innehåller interleaved CbCr-data i DXGI_FORMAT_R8G8_UNORM-format. Du använder vanligtvis den här effekten i stället för ID2D1Bitmap- som skulle ha innehållit BGRA-pixeldata.

YC-bCr bildeffekt är avsedd att användas tillsammans med API:erna för WIC YCbCr som tillhandahåller YC-bCr data. Detta fungerar effektivt för att avlasta en del av avkodningsarbetet från processorn till GPU:n, där det kan bearbetas mycket snabbare och parallellt.

Avgöra om konfigurationen av YCbCr stöds

Som tidigare nämnts bör din app vara robust i fall där YCbCr support inte är tillgänglig. I det här avsnittet beskrivs de villkor som appen ska söka efter. Om någon av följande kontroller misslyckas bör appen återgå till en BGRA-baserad standardpipeline.

Stöder WIC-komponenten YCbCr dataåtkomst?

Endast Den JPEG-kod som tillhandahålls av Windows och vissa WIC-transformeringar stöder YCbCr dataåtkomst. En fullständig lista finns i avsnittet API:er för Windows Imaging-komponenten.

Om du vill hämta ett av planar YC-bCr-gränssnitten anropar du QueryInterface på det ursprungliga gränssnittet. Detta misslyckas om komponenten inte stöder YC-bCr dataåtkomst.

Stöds den begärda WIC-transformeringen för YCbCr?

När du har hämtat en IWICPlanarBitmapSourceTransformbör du först anropa DoesSupportTransform. Den här metoden tar som indataparametrar den fullständiga uppsättningen transformeringar som du vill tillämpa på planar YC-bCr data och returnerar ett booleskt stöd, samt de närmaste dimensionerna till den begärda storleken som kan returneras. Du bör kontrollera alla tre värdena innan du kommer åt pixeldata med IWICPlanarBitmapSourceTransform::CopyPixels.

Det här mönstret liknar hur IWICBitmapSourceTransform används.

Stöder grafikdrivrutinen de funktioner som krävs för att använda YCbCr med Direct2D?

Den här kontrollen är bara nödvändig om du använder Direct2D YCbCr effekt för att återge YC-bCr innehåll. Direct2D lagrar YC-bCr data med formaten DXGI_FORMAT_R8_UNORM och DXGI_FORMAT_R8G8_UNORM pixel, som inte är tillgängliga från alla grafikdrivrutiner.

Innan du använder YC-bCr bildeffekt bör du anropa ID2D1DeviceContext::IsDxgiFormatSupported för att säkerställa att båda formaten stöds av drivrutinen.

Exempelkod

Nedan visas ett kodexempel som visar de rekommenderade kontrollerna. Det här exemplet togs från JPEG YCbCr-optimeringar i Direct2D- och WIC-exempel.

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));
}

Avkodning av YCbCr Pixel Data

Om du vill hämta YC-bCr pixeldata bör du anropa IWICPlanarBitmapSourceTransform::CopyPixels. Den här metoden kopierar pixeldata till en matris med ifyllda WICBitmapPlane- strukturer, en för varje dataplan som du vill använda (till exempel Y och CbCr). En WICBitmapPlane- innehåller information om pixeldata och pekar på minnesbufferten som tar emot data.

Om du vill använda YC-bCr pixeldata med andra WIC-API:er bör du skapa en korrekt konfigurerad IWICBitmap-anropa Lås för att hämta den underliggande minnesbufferten. och associera bufferten med WICBitmapPlane som används för att ta emot YC-bCr pixeldata. Du kan sedan använda IWICBitmap- normalt.

Om du vill återge YC-bCr data i Direct2D bör du skapa en ID2D1Bitmap- från varje IWICBitmap- och använda dem som källa för YCbCr bildeffekt. Med WIC kan du begära flera planar-konfigurationer. När du samverkar med Direct2D bör du begära två plan, ett med hjälp av GUID_WICPixelFormat8bppY och det andra med hjälp av GUID_WICPixelFormat16bppCbCr, eftersom detta är den konfiguration som förväntas av Direct2D.

Kodexempel

Nedan visas ett kodexempel som visar stegen för att avkoda och återge YCbCr data i Direct2D. Det här exemplet togs från JPEG YCbCr-optimeringar i Direct2D- och WIC-exempel.

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();
}

Transformera YCbCr Pixel Data

Transformering av YC-bCr data är nästan identisk med avkodning, eftersom båda omfattar IWICPlanarBitmapSourceTransform. Den enda skillnaden är vilket WIC-objekt du hämtade gränssnittet från. Windows-skalning, vändrottor och färgtransformering stöder alla YC-bCr åtkomst.

Sammanlänkning av transformeringar

WIC stöder begreppet sammanlänkning av flera transformeringar. Du kan till exempel skapa följande WIC-pipeline:

ett diagram över en wic-pipeline som börjar med en jpeg-avkodare.

Du kan sedan anropa QueryInterface på IWICColorTransform för att hämta IWICPlanarBitmapSourceTransform. Färgtransformeringen kan kommunicera med föregående transformeringar och kan exponera aggregeringsfunktionerna i varje steg i pipelinen. WIC säkerställer att YC-bCr data bevaras genom hela processen. Den här länkningen fungerar bara när du använder komponenter som stöder YC-bCr åtkomst.

JPEG Codec-optimeringar

På samma sätt som implementeringen av JPEG-ramavkodning av IWICBitmapSourceTransformstöder JPEG-ramavkodningsimplementeringen av IWICPlanarBitmapSourceTransform inbyggt skalning och rotation av JPEG DCT-domäner. Du kan begära en effekt av två nedskalning eller en rotation direkt från JPEG-avkodaren. Detta resulterar vanligtvis i högre kvalitet och prestanda än att använda diskreta transformeringar.

När du kedjar en eller flera WIC-transformeringar efter JPEG-avkodaren kan den dessutom använda inbyggd JPEG-skalning och rotation för att uppfylla den begärda åtgärden.

Formatera konverteringar

Använd IWICPlanarFormatConverter för att konvertera planar YCbCr pixeldata till ett interfolierat pixelformat som GUID_WICPixelFormat32bppPBGRA. WIC i Windows 8.1 ger inte möjlighet att konvertera till ett planar YC-bCr pixelformat.

Kodning av YCbCr Pixel Data

Använd IWICPlanarBitmapFrameEncode för att koda YC-bCr pixeldata till JPEG-kodaren. Kodning av YCbCr data IWICPlanarBitmapFrameEncode liknar men är inte identisk med kodning av interleaved-data med hjälp av IWICBitmapFrameEncode. Planar-gränssnittet visar bara möjligheten att skriva bilddata för planar-bild, och du bör fortsätta att använda ramkodningsgränssnittet för att ange metadata eller en miniatyrbild och checka in i slutet av åtgärden.

I vanliga fall bör du följa dessa steg:

  1. Hämta IWICBitmapFrameEncode som vanligt. Om du vill konfigurera chroma-undersampling anger du alternativet JpegYCrCbSubsampling kodare när du skapar ramen.
  2. Om du behöver ange metadata eller en miniatyrbild gör du detta med hjälp av IWICBitmapFrameEncode som vanligt.
  3. QueryInterface för IWICPlanarBitmapFrameEncode.
  4. Ange YC-bCr pixeldata med hjälp av IWICPlanarBitmapFrameEncode::WriteSource eller IWICPlanarBitmapFrameEncode::WritePixels. Till skillnad från deras IWICBitmapFrameEncode- motsvarigheter tillhandahåller du dessa metoder med en matris med IWICBitmapSource eller WICBitmapPlane som innehåller YC-bCr pixelplan.
  5. När du är klar anropar du IWICBitmapFrameEncode::Commit.

Avkodning av YC-bCr pixeldata i Windows 10

Från och med Windows 10 build 1507 tillhandahåller Direct2D ID2D1ImageSourceFromWic, ett enklare sätt att avkoda JPEG:er till Direct2D samtidigt som YC användsbCr optimeringar. ID2D1ImageSourceFromWic utför automatiskt alla nödvändiga YC-bCr kapacitetskontroller åt dig. den använder den optimerade kodvägen när det är möjligt och använder en återställning annars. Det möjliggör också nya optimeringar, till exempel endast cachelagring av underregioner av avbildningen som behövs i taget.

Mer information om hur du använder ID2D1ImageSourceFromWicfinns i Direct2D Photo Adjustment SDK exempel.