Как использовать поток памяти вместо файлов при рендеринге изображений Direct2D через SharpDX?
настройки
рассмотрим данную программу scratch, которая использует 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")));
}
}
}
запуск этой программы дает вам "тест.png " файл в рабочем каталоге программы со следующим красивым изображением:
вопрос
Awesome, я только что визуализировал изображение с помощью Direct2D вместо GDI+, который предположительно более поддерживается в контексте ASP.NET применение. Кроме того, Direct2D-это новая горячность.
предположим, что я хотел написать функцию, которая визуализировала такое изображение и вернула PNG как Stream
или byte[]
массив, выполняющий всю операцию рендеринга и кодирования в памяти вместо записи в файловую систему. Это для ответа на веб-запрос; имеет смысл просто передать его прямо в браузер без прохождения через файловую систему.
в GDI+ я мог бы сделать это с помощью MemoryStream
довольно легко, но я не могу выяснить, как использовать DataStream
в SharpDX в мою пользу, не зная размер буфера:
var bufferSize = 1024 * 3; // how do I know?
var buffer = new DataStream(
bufferSize,
true,
true);
var stream = new WICStream(
wicFactory,
buffer);
- должен ли я P / Invoke to
CreateStreamOnHGlobal
и использоватьIntPtr
строитьDataStream
? - есть перегрузка
DataStream
что я пропал? - есть ли простой способ предварительно вычислить необходимый буфер, необходимый для хранения закодированного PNG-изображения?
- или я должен просто пройти через файловую систему?
Спасибо за любую помощь!
2 ответов
автор библиотека добавил Это как функцию.
Я оставлю вопрос, поскольку я думаю, что код предоставляет полезный образец Direct2D для людей.
Если кто-то хочет сделать это в 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);