C#(MediaFrameReader API)SoftwareBitmap没有显示

时间:2018-03-20 08:39:50

标签: c# bitmap uwp

我跟着Microsoft's instructions实施了MediaFrameReader API,以便处理相机捕获的视频。问题是我不知道为什么位图不会出现在XAML中,我也无法将其保存到jpeg(位图不为空)。我确实将位图转换为XAML的正确格式:

这是我在XAML控件中显示框架的代码(无错误):

public void ShowSoftwareBitmap(SoftwareBitmap softwareBitmap, SoftwareBitmap backBuffer, Image imageElement, bool taskRunning)
    {
        try
        {
            //check if softwareBitmap is in proper format (Bgra8 and premultiplied alpha) to display to XAML Image control 
            if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 ||
                softwareBitmap.BitmapAlphaMode != BitmapAlphaMode.Premultiplied)
            {
                softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
            }

            if(softwareBitmap != null)
            {
                softwareBitmap = Interlocked.Exchange(ref backBuffer, softwareBitmap);
                softwareBitmap?.Dispose();
                var task = imageElement.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                async () =>
                {
                    if (taskRunning)
                    {
                        return;
                    }
                    taskRunning = true;

                    SoftwareBitmap latestBitmap;
                    while ((latestBitmap = Interlocked.Exchange(ref backBuffer, null)) != null)
                    {
                        SaveSoftwareBitmapToJpg(latestBitmap, 2);
                        var imageSource = (SoftwareBitmapSource)imageElement.Source;
                        await imageSource.SetBitmapAsync(latestBitmap);
                        latestBitmap.Dispose();
                    }
                    taskRunning = false;
                }
                );
            }

        }
        catch (NullReferenceException e)
        {
            Debug.WriteLine("Backbuffer is empty." + e.Message);
        }

    }

这是我的代码,将其保存为jpeg(错误不支持的位图格式):

public async void SaveSoftwareBitmapToJpg(SoftwareBitmap softwareBitmap, int _frameIndex)
    {
        StorageFolder captureFolder = await FileAccess();
        StorageFile outputFile = await captureFolder.CreateFileAsync($"capture{_frameIndex}.jpg", CreationCollisionOption.FailIfExists);
        using (IRandomAccessStream stream = await outputFile.OpenAsync(FileAccessMode.ReadWrite)) 
        {
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
            encoder.SetSoftwareBitmap(softwareBitmap);
            encoder.BitmapTransform.ScaledHeight = 300;
            encoder.BitmapTransform.ScaledWidth = 300;
            encoder.IsThumbnailGenerated = true;
            try
            {
                await encoder.FlushAsync();
            }
            catch (Exception e)
            {
                switch (e.HResult)
                {
                    case unchecked((int)0x88982F81): //WINCODEC_ERR_UNSUPPORTEDOPERATION
                                                     // If the encoder does not support writing a thumbnail, then try again
                                                     // but disable thumbnail generation.
                        encoder.IsThumbnailGenerated = false;
                        break;
                    default:
                        throw e;
                }
            }
            //catch error generating thumbnail
            if (encoder.IsThumbnailGenerated == false)
            {
                await encoder.FlushAsync();
            }
        }
    }

2 个答案:

答案 0 :(得分:0)

我使用您的代码段进行了测试,如果您使用正确的SoftwareBitmap对象正确调用上述方法,则上述方法可以正常运行。仅举例:

 <Image x:Name="imgshow" ></Image>
 imgshow.Source = new SoftwareBitmapSource();
 SoftwareBitmap _backBuffer = new SoftwareBitmap(BitmapPixelFormat.Bgra8, 300, 400);
 ShowSoftwareBitmap(softwareBitmap, _backBuffer, imgshow, false);

因此,上述方法可能不会发生此问题。这可以帮助您缩小问题范围,在获取SoftwareBitmap对象时可以检查是否有问题。我看到你可以复制ProcessFrame方法中的代码,该方法位于官方样本的FrameRenderer类中。官方示例通过转换SoftwareBitmap获得VideoMediaFrame,在转换时检查是否有任何错误。

另外,请调试您的代码,看看您的代码在设置图片源步骤时是否taskRunning false

答案 1 :(得分:0)

所以这就是我改变代码的方式:

ShowSoftwareBitmap()中,我在其他方法中使用了相同的布尔taskRunning,因此在运行时疯狂地更改了它。只需创建另一个布尔值来解决问题。

在保存SaveSoftwareBitmapToJpg()中,位图未正确转换,必须将Rgba8或Rgba16打印为JPEG,因此用于ShowSoftwareBitmap()的相同转换无效。请改用:

try
{
    if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Rgba16)
       {
          result = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Rgba16);
       }
    else
       {
          result = SoftwareBitmap.Copy(softwareBitmap);
       }
}