How to use memory stream instead of files when rendering Direct2D images through SharpDX?

Customization

Consider this program from scratch, which uses SharpDX , a managed shell for Direct * libraries, to display a bitmap image and save it as 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"))); } } } 

Running this program gives you the test.png file in the working directory of the program with the following beautiful image:

Output image

Question

Surprisingly, I just made an image using Direct2D instead of GDI +, which is supposedly supported more in the context of an ASP.NET expression. In addition, Direct2D is a new heat.

Let's say that I wanted to write a function that displayed such an image, and returned a PNG as a Stream or byte[] array, which performs the entire operation of visualization and encoding in memory instead of writing to the file system. This is for responding to a web request; it makes sense to just release it directly into the browser without going through the file system.

In GDI +, I could do this with a MemoryStream quite easily, but I cannot figure out how to use a DataStream in SharpDX in my favor, not knowing the buffer size:

  var bufferSize = 1024 * 3; // how do I know? var buffer = new DataStream( bufferSize, true, true); var stream = new WICStream( wicFactory, buffer); 
  • Should I P / Invoke on CreateStreamOnHGlobal and use IntPtr to build a DataStream
  • Is there some kind of DataStream overload that I am missing?
  • Is there an easy way to pre-compute the necessary buffer needed to store a PNG encoded image?
  • Or do I just need to navigate through the file system?

Thanks for any help!

+6
source share
2 answers

The author of the library added this as a function .

I will leave a question, because, in my opinion, the code provides a useful Direct2D sample for people.

+4
source

If someone wants to do this in 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); 
+1
source

Source: https://habr.com/ru/post/907708/


All Articles