SierraTiger
SierraTiger

Reputation: 51

How to convert SoftwareBitmap from Bgra8 to JPEG in Windows UWP

How to convert SoftwareBitmap from Bgra8 to JPEG in Windows UWP. GetPreviewFrameAsync function is used to get videoFrame data in Bgra8. What is going wrong in the following code?. I am getting jpeg size 0.

    auto previewProperties = static_cast<MediaProperties::VideoEncodingProperties^>
        (mediaCapture->VideoDeviceController->GetMediaStreamProperties(Capture::MediaStreamType::VideoPreview));
    unsigned int videoFrameWidth = previewProperties->Width;
    unsigned int videoFrameHeight = previewProperties->Height;
    FN_TRACE("%s videoFrameWidth %d videoFrameHeight %d\n",
        __func__, videoFrameWidth, videoFrameHeight);

    // Create the video frame to request a SoftwareBitmap preview frame
    auto videoFrame = ref new VideoFrame(BitmapPixelFormat::Bgra8, videoFrameWidth, videoFrameHeight);

    // Capture the preview frames
    return create_task(mediaCapture->GetPreviewFrameAsync(videoFrame))
        .then([this](VideoFrame^ currentFrame)
    {
        // Collect the resulting frame
        auto previewFrame = currentFrame->SoftwareBitmap;

        auto inputStream = ref new Streams::InMemoryRandomAccessStream();

        create_task(BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, inputStream))
            .then([this, previewFrame, inputStream](BitmapEncoder^ encoder)
        {
            encoder->SetSoftwareBitmap(previewFrame);
            encoder->FlushAsync();

            FN_TRACE("jpeg size %d\n", inputStream->Size);
            Streams::Buffer^ data = ref new Streams::Buffer(inputStream->Size);
            create_task(inputStream->ReadAsync(data, (unsigned int)inputStream->Size, InputStreamOptions::None));
        });
});

Upvotes: 1

Views: 1052

Answers (1)

Jay Zuo
Jay Zuo

Reputation: 15758

Bitmap​Encoder.FlushAsync() method is a asynchronous method. We should consume it like the following:

// Capture the preview frames
return create_task(mediaCapture->GetPreviewFrameAsync(videoFrame))
    .then([this](VideoFrame^ currentFrame)
{
    // Collect the resulting frame
    auto previewFrame = currentFrame->SoftwareBitmap;

    auto inputStream = ref new Streams::InMemoryRandomAccessStream();

    return create_task(BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, inputStream))
        .then([this, previewFrame](BitmapEncoder^ encoder)
    {
        encoder->SetSoftwareBitmap(previewFrame);
        return encoder->FlushAsync();
    }).then([this, inputStream]()
    {

        FN_TRACE("jpeg size %d\n", inputStream->Size);
        //TODO
    });
});

Then you should be able to get the right size. For more info, please see Asynchronous programming in C++.

Upvotes: 1

Related Questions