如何从UWP中的IBuffer或字节数组创建IDirect3DSurface [英] How to create a IDirect3DSurface from an IBuffer or byte array in UWP

查看:235
本文介绍了如何从UWP中的IBuffer或字节数组创建IDirect3DSurface的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用UWP中的几个RenderTargetBitmap创建一个视频.我通过使用MediaClips来做到这一点. 从RenderTargetBitmap我可以得到IBuffer或像素的字节数组. 要创建MediaClip,我需要一个图像文件或一个IDirect3DSurface. 仅创建图像就创建一个剪辑非常昂贵,因此我想到了使用IDirect3DSurface的方法. 我怎样才能做到这一点? 我已经尝试过了:

I want to create a video from a few RenderTargetBitmaps in UWP. I am doing that by using MediaClips. From RenderTargetBitmap i can get an IBuffer or byte array of pixels. To create a MediaClip I need either an image file or an IDirect3DSurface. Creating an image just to create a clip is very expensive, so I thought of using IDirect3DSurface. How can I do this? I have tried this:

        RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
        await renderTargetBitmap.RenderAsync(RenderedGrid, 100, 100);

        IBuffer pixels = await renderTargetBitmap.GetPixelsAsync();
        var values = Enum.GetValues(typeof(DirectXPixelFormat));
        CanvasBitmap bitmap=null;

        foreach (DirectXPixelFormat format in values)
        {
            try
            {
                videoClip = new MediaComposition();
                bitmap = CanvasBitmap.CreateFromBytes(myWidget.Device, pixels, renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight, format);
                StorageFile video2 = await storageFolder.CreateFileAsync("video2" + ".mp4", CreationCollisionOption.ReplaceExisting);
                MediaClip d = MediaClip.CreateFromSurface(bitmap, DateTime.Now - previousFrame+new TimeSpan(100));
                videoClip.Clips.Add(d);
                await videoClip.RenderToFileAsync(video2);
                break;
            }
            catch(Exception e)
            {

            }
        }

我尝试了DirectXPixelFormat中的所有格式,但是没有任何效果.

I try all the formats in DirectXPixelFormat but none works.

我有一个名为myWidgetCanvasControl,为空.

I have a CanvasControl named myWidget that is empty.

我从Ibuffer创建一个CanvasBitmap(CanvasBitmap实现IDirect3DSurface)

CanvasBitmap

Add it to MediaComposition.

然后我尝试渲染为视频文件.当我尝试将其保存到文件时会引发错误

Then I try to render to video file.When i try to save to a file it throws an error

System.Runtime.InteropServices.COMException流未处于状态 处理请求.

System.Runtime.InteropServices.COMException Stream is not in a state to handle the request.

我弄清楚了问题出在哪里,但不知道为什么,也不知道如何解决.

I figured out where the problem is, but not why and not how to fix it.

            await videoClip.SaveAsync(video2);
            videoClip= await MediaComposition.LoadAsync(video2);
            var x=await videoClip.RenderToFileAsync(video2);

现在,使用这三行代码我可以保存视频,但是仅使用第三行它会引发上面的错误.我无法理解.为什么保存和加载可以解决问题?

Now with these three lines i can save the video, but using only the third line it throws the error above. I cannot make sense of it. Why does saving and loading fix the problem??

推荐答案

最可能的原因是,CanvasBitmap具有一个基础IDirce3DSurface对象以及诸如byte[]之类的图像数据或其他东西,尽管我不是对此肯定.

Most probable reason is that, CanvasBitmap has an underlying IDirce3DSurface object as well as image data like byte[] or something else , though I am not sure about this.

如果是这样,则从byte[]IBuffer创建CanvasBitmap不会影响基础的IDirect3DSurface,将仅构造图像部分.您可以看到,通过将该映像保存在磁盘上,它没有任何错误.

If that's true, then creating a CanvasBitmap from byte[] or IBuffer won't effect the underlying IDirect3DSurface, the image part will be constructed only. You can see that by saving that image on the disk, it gives no error.

但是如果您要跳过将数据保存到磁盘上的话,我认为有一种解决方法:

如果您执行屏幕外绘图,则可以构造基础IDirect3DSurface.到 CanvasRenderTarget .

You can contruct the underlying IDirect3DSurface if you do Offscreen Drawing to a CanvasRenderTarget.

因此,您可以使用CanvasBitmap构造一个CanvasRenderTarget,然后使用该CanvasRenderTarget构造一个MediaClip:

So, you can use the CanvasBitmap to construct a CanvasRenderTarget and then use that CanvasRenderTarget to contruct a MediaClip:

CanvasRenderTarget rendertarget;
using (CanvasBitmap canvas = CanvasBitmap.CreateFromBytes(CanvasDevice.GetSharedDevice(), pixels, renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight, format))
{
     rendertarget = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), canvas.SizeInPixels.Width, canvas.SizeInPixels.Height, 96);
     using (CanvasDrawingSession ds = rendertarget.CreateDrawingSession())
     {
         ds.Clear(Colors.Black);
         ds.DrawImage(canvas);
     }
}
MediaClip d = MediaClip.CreateFromSurface(renderTarget, TimeSpan.FromMilliseconds(80));
mc.Clips.Add(m);

这篇关于如何从UWP中的IBuffer或字节数组创建IDirect3DSurface的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆