【问题标题】:How does one use a memory stream instead of files when rendering Direct2D images via SharpDX?通过 SharpDX 渲染 Direct2D 图像时,如何使用内存流而不是文件?
【发布时间】:2012-02-27 10:14:04
【问题描述】:

设置

考虑使用 SharpDX(Direct* 库的托管包装器)的给定临时程序来呈现位图并将其保存为 PNG:

namespace ConsoleApplication5
{
    using System;
    using System.Diagnostics;
    using System.IO;
    using SharpDX;
    using SharpDX.Direct2D1;
    using SharpDX.DirectWrite;
    using SharpDX.DXGI;
    using SharpDX.IO;
    using SharpDX.WIC;
    using AlphaMode = SharpDX.Direct2D1.AlphaMode;
    using Bitmap = SharpDX.WIC.Bitmap;
    using D2DPixelFormat = SharpDX.Direct2D1.PixelFormat;
    using WicPixelFormat = SharpDX.WIC.PixelFormat;

    class Program
    {
        static void Main(string[] args)
        {
            var width = 400;
            var height = 100;
            var pixelFormat = WicPixelFormat.Format32bppBGR;

            var wicFactory = new ImagingFactory();
            var dddFactory = new SharpDX.Direct2D1.Factory();
            var dwFactory = new SharpDX.DirectWrite.Factory();

            var wicBitmap = new Bitmap(
                wicFactory,
                width,
                height,
                pixelFormat,
                BitmapCreateCacheOption.CacheOnLoad);

            var renderTargetProperties = new RenderTargetProperties(
                RenderTargetType.Default,
                new D2DPixelFormat(Format.Unknown, AlphaMode.Unknown),
                0,
                0,
                RenderTargetUsage.None,
                FeatureLevel.Level_DEFAULT);
            var renderTarget = new WicRenderTarget(
                dddFactory,
                wicBitmap,
                renderTargetProperties)
            {
                TextAntialiasMode = TextAntialiasMode.Cleartype
            };

            renderTarget.BeginDraw();

            var textFormat = new TextFormat(dwFactory, "Consolas", 48) 
            {
                TextAlignment = TextAlignment.Center, 
                ParagraphAlignment = ParagraphAlignment.Center
            };
            var textBrush = new SolidColorBrush(
                renderTarget,
                Colors.Blue);

            renderTarget.Clear(Colors.White);
            renderTarget.DrawText(
                "Hi, mom!",
                textFormat,
                new RectangleF(0, 0, width, height),
                textBrush);

            renderTarget.EndDraw();

            var stream = new WICStream(
                wicFactory,
                "test.png",
                NativeFileAccess.Write);

            var encoder = new PngBitmapEncoder(wicFactory);
            encoder.Initialize(stream);

            var frameEncoder = new BitmapFrameEncode(encoder);
            frameEncoder.Initialize();
            frameEncoder.SetSize(width, height);
            frameEncoder.PixelFormat = WicPixelFormat.FormatDontCare;
            frameEncoder.WriteSource(wicBitmap);
            frameEncoder.Commit();

            encoder.Commit();

            frameEncoder.Dispose();
            encoder.Dispose();
            stream.Dispose();

            Process.Start(Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "test.png")));
        }
    }
}

运行此程序会在程序的工作目录中为您提供一个“test.png”文件,其中包含以下精美图像:

问题

太棒了,我刚刚在 ASP.NET 应用程序的上下文中使用 Direct2D 而不是 GDI+ which is supposedly more supported 渲染了一个图像。另外,Direct2D 是新的热点。

假设我想编写一个函数来渲染这样的图像并将 PNG 作为 Streambyte[] 数组返回,在内存中执行整个渲染和编码操作,而不是写入文件系统。这是为了响应 Web 请求;将其直接流式传输到浏览器而不通过文件系统是有意义的。

在 GDI+ 中,我可以很容易地用 MemoryStream 做到这一点,但我不知道如何在不知道缓冲区大小的情况下在 SharpDX 中使用 DataStream 来发挥我的优势:

        var bufferSize = 1024 * 3; // how do I know?
        var buffer = new DataStream(
            bufferSize,
            true,
            true);
        var stream = new WICStream(
            wicFactory,
            buffer);
  • 我是否必须 P/Invoke 到 CreateStreamOnHGlobal 并使用该 IntPtr 来构建我的 DataStream
  • 我是否缺少 DataStream 的一些过载?
  • 是否有一种简单的方法来预先计算保存编码的 PNG 图像所需的必要缓冲区?
  • 或者我是否应该跳过文件系统?

感谢您的帮助!

【问题讨论】:

    标签: asp.net direct2d sharpdx


    【解决方案1】:

    库的作者added this as a feature

    我认为代码为人们提供了一个有用的 Direct2D 示例,所以我将把这个问题留在身边。

    【讨论】:

      【解决方案2】:

      如果有人想在 asp.net 中这样做:

      var memStream = new MemoryStream();
      var wicStream = new WICStream(wicFactory, memStream);
      
      //Encode wic bitmap
      var encoder = new PngBitmapEncoder(wicFactory);
      encoder.Initialize(wicStream);
      var frameEncoder = new BitmapFrameEncode(encoder);
      frameEncoder.Initialize();
      frameEncoder.SetSize(width, height);
      var format = WicPixelFormat.FormatDontCare;
      frameEncoder.SetPixelFormat(ref format);
      frameEncoder.WriteSource(wicBitmap);
      frameEncoder.Commit();
      encoder.Commit();
      
      //Clean-up
      frameEncoder.Dispose();
      encoder.Dispose();
      wicStream.Dispose();
      
      imgBackdrop.ImageUrl = "data:image/png;base64," + Convert.ToBase64String(memStream.ToArray(), 0, memStream.ToArray().Length);
      

      【讨论】:

        猜你喜欢
        • 2013-10-11
        • 1970-01-01
        • 2021-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-11
        相关资源
        最近更新 更多