Michael Chourdakis
Michael Chourdakis

Reputation: 11178

ID2D1Bitmap to Wic with Alpha but not PNG

I 'm saving the bitmap of a Direct2D Device Context. My goal is to keep 32-bit (RGB with alpha) but not have a PNG, I 'd rather have a 32-bit bitmap.

I'm using this function:

HRESULT SaveBitmapToStream(
    _In_ CComPtr<ID2D1Bitmap1> d2dBitmap,
    _In_ CComPtr<IWICImagingFactory2> wicFactory2,
    _In_ CComPtr<ID2D1DeviceContext> d2dContext,
    _In_ REFGUID wicFormat,
    _In_ IStream* stream
)
{
    // Create and initialize WIC Bitmap Encoder.
    CComPtr<IWICBitmapEncoder> wicBitmapEncoder;
    auto hr =
        wicFactory2->CreateEncoder(
            wicFormat,
            nullptr,    // No preferred codec vendor.
            &wicBitmapEncoder
        );

    hr =
        wicBitmapEncoder->Initialize(
            stream,
            WICBitmapEncoderNoCache
        );

// Create and initialize WIC Frame Encoder.
    CComPtr<IWICBitmapFrameEncode> wicFrameEncode;
    hr =
        wicBitmapEncoder->CreateNewFrame(
            &wicFrameEncode,
            nullptr     // No encoder options.
        );

    if (FAILED(hr))
        return hr;
    hr = 
        wicFrameEncode->Initialize(nullptr);
    if (FAILED(hr))
        return hr;

// Retrieve D2D Device.
    CComPtr<ID2D1Device> d2dDevice;
    if (!d2dContext)
        return E_FAIL;
    d2dContext->GetDevice(&d2dDevice);

    // Create IWICImageEncoder.
    CComPtr<IWICImageEncoder> imageEncoder;
    hr = 
        wicFactory2->CreateImageEncoder(
            d2dDevice,
            &imageEncoder
        );
    if (FAILED(hr))
        return hr;

    hr =        
        imageEncoder->WriteFrame(
            d2dBitmap,  wicFrameEncode,
            nullptr     // Use default WICImageParameter options.
        );
    if (FAILED(hr))
        return hr;

    hr = wicFrameEncode->Commit();

    if (FAILED(hr))
        return hr;

    hr = wicBitmapEncoder->Commit();

    if (FAILED(hr))
        return hr;
// Flush all memory buffers to the next-level storage object.
    hr =
        stream->Commit(STGC_DEFAULT);

    return hr;

}

The problem is that, when I pass GUID_ContainerFormatBmp, the resulting bitmap does not have alpha. I must put GUID_ContainerFormatPng, but this will compress my image which I do not want, this is for video rendering and I don't want any compression.

Is there a way to get a capture of the Direct2D Context in a 32-bit format but not a compressed one?

Upvotes: 0

Views: 441

Answers (1)

Simon Mourier
Simon Mourier

Reputation: 139256

The native BMP codec supports one property, EnableV5Header32bppBGRA of type VT_BOOL:

Specifies whether to allow encoding data in the GUID_WICPixelFormat32bppBGRA pixel format. If this option is set to VARIANT_TRUE, the BMP will be written out with a BITMAPV5HEADER header. The default value is VARIANT_FALSE.

Note for 16-bit and 32-bit Windows BMP files, the BMP codec ignores any alpha channel, as many legacy image files contain invalid data in this extra channel. Starting with Windows 8, 32-bit Windows BMP files written using the BITMAPV5HEADER with valid alpha channel content are read as WICPixelFormat32bppBGRA

Upvotes: 1

Related Questions