繁体   English   中英

C#(MediaFrameReader API)SoftwareBitmap不显示

[英]C# (MediaFrameReader API) SoftwareBitmap doesn't show

我按照Microsoft的说明实施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();
            }
        }
    }

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

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

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

另外,请调试您的代码以查看taskRunning是否为false ,以确保您的代码确实会运行到设置图像源步骤中。

因此,这就是我更改代码的方式:

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

在保存SaveSoftwareBitmapToJpg() ,位图未正确转换,必须为Rgba8或Rgba16才能打印为JPEG,因此与ShowSoftwareBitmap()相同的转换将不起作用。 使用此代替:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM