private MemoryStream GetBitmapAsStream(WIC.Bitmap wicBitmap) { int width = wicBitmap.Size.Width; int height = wicBitmap.Size.Height; var ms = new MemoryStream(); using (var stream = new WIC.WICStream( this.WicFactory, ms)) { using (var encoder = new WIC.PngBitmapEncoder(WicFactory)) { encoder.Initialize(stream); using (var frameEncoder = new WIC.BitmapFrameEncode(encoder)) { frameEncoder.Initialize(); frameEncoder.SetSize(width, height); var format = WIC.PixelFormat.Format32bppBGRA; frameEncoder.SetPixelFormat(ref format); frameEncoder.WriteSource(wicBitmap); frameEncoder.Commit(); } encoder.Commit(); } } ms.Position = 0; return(ms); }
//------------------------------------------------------------------------------------- // Encodes a single frame //------------------------------------------------------------------------------------- private static void EncodeImage(PixelBuffer image, WICFlags flags, WIC.BitmapFrameEncode frame) { Guid pfGuid; if (!ToWIC(image.Format, out pfGuid)) { throw new NotSupportedException("Format not supported"); } frame.Initialize(); frame.SetSize(image.Width, image.Height); frame.SetResolution(72, 72); Guid targetGuid = pfGuid; frame.SetPixelFormat(ref targetGuid); if (targetGuid != pfGuid) { using (var source = new WIC.Bitmap(Factory, image.Width, image.Height, pfGuid, new SDX.DataRectangle(image.DataPointer, image.RowStride), image.BufferStride)) { using (var converter = new WIC.FormatConverter(Factory)) { using (var palette = new WIC.Palette(Factory)) { palette.Initialize(source, 256, true); converter.Initialize(source, targetGuid, GetWICDither(flags), palette, 0, WIC.BitmapPaletteType.Custom); int bpp = GetBitsPerPixel(targetGuid); if (bpp == 0) { throw new NotSupportedException("Unable to determine the Bpp for the target format"); } int rowPitch = (image.Width * bpp + 7) / 8; int slicePitch = rowPitch * image.Height; var temp = SDX.Utilities.AllocateMemory(slicePitch); try { converter.CopyPixels(rowPitch, temp, slicePitch); frame.Palette = palette; frame.WritePixels(image.Height, temp, rowPitch, slicePitch); } finally { SDX.Utilities.FreeMemory(temp); } } } } } else { // No conversion required frame.WritePixels(image.Height, image.DataPointer, image.RowStride, image.BufferStride); } frame.Commit(); }
public void Save(Stream stream, ImageFormat format) { using (var encoder = new s.WIC.BitmapEncoder( SDFactory.WicImagingFactory, format.ToWic())) { encoder.Initialize(stream); using (var frameEncoder = new s.WIC.BitmapFrameEncode(encoder)) { frameEncoder.WriteSource(Control); frameEncoder.Commit(); } encoder.Commit(); } }
private Stream DumpAndSaveImage() { var stream = new MemoryStream(); var textureSDRCpuCopy = new D3D11.Texture2D(d3dDevice, new D3D11.Texture2DDescription { Width = description.CanvasRect.Width, Height = description.CanvasRect.Height, MipLevels = 1, ArraySize = 1, Format = DXGI.Format.B8G8R8A8_UNorm_SRgb, Usage = D3D11.ResourceUsage.Staging, SampleDescription = new DXGI.SampleDescription(1, 0), BindFlags = D3D11.BindFlags.None, CpuAccessFlags = D3D11.CpuAccessFlags.Read, OptionFlags = D3D11.ResourceOptionFlags.None, }); DataStream rawSdrImageDataStream; d3dContext.CopyResource(textureSDRImage, textureSDRCpuCopy); var dataBox = d3dContext.MapSubresource(textureSDRCpuCopy, 0, 0, D3D11.MapMode.Read, D3D11.MapFlags.None, out rawSdrImageDataStream); var dataRectangle = new DataRectangle { DataPointer = rawSdrImageDataStream.DataPointer, Pitch = dataBox.RowPitch, }; using (var bitmap = new WIC.Bitmap(wicFactory, description.CanvasRect.Width, description.CanvasRect.Height, WIC.PixelFormat.Format32bppBGRA, dataRectangle)) using (var imageEncoder = new WIC.BmpBitmapEncoder(wicFactory, stream)) using (var encodeInstance = new WIC.BitmapFrameEncode(imageEncoder)) { encodeInstance.Initialize(); encodeInstance.SetSize(bitmap.Size.Width, bitmap.Size.Height); var pixelFormat = WIC.PixelFormat.Format24bppBGR; encodeInstance.SetPixelFormat(ref pixelFormat); encodeInstance.WriteSource(bitmap); encodeInstance.Commit(); imageEncoder.Commit(); stream.Flush(); } d3dContext.UnmapSubresource(textureSDRCpuCopy, 0); rawSdrImageDataStream.Dispose(); textureSDRCpuCopy.Dispose(); return(stream); }
public void Save(WIC.Bitmap wicBitmap, Stream stream) { using (var encoder = new WIC.BitmapEncoder(WicFactory, WIC.ContainerFormatGuids.Jpeg, stream)) using (var frame = new WIC.BitmapFrameEncode(encoder)) { frame.Initialize(); var pfx = WIC.PixelFormat.Format128bppRGBAFloat; //Format64bppRGBA; //FormatDontCare; frame.SetResolution(600, 600); frame.SetPixelFormat(ref pfx); frame.WriteSource(wicBitmap); frame.Commit(); encoder.Commit(); } }
public static void EncodeImage(this d2.Bitmap target, ImageFormat imageFormat, Stream outputStream) { var width = target.PixelSize.Width; var height = target.PixelSize.Height; var wicBitmap = new wic.Bitmap(DXGraphicsService.FactoryImaging, width, height, wic.PixelFormat.Format32bppBGR, wic.BitmapCreateCacheOption.CacheOnLoad); var renderTargetProperties = new d2.RenderTargetProperties(d2.RenderTargetType.Default, new d2.PixelFormat(Format.Unknown, d2.AlphaMode.Unknown), 0, 0, d2.RenderTargetUsage.None, d2.FeatureLevel.Level_DEFAULT); var d2DRenderTarget = new d2.WicRenderTarget(target.Factory, wicBitmap, renderTargetProperties); d2DRenderTarget.BeginDraw(); d2DRenderTarget.Clear(global::SharpDX.Color.Transparent); d2DRenderTarget.DrawBitmap(target, 1, d2.BitmapInterpolationMode.Linear); d2DRenderTarget.EndDraw(); var stream = new wic.WICStream(DXGraphicsService.FactoryImaging, outputStream); // Initialize a Jpeg encoder with this stream var encoder = new wic.BitmapEncoder(DXGraphicsService.FactoryImaging, GetImageFormat(imageFormat)); encoder.Initialize(stream); // Create a Frame encoder var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder); bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(width, height); Guid pixelFormatGuid = wic.PixelFormat.FormatDontCare; bitmapFrameEncode.SetPixelFormat(ref pixelFormatGuid); bitmapFrameEncode.WriteSource(wicBitmap); bitmapFrameEncode.Commit(); encoder.Commit(); bitmapFrameEncode.Dispose(); encoder.Dispose(); stream.Dispose(); d2DRenderTarget.Dispose(); wicBitmap.Dispose(); }
public void SaveAsPng(System.IO.Stream stream) { using (var encoder = new WIC.PngBitmapEncoder(factories.WICFactory, stream)) { using (var bitmapFrameEncode = new WIC.BitmapFrameEncode(encoder)) { bitmapFrameEncode.Initialize(); var size = bmp.Size; bitmapFrameEncode.SetSize(size.Width, size.Height); var pf = bmp.PixelFormat; bitmapFrameEncode.SetPixelFormat(ref pf); bitmapFrameEncode.WriteSource(bmp); bitmapFrameEncode.Commit(); encoder.Commit(); } } }
private static void SaveD2DBitmap(WIC.ImagingFactory2 wic, WIC.Bitmap wicBitmap, Stream outputStream) { using (var encoder = new WIC.BitmapEncoder(wic, WIC.ContainerFormatGuids.Png)) { encoder.Initialize(outputStream); using (var frame = new WIC.BitmapFrameEncode(encoder)) { frame.Initialize(); frame.SetSize(wicBitmap.Size.Width, wicBitmap.Size.Height); var pixelFormat = wicBitmap.PixelFormat; frame.SetPixelFormat(ref pixelFormat); frame.WriteSource(wicBitmap); frame.Commit(); encoder.Commit(); } } }
private void WriteToEncoder(wic.BitmapEncoder encoder, wic.WICStream wicStream) { encoder.Initialize(wicStream); using (var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder)) { bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(Width, Height); var format = wic.PixelFormat.FormatDontCare; bitmapFrameEncode.SetPixelFormat(ref format); // this is the trick to write D2D1 bitmap to WIC var imageEncoder = new wic.ImageEncoder(DXGraphicsService.FactoryImaging, _device2D); var parameters = new wic.ImageParameters(_pixelFormat, Dpi, Dpi, 0, 0, Width, Height); imageEncoder.WriteFrame(_bitmap, bitmapFrameEncode, parameters); bitmapFrameEncode.Commit(); encoder.Commit(); } }
static void over() { var inputPath = "Input.png"; var outputPath = "output.png"; // 그래픽을 랜더링할 장비를 추가 - 3D or 2D var defaultDevice = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, d3d.DeviceCreationFlags.VideoSupport | d3d.DeviceCreationFlags.BgraSupport | d3d.DeviceCreationFlags.None); var d3dDevice = defaultDevice.QueryInterface <d3d.Device1>(); //get a refer to the D3D 11.1 device var dxgiDevice = d3dDevice.QueryInterface <dxgi.Device1>(); //get a refer to the DXGI device var d2dDevice = new d2.Device(dxgiDevice); // DeviceContext를 초기화. D2D 렌더링 타겟이 될 것이고 모든 렌더링 작업을 허용 var d2dContext = new d2.DeviceContext(d2dDevice, d2.DeviceContextOptions.None); var dwFactory = new dw.Factory(); //D2D, WIC 둘 다 지원되는 픽셀 형식 지정 var d2PixelFormat = new d2.PixelFormat(dxgi.Format.R8G8B8A8_UNorm, d2.AlphaMode.Premultiplied); //RGBA형식 사용 var wicPixelFormat = wic.PixelFormat.Format32bppPRGBA; //이미지 로딩 var imagingFactory = new wic.ImagingFactory2(); var decoder = new wic.PngBitmapDecoder(imagingFactory); var inputStream = new wic.WICStream(imagingFactory, inputPath, NativeFileAccess.Read); decoder.Initialize(inputStream, wic.DecodeOptions.CacheOnLoad); //다이렉트2D가 사용할수 있도록 디코딩 var formatConverter = new wic.FormatConverter(imagingFactory); formatConverter.Initialize(decoder.GetFrame(0), wicPixelFormat); //기본 이미지를 D2D이미지로 로드 //var inputBitmap = d2.Bitmap1.FromWicBitmap(d2dContext, formatConverter, new d2.BitmapProperties1(d2PixelFormat)); //이미지 크기 저장 var inputImageSize = formatConverter.Size; var pixelWidth = inputImageSize.Width; var pixelHeight = inputImageSize.Height; //Effect1 : BitpmapSource - 디코딩된 이미지 데이터를 가져오고 BitmapSource 가져오기 var bitmapSourceEffect = new d2.Effects.BitmapSource(d2dContext); bitmapSourceEffect.WicBitmapSource = formatConverter; // Effect 2 : GaussianBlur - bitmapsource에 가우시안블러 효과 적용 var gaussianBlurEffect = new d2.Effects.GaussianBlur(d2dContext); gaussianBlurEffect.SetInput(0, bitmapSourceEffect.Output, true); gaussianBlurEffect.StandardDeviation = 5f; //overlay text setup var textFormat = new dw.TextFormat(dwFactory, "Arial", 15f); //draw a long text to show the automatic line wrapping var textToDraw = "sime ling text..." + "text" + "dddd"; //create the text layout - this imroves the drawing performance for static text // as the glyph positions are precalculated //윤곽선 글꼴 데이터에서 글자 하나의 모양에 대한 기본 단위를 글리프(glyph)라고 한다 var textLayout = new dw.TextLayout(dwFactory, textToDraw, textFormat, 300f, 1000f); SharpDX.Mathematics.Interop.RawColor4 color = new SharpDX.Mathematics.Interop.RawColor4(255, 255, 255, 1); var textBrush = new d2.SolidColorBrush(d2dContext, color); //여기서부터 다시 //render target setup //create the d2d bitmap description using default flags and 96 DPI var d2dBitmapProps = new d2.BitmapProperties1(d2PixelFormat, 96, 96, d2.BitmapOptions.Target | d2.BitmapOptions.CannotDraw); //the render target var d2dRenderTarget = new d2.Bitmap1(d2dContext, new Size2(pixelWidth, pixelHeight), d2dBitmapProps); d2dContext.Target = d2dRenderTarget; //associate bitmap with the d2d context //Drawing //slow preparations - fast drawing d2dContext.BeginDraw(); d2dContext.DrawImage(gaussianBlurEffect, new SharpDX.Mathematics.Interop.RawVector2(100f, 100f)); d2dContext.DrawTextLayout(new SharpDX.Mathematics.Interop.RawVector2(50f, 50f), textLayout, textBrush); d2dContext.EndDraw(); //Image save //delete the output file if it already exists if (System.IO.File.Exists(outputPath)) { System.IO.File.Delete(outputPath); } //use the appropiate overload to write either to tream or to a file var stream = new wic.WICStream(imagingFactory, outputPath, NativeFileAccess.Write); //select the image encoding format HERE var encoder = new wic.PngBitmapEncoder(imagingFactory); encoder.Initialize(stream); var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder); bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(pixelWidth, pixelHeight); bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat); //this is the trick to write d2d1 bitmap to WIC var imageEncoder = new wic.ImageEncoder(imagingFactory, d2dDevice); imageEncoder.WriteFrame(d2dRenderTarget, bitmapFrameEncode, new wic.ImageParameters(d2PixelFormat, 96, 96, 0, 0, pixelWidth, pixelHeight)); bitmapFrameEncode.Commit(); encoder.Commit(); //cleanup //dispose everything and free used resources bitmapFrameEncode.Dispose(); encoder.Dispose(); stream.Dispose(); textBrush.Dispose(); textLayout.Dispose(); textFormat.Dispose(); formatConverter.Dispose(); //gaussianBlurEffect.Dispose(); bitmapSourceEffect.Dispose(); d2dRenderTarget.Dispose(); inputStream.Dispose(); decoder.Dispose(); d2dContext.Dispose(); dwFactory.Dispose(); imagingFactory.Dispose(); d2dDevice.Dispose(); dxgiDevice.Dispose(); d3dDevice.Dispose(); defaultDevice.Dispose(); //save System.Diagnostics.Process.Start(outputPath); }
public void SaveAsPng(System.IO.Stream stream) { using (var encoder = new WIC.PngBitmapEncoder (factories.WICFactory, stream)) { using (var bitmapFrameEncode = new WIC.BitmapFrameEncode (encoder)) { bitmapFrameEncode.Initialize (); var size = bmp.Size; bitmapFrameEncode.SetSize (size.Width, size.Height); var pf = bmp.PixelFormat; bitmapFrameEncode.SetPixelFormat (ref pf); bitmapFrameEncode.WriteSource (bmp); bitmapFrameEncode.Commit (); encoder.Commit (); } } }
public System.Drawing.Bitmap TextToBitmap(string text, out Size2F size, RawColor4 bgcolor, d2.TextAntialiasMode aamode, int maxWidth = 1000, int maxHeight = 1000) { var sz = GetTextSize(text, maxWidth, maxHeight); int pixelWidth = (int)(sz.Width * 2); int pixelHeight = (int)(sz.Height * 2); var d2dRenderTarget = new Bitmap1(d2dContext, new Size2(pixelWidth, pixelHeight), d2dBitmapProps); if (d2dContext.Target != null) { d2dContext.Target.Dispose(); } d2dContext.Target = d2dRenderTarget; // associate bitmap with the d2d context // Draw Text TextLayout textLayout = new TextLayout(dwFactory, text, textFormat, pixelWidth, pixelHeight); //d2dContext.TextRenderingParams = new RenderingParams(dwFactory, 1, 0, 0, PixelGeometry.Flat, renderingMode); d2dContext.TextAntialiasMode = aamode; d2dContext.BeginDraw(); d2dContext.Clear(bgcolor); d2dContext.DrawTextLayout(new RawVector2(0, 0), textLayout, textBrush, DrawTextOptions.EnableColorFont); d2dContext.EndDraw(); size = new Size2F(textLayout.Metrics.Width, textLayout.Metrics.Height); textLayout.Dispose(); // Copy to MemoryStream var stream = new MemoryStream(); var encoder = new wic.PngBitmapEncoder(imagingFactory); encoder.Initialize(stream); var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder); bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(pixelWidth, pixelHeight); bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat); // this is the trick to write D2D1 bitmap to WIC var imageEncoder = new wic.ImageEncoder(imagingFactory, d2dDevice); var imageParam = new wic.ImageParameters(d2PixelFormat, dpi, dpi, 0, 0, pixelWidth, pixelHeight); imageEncoder.WriteFrame(d2dRenderTarget, bitmapFrameEncode, imageParam); bitmapFrameEncode.Commit(); encoder.Commit(); imageEncoder.Dispose(); encoder.Dispose(); bitmapFrameEncode.Dispose(); d2dRenderTarget.Dispose(); // Convert To Bitmap byte[] data = stream.ToArray(); stream.Seek(0, SeekOrigin.Begin); var bmp = new System.Drawing.Bitmap(stream); stream.Dispose(); return(bmp); }
public static byte[] CreatePngImage(int width, int height, string text, float fontSize = 30.0f, string font = "Times New Roman", int lineCount = 5, bool rotation = false, float turbulenceAmount = 60.0f) { using (var wic = new WIC.ImagingFactory2()) using (var d2d = new D2D.Factory()) using (var wicBitmap = new WIC.Bitmap(wic, width, height, WIC.PixelFormat.Format32bppPBGRA, WIC.BitmapCreateCacheOption.CacheOnDemand)) using (var target = new D2D.WicRenderTarget(d2d, wicBitmap, new D2D.RenderTargetProperties())) using (var dwriteFactory = new DWrite.Factory()) using (var brush = new D2D.SolidColorBrush(target, Color.Yellow)) using (var encoder = new WIC.PngBitmapEncoder(wic)) using (var ms = new MemoryStream()) using (var dc = target.QueryInterface <D2D.DeviceContext>()) using (var bmpLayer = new D2D.Bitmap1(dc, target.PixelSize, new D2D.BitmapProperties1(new D2D.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Premultiplied), d2d.DesktopDpi.Width, d2d.DesktopDpi.Height, D2D.BitmapOptions.Target))) { var r = new Random(); encoder.Initialize(ms); D2D.Image oldTarget = dc.Target; { dc.Target = bmpLayer; dc.BeginDraw(); var textFormat = new DWrite.TextFormat(dwriteFactory, font, fontSize); for (int charIndex = 0; charIndex < text.Length; ++charIndex) { using (var layout = new DWrite.TextLayout(dwriteFactory, text[charIndex].ToString(), textFormat, float.MaxValue, float.MaxValue)) { var layoutSize = new Vector2(layout.Metrics.Width, layout.Metrics.Height); using (var b2 = new D2D.LinearGradientBrush(dc, new D2D.LinearGradientBrushProperties { StartPoint = Vector2.Zero, EndPoint = layoutSize, }, new D2D.GradientStopCollection(dc, new[] { new D2D.GradientStop { Position = 0.0f, Color = ColorFromHsl(r.NextFloat(0, 1), 1.0f, 0.8f) }, new D2D.GradientStop { Position = 1.0f, Color = ColorFromHsl(r.NextFloat(0, 1), 1.0f, 0.8f) }, }))) { var position = new Vector2(charIndex * width / text.Length, r.NextFloat(0, height - layout.Metrics.Height)); dc.Transform = Matrix3x2.Translation(-layoutSize / 2) * Matrix3x2.Skew(r.NextFloat(0, 0.5f), r.NextFloat(0, 0.5f)) * (rotation ? Matrix3x2.Rotation(r.NextFloat(0, (float)(Math.PI * 2))) : Matrix3x2.Identity) * Matrix3x2.Translation(position + layoutSize / 2); dc.DrawTextLayout(Vector2.Zero, layout, b2); } } } for (var i = 0; i < lineCount; ++i) { target.Transform = Matrix3x2.Identity; brush.Color = ColorFromHsl(r.NextFloat(0, 1), 1.0f, 0.3f); target.DrawLine( r.NextVector2(Vector2.Zero, new Vector2(width, height)), r.NextVector2(Vector2.Zero, new Vector2(width, height)), brush, 3.0f); } target.EndDraw(); } Color background = ColorFromHsl(r.NextFloat(0, 1), 1.0f, 0.3f); { dc.Target = null; using (var displacement = new D2D.Effects.DisplacementMap(dc)) { displacement.SetInput(0, bmpLayer, true); displacement.Scale = turbulenceAmount; var turbulence = new D2D.Effects.Turbulence(dc); displacement.SetInputEffect(1, turbulence); dc.Target = oldTarget; dc.BeginDraw(); dc.Clear(background); dc.DrawImage(displacement); dc.EndDraw(); using (var frame = new WIC.BitmapFrameEncode(encoder)) { frame.Initialize(); frame.SetSize(wicBitmap.Size.Width, wicBitmap.Size.Height); var pixelFormat = wicBitmap.PixelFormat; frame.SetPixelFormat(ref pixelFormat); frame.WriteSource(wicBitmap); frame.Commit(); } } } encoder.Commit(); return(ms.ToArray()); } }
static void Main() { // input and output files are supposed to be in the program folder var inputPath = "Input.png"; var outputPath = "Output.png"; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // INITIALIZATION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // initialize the D3D device which will allow to render to image any graphics - 3D or 2D var defaultDevice = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, d3d.DeviceCreationFlags.VideoSupport | d3d.DeviceCreationFlags.BgraSupport | d3d.DeviceCreationFlags.Debug); // take out the Debug flag for better performance var d3dDevice = defaultDevice.QueryInterface<d3d.Device1>(); // get a reference to the Direct3D 11.1 device var dxgiDevice = d3dDevice.QueryInterface<dxgi.Device>(); // get a reference to DXGI device var d2dDevice = new d2.Device(dxgiDevice); // initialize the D2D device var imagingFactory = new wic.ImagingFactory2(); // initialize the WIC factory // initialize the DeviceContext - it will be the D2D render target and will allow all rendering operations var d2dContext = new d2.DeviceContext(d2dDevice, d2.DeviceContextOptions.None); var dwFactory = new dw.Factory(); // specify a pixel format that is supported by both D2D and WIC var d2PixelFormat = new d2.PixelFormat(dxgi.Format.R8G8B8A8_UNorm, d2.AlphaMode.Premultiplied); // if in D2D was specified an R-G-B-A format - use the same for wic var wicPixelFormat = wic.PixelFormat.Format32bppPRGBA; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IMAGE LOADING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var decoder = new wic.PngBitmapDecoder(imagingFactory); // we will load a PNG image var inputStream = new wic.WICStream(imagingFactory, inputPath, NativeFileAccess.Read); // open the image file for reading decoder.Initialize(inputStream, wic.DecodeOptions.CacheOnLoad); // decode the loaded image to a format that can be consumed by D2D var formatConverter = new wic.FormatConverter(imagingFactory); formatConverter.Initialize(decoder.GetFrame(0), wicPixelFormat); // load the base image into a D2D Bitmap //var inputBitmap = d2.Bitmap1.FromWicBitmap(d2dContext, formatConverter, new d2.BitmapProperties1(d2PixelFormat)); // store the image size - output will be of the same size var inputImageSize = formatConverter.Size; var pixelWidth = inputImageSize.Width; var pixelHeight = inputImageSize.Height; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // EFFECT SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect 1 : BitmapSource - take decoded image data and get a BitmapSource from it var bitmapSourceEffect = new d2.Effects.BitmapSource(d2dContext); bitmapSourceEffect.WicBitmapSource = formatConverter; // Effect 2 : GaussianBlur - give the bitmapsource a gaussian blurred effect var gaussianBlurEffect = new d2.Effects.GaussianBlur(d2dContext); gaussianBlurEffect.SetInput(0, bitmapSourceEffect.Output, true); gaussianBlurEffect.StandardDeviation = 5f; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // OVERLAY TEXT SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var textFormat = new dw.TextFormat(dwFactory, "Arial", 15f); // create the text format of specified font configuration // draw a long text to show the automatic line wrapping var textToDraw = "Some long text to show the drawing of preformatted " + "glyphs using DirectWrite on the Direct2D surface." + " Notice the automatic wrapping of line if it exceeds desired width."; // create the text layout - this improves the drawing performance for static text // as the glyph positions are precalculated var textLayout = new dw.TextLayout(dwFactory, textToDraw, textFormat, 300f, 1000f); var textBrush = new d2.SolidColorBrush(d2dContext, Color.LightGreen); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // RENDER TARGET SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // create the d2d bitmap description using default flags (from SharpDX samples) and 96 DPI var d2dBitmapProps = new d2.BitmapProperties1(d2PixelFormat, 96, 96, d2.BitmapOptions.Target | d2.BitmapOptions.CannotDraw); // the render target var d2dRenderTarget = new d2.Bitmap1(d2dContext, new Size2(pixelWidth, pixelHeight), d2dBitmapProps); d2dContext.Target = d2dRenderTarget; // associate bitmap with the d2d context // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // DRAWING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // slow preparations - fast drawing: d2dContext.BeginDraw(); d2dContext.DrawImage(gaussianBlurEffect); d2dContext.DrawTextLayout(new Vector2(5f, 5f), textLayout, textBrush); d2dContext.EndDraw(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IMAGE SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // delete the output file if it already exists if (System.IO.File.Exists(outputPath)) System.IO.File.Delete(outputPath); // use the appropiate overload to write either to stream or to a file var stream = new wic.WICStream(imagingFactory, outputPath, NativeFileAccess.Write); // select the image encoding format HERE var encoder = new wic.PngBitmapEncoder(imagingFactory); encoder.Initialize(stream); var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder); bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(pixelWidth, pixelHeight); bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat); // this is the trick to write D2D1 bitmap to WIC var imageEncoder = new wic.ImageEncoder(imagingFactory, d2dDevice); imageEncoder.WriteFrame(d2dRenderTarget, bitmapFrameEncode, new wic.ImageParameters(d2PixelFormat, 96, 96, 0, 0, pixelWidth, pixelHeight)); bitmapFrameEncode.Commit(); encoder.Commit(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CLEANUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // dispose everything and free used resources bitmapFrameEncode.Dispose(); encoder.Dispose(); stream.Dispose(); textBrush.Dispose(); textLayout.Dispose(); textFormat.Dispose(); formatConverter.Dispose(); gaussianBlurEffect.Dispose(); bitmapSourceEffect.Dispose(); d2dRenderTarget.Dispose(); inputStream.Dispose(); decoder.Dispose(); d2dContext.Dispose(); dwFactory.Dispose(); imagingFactory.Dispose(); d2dDevice.Dispose(); dxgiDevice.Dispose(); d3dDevice.Dispose(); defaultDevice.Dispose(); // show the result System.Diagnostics.Process.Start(outputPath); }
public MemoryStream RenderToPngStream(FrameworkElement fe) { var width = (int)Math.Ceiling(fe.ActualWidth); var height = (int)Math.Ceiling(fe.ActualHeight); // pixel format with transparency/alpha channel and RGB values premultiplied by alpha var pixelFormat = WIC.PixelFormat.Format32bppPRGBA; // pixel format without transparency, but one that works with Cleartype antialiasing //var pixelFormat = WicPixelFormat.Format32bppBGR; var wicBitmap = new WIC.Bitmap( this.WicFactory, width, height, pixelFormat, WIC.BitmapCreateCacheOption.CacheOnLoad); var renderTargetProperties = new D2D.RenderTargetProperties( D2D.RenderTargetType.Default, new D2D.PixelFormat(Format.R8G8B8A8_UNorm, D2D.AlphaMode.Premultiplied), //new D2DPixelFormat(Format.Unknown, AlphaMode.Unknown), // use this for non-alpha, cleartype antialiased text 0, 0, D2D.RenderTargetUsage.None, D2D.FeatureLevel.Level_DEFAULT); var renderTarget = new D2D.WicRenderTarget( this.D2DFactory, wicBitmap, renderTargetProperties) { //TextAntialiasMode = TextAntialiasMode.Cleartype // this only works with the pixel format with no alpha channel TextAntialiasMode = D2D.TextAntialiasMode.Grayscale // this is the best we can do for bitmaps with alpha channels }; Compose(renderTarget, fe); // TODO: There is no need to encode the bitmap to PNG - we could just copy the texture pixel buffer to a WriteableBitmap pixel buffer. var ms = new MemoryStream(); var stream = new WIC.WICStream( this.WicFactory, ms); var encoder = new WIC.PngBitmapEncoder(WicFactory); encoder.Initialize(stream); var frameEncoder = new WIC.BitmapFrameEncode(encoder); frameEncoder.Initialize(); frameEncoder.SetSize(width, height); var format = WIC.PixelFormat.Format32bppBGRA; //var format = WicPixelFormat.FormatDontCare; frameEncoder.SetPixelFormat(ref format); frameEncoder.WriteSource(wicBitmap); frameEncoder.Commit(); encoder.Commit(); frameEncoder.Dispose(); encoder.Dispose(); stream.Dispose(); ms.Position = 0; return(ms); }
public static MemoryStream Resize(System.IO.Stream source, int maxwidth, int maxheight, Action beforeDrawImage, Action afterDrawImage) { // initialize the D3D device which will allow to render to image any graphics - 3D or 2D var defaultDevice = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Warp, d3d.DeviceCreationFlags.BgraSupport | d3d.DeviceCreationFlags.SingleThreaded | d3d.DeviceCreationFlags.PreventThreadingOptimizations); var d3dDevice = defaultDevice.QueryInterface<d3d.Device1>(); // get a reference to the Direct3D 11.1 device var dxgiDevice = d3dDevice.QueryInterface<dxgi.Device>(); // get a reference to DXGI device var d2dDevice = new d2.Device(dxgiDevice); // initialize the D2D device var imagingFactory = new wic.ImagingFactory2(); // initialize the WIC factory // initialize the DeviceContext - it will be the D2D render target and will allow all rendering operations var d2dContext = new d2.DeviceContext(d2dDevice, d2.DeviceContextOptions.None); var dwFactory = new dw.Factory(); // specify a pixel format that is supported by both D2D and WIC var d2PixelFormat = new d2.PixelFormat(dxgi.Format.R8G8B8A8_UNorm, d2.AlphaMode.Premultiplied); // if in D2D was specified an R-G-B-A format - use the same for wic var wicPixelFormat = wic.PixelFormat.Format32bppPRGBA; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IMAGE LOADING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var decoder = new wic.BitmapDecoder(imagingFactory,source, wic.DecodeOptions.CacheOnLoad); // decode the loaded image to a format that can be consumed by D2D var formatConverter = new wic.FormatConverter(imagingFactory); formatConverter.Initialize(decoder.GetFrame(0), wicPixelFormat); // store the image size - output will be of the same size var inputImageSize = formatConverter.Size; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // RENDER TARGET SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // create the d2d bitmap description using default flags (from SharpDX samples) and 96 DPI var d2dBitmapProps = new d2.BitmapProperties1(d2PixelFormat, 96, 96, d2.BitmapOptions.Target | d2.BitmapOptions.CannotDraw); //Calculate size var resultSize = MathUtil.ScaleWithin(inputImageSize.Width,inputImageSize.Height,maxwidth,maxheight); var newWidth = resultSize.Item1; var newHeight = resultSize.Item2; // the render target var d2dRenderTarget = new d2.Bitmap1(d2dContext, new Size2(newWidth, newHeight), d2dBitmapProps); d2dContext.Target = d2dRenderTarget; // associate bitmap with the d2d context var bitmapSourceEffect = new d2.Effects.BitmapSourceEffect(d2dContext); bitmapSourceEffect.WicBitmapSource = formatConverter; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // DRAWING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ beforeDrawImage(); // slow preparations - fast drawing: d2dContext.BeginDraw(); d2dContext.Transform = Matrix3x2.Scaling(new Vector2((float)(newWidth / (float)inputImageSize.Width), (float)(newHeight / (float)inputImageSize.Height))); d2dContext.DrawImage(bitmapSourceEffect, d2.InterpolationMode.HighQualityCubic); d2dContext.EndDraw(); afterDrawImage(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IMAGE SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var ms = new MemoryStream(); // use the appropiate overload to write either to stream or to a file var stream = new wic.WICStream(imagingFactory,ms); // select the image encoding format HERE var encoder = new wic.JpegBitmapEncoder(imagingFactory); encoder.Initialize(stream); var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder); bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(newWidth, newHeight); bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat); // this is the trick to write D2D1 bitmap to WIC var imageEncoder = new wic.ImageEncoder(imagingFactory, d2dDevice); imageEncoder.WriteFrame(d2dRenderTarget, bitmapFrameEncode, new wic.ImageParameters(d2PixelFormat, 96, 96, 0, 0, newWidth, newHeight)); bitmapFrameEncode.Commit(); encoder.Commit(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CLEANUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // dispose everything and free used resources bitmapFrameEncode.Dispose(); encoder.Dispose(); stream.Dispose(); formatConverter.Dispose(); bitmapSourceEffect.Dispose(); d2dRenderTarget.Dispose(); decoder.Dispose(); d2dContext.Dispose(); dwFactory.Dispose(); imagingFactory.Dispose(); d2dDevice.Dispose(); dxgiDevice.Dispose(); d3dDevice.Dispose(); defaultDevice.Dispose(); return ms; }
private MemoryStream GetBitmapAsStream(WIC.Bitmap wicBitmap) { int width = wicBitmap.Size.Width; int height = wicBitmap.Size.Height; var ms = new MemoryStream(); using (var stream = new WIC.WICStream( this.WicFactory, ms)) { using (var encoder = new WIC.PngBitmapEncoder(WicFactory)) { encoder.Initialize(stream); using (var frameEncoder = new WIC.BitmapFrameEncode(encoder)) { frameEncoder.Initialize(); frameEncoder.SetSize(width, height); var format = WIC.PixelFormat.Format32bppBGRA; frameEncoder.SetPixelFormat(ref format); frameEncoder.WriteSource(wicBitmap); frameEncoder.Commit(); } encoder.Commit(); } } ms.Position = 0; return ms; }
private Result SaveWICTextureToFileFix( DeviceContext context, Texture2D source, ref Guid guidContainerFormat, string fileName) { if (fileName == null) { return(Result.InvalidArg); } Result res = CaptureTextureFix(context, source, out Texture2DDescription desc, out Texture2D staging); if (res.Failure) { return(res); } Guid pfGuid; //bool sRGB = false; Guid targetGuid; switch (desc.Format) { case DXGI.Format.R32G32B32A32_Float: pfGuid = WIC.PixelFormat.Format128bppRGBAFloat; break; case DXGI.Format.R16G16B16A16_Float: pfGuid = WIC.PixelFormat.Format64bppRGBAHalf; break; case DXGI.Format.R16G16B16A16_UNorm: pfGuid = WIC.PixelFormat.Format64bppRGBA; break; case DXGI.Format.R10G10B10_Xr_Bias_A2_UNorm: pfGuid = WIC.PixelFormat.Format32bppRGBA1010102XR; break; // DXGI 1.1 case DXGI.Format.R10G10B10A2_UNorm: pfGuid = WIC.PixelFormat.Format32bppRGBA1010102; break; case DXGI.Format.B5G5R5A1_UNorm: pfGuid = WIC.PixelFormat.Format16bppBGRA5551; break; case DXGI.Format.B5G6R5_UNorm: pfGuid = WIC.PixelFormat.Format16bppBGR565; break; case DXGI.Format.R32_Float: pfGuid = WIC.PixelFormat.Format32bppGrayFloat; break; case DXGI.Format.R16_Float: pfGuid = WIC.PixelFormat.Format16bppGrayHalf; break; case DXGI.Format.R16_UNorm: pfGuid = WIC.PixelFormat.Format16bppGray; break; case DXGI.Format.R8_UNorm: pfGuid = WIC.PixelFormat.Format8bppGray; break; case DXGI.Format.A8_UNorm: pfGuid = WIC.PixelFormat.Format8bppAlpha; break; case DXGI.Format.R8G8B8A8_UNorm: pfGuid = WIC.PixelFormat.Format32bppRGBA; break; case DXGI.Format.R8G8B8A8_UNorm_SRgb: pfGuid = WIC.PixelFormat.Format32bppRGBA; //sRGB = true; break; case DXGI.Format.B8G8R8A8_UNorm: // DXGI 1.1 pfGuid = WIC.PixelFormat.Format32bppBGRA; break; case DXGI.Format.B8G8R8A8_UNorm_SRgb: // DXGI 1.1 pfGuid = WIC.PixelFormat.Format32bppBGRA; //sRGB = true; break; case DXGI.Format.B8G8R8X8_UNorm: // DXGI 1.1 pfGuid = WIC.PixelFormat.Format32bppBGR; break; case DXGI.Format.B8G8R8X8_UNorm_SRgb: // DXGI 1.1 pfGuid = WIC.PixelFormat.Format32bppBGR; //sRGB = true; break; default: return(Result.GetResultFromWin32Error(unchecked ((int)0x80070032))); } // Create file FileStream fs = new FileStream(fileName, FileMode.Create); WIC.BitmapEncoder encoder = new WIC.BitmapEncoder(DirectX.ImageFactory, guidContainerFormat); encoder.Initialize(fs); WIC.BitmapFrameEncode frameEncode = new WIC.BitmapFrameEncode(encoder); frameEncode.Initialize(); frameEncode.SetSize(desc.Width, desc.Height); frameEncode.SetResolution(72.0, 72.0); switch (desc.Format) { case DXGI.Format.R32G32B32A32_Float: case DXGI.Format.R16G16B16A16_Float: targetGuid = WIC.PixelFormat.Format24bppBGR; break; case DXGI.Format.R16G16B16A16_UNorm: targetGuid = WIC.PixelFormat.Format48bppBGR; break; case DXGI.Format.B5G5R5A1_UNorm: targetGuid = WIC.PixelFormat.Format16bppBGR555; break; case DXGI.Format.B5G6R5_UNorm: targetGuid = WIC.PixelFormat.Format16bppBGR565; break; case DXGI.Format.R32_Float: case DXGI.Format.R16_Float: case DXGI.Format.R16_UNorm: case DXGI.Format.R8_UNorm: case DXGI.Format.A8_UNorm: targetGuid = WIC.PixelFormat.Format8bppGray; break; default: targetGuid = WIC.PixelFormat.Format24bppBGR; break; } frameEncode.SetPixelFormat(ref targetGuid); #region Write DataBox db = context.MapSubresource(staging, 0, MapMode.Read, MapFlags.None, out DataStream stream); if (pfGuid != targetGuid) { WIC.FormatConverter formatCoverter = new WIC.FormatConverter(DirectX.ImageFactory); if (formatCoverter.CanConvert(pfGuid, targetGuid)) { WIC.Bitmap src = new WIC.Bitmap(DirectX.ImageFactory, desc.Width, desc.Height, pfGuid, new DataRectangle(db.DataPointer, db.RowPitch)); formatCoverter.Initialize(src, targetGuid, SharpDX.WIC.BitmapDitherType.None, null, 0, SharpDX.WIC.BitmapPaletteType.Custom); frameEncode.WriteSource(formatCoverter, new Rectangle(0, 0, desc.Width, desc.Height)); } } else { frameEncode.WritePixels(desc.Height, new DataRectangle(db.DataPointer, db.RowPitch)); } context.UnmapSubresource(staging, 0); frameEncode.Commit(); encoder.Commit(); #endregion frameEncode.Dispose(); encoder.Dispose(); fs.Close(); return(Result.Ok); }
static void Main() { // input and output files are supposed to be in the program folder var inputPath = "Input.png"; var outputPath = "Output.png"; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // INITIALIZATION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // initialize the D3D device which will allow to render to image any graphics - 3D or 2D var defaultDevice = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware, d3d.DeviceCreationFlags.VideoSupport | d3d.DeviceCreationFlags.BgraSupport | d3d.DeviceCreationFlags.Debug); // take out the Debug flag for better performance var d3dDevice = defaultDevice.QueryInterface <d3d.Device1>(); // get a reference to the Direct3D 11.1 device var dxgiDevice = d3dDevice.QueryInterface <dxgi.Device>(); // get a reference to DXGI device var d2dDevice = new d2.Device(dxgiDevice); // initialize the D2D device var imagingFactory = new wic.ImagingFactory2(); // initialize the WIC factory // initialize the DeviceContext - it will be the D2D render target and will allow all rendering operations var d2dContext = new d2.DeviceContext(d2dDevice, d2.DeviceContextOptions.None); var dwFactory = new dw.Factory(); // specify a pixel format that is supported by both D2D and WIC var d2PixelFormat = new d2.PixelFormat(dxgi.Format.R8G8B8A8_UNorm, d2.AlphaMode.Premultiplied); // if in D2D was specified an R-G-B-A format - use the same for wic var wicPixelFormat = wic.PixelFormat.Format32bppPRGBA; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IMAGE LOADING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var decoder = new wic.PngBitmapDecoder(imagingFactory); // we will load a PNG image var inputStream = new wic.WICStream(imagingFactory, inputPath, NativeFileAccess.Read); // open the image file for reading decoder.Initialize(inputStream, wic.DecodeOptions.CacheOnLoad); // decode the loaded image to a format that can be consumed by D2D var formatConverter = new wic.FormatConverter(imagingFactory); formatConverter.Initialize(decoder.GetFrame(0), wicPixelFormat); // load the base image into a D2D Bitmap //var inputBitmap = d2.Bitmap1.FromWicBitmap(d2dContext, formatConverter, new d2.BitmapProperties1(d2PixelFormat)); // store the image size - output will be of the same size var inputImageSize = formatConverter.Size; var pixelWidth = inputImageSize.Width; var pixelHeight = inputImageSize.Height; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // EFFECT SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Effect 1 : BitmapSource - take decoded image data and get a BitmapSource from it var bitmapSourceEffect = new d2.Effects.BitmapSource(d2dContext); bitmapSourceEffect.WicBitmapSource = formatConverter; // Effect 2 : GaussianBlur - give the bitmapsource a gaussian blurred effect var gaussianBlurEffect = new d2.Effects.GaussianBlur(d2dContext); gaussianBlurEffect.SetInput(0, bitmapSourceEffect.Output, true); gaussianBlurEffect.StandardDeviation = 5f; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // OVERLAY TEXT SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var textFormat = new dw.TextFormat(dwFactory, "Arial", 15f); // create the text format of specified font configuration // draw a long text to show the automatic line wrapping var textToDraw = "Some long text to show the drawing of preformatted " + "glyphs using DirectWrite on the Direct2D surface." + " Notice the automatic wrapping of line if it exceeds desired width."; // create the text layout - this improves the drawing performance for static text // as the glyph positions are precalculated var textLayout = new dw.TextLayout(dwFactory, textToDraw, textFormat, 300f, 1000f); var textBrush = new d2.SolidColorBrush(d2dContext, Color.LightGreen); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // RENDER TARGET SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // create the d2d bitmap description using default flags (from SharpDX samples) and 96 DPI var d2dBitmapProps = new d2.BitmapProperties1(d2PixelFormat, 96, 96, d2.BitmapOptions.Target | d2.BitmapOptions.CannotDraw); // the render target var d2dRenderTarget = new d2.Bitmap1(d2dContext, new Size2(pixelWidth, pixelHeight), d2dBitmapProps); d2dContext.Target = d2dRenderTarget; // associate bitmap with the d2d context // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // DRAWING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // slow preparations - fast drawing: d2dContext.BeginDraw(); d2dContext.DrawImage(gaussianBlurEffect); d2dContext.DrawTextLayout(new Vector2(5f, 5f), textLayout, textBrush); d2dContext.EndDraw(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IMAGE SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // delete the output file if it already exists if (System.IO.File.Exists(outputPath)) { System.IO.File.Delete(outputPath); } // use the appropiate overload to write either to stream or to a file var stream = new wic.WICStream(imagingFactory, outputPath, NativeFileAccess.Write); // select the image encoding format HERE var encoder = new wic.PngBitmapEncoder(imagingFactory); encoder.Initialize(stream); var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder); bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(pixelWidth, pixelHeight); bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat); // this is the trick to write D2D1 bitmap to WIC var imageEncoder = new wic.ImageEncoder(imagingFactory, d2dDevice); imageEncoder.WriteFrame(d2dRenderTarget, bitmapFrameEncode, new wic.ImageParameters(d2PixelFormat, 96, 96, 0, 0, pixelWidth, pixelHeight)); bitmapFrameEncode.Commit(); encoder.Commit(); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CLEANUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // dispose everything and free used resources bitmapFrameEncode.Dispose(); encoder.Dispose(); stream.Dispose(); textBrush.Dispose(); textLayout.Dispose(); textFormat.Dispose(); formatConverter.Dispose(); gaussianBlurEffect.Dispose(); bitmapSourceEffect.Dispose(); d2dRenderTarget.Dispose(); inputStream.Dispose(); decoder.Dispose(); d2dContext.Dispose(); dwFactory.Dispose(); imagingFactory.Dispose(); d2dDevice.Dispose(); dxgiDevice.Dispose(); d3dDevice.Dispose(); defaultDevice.Dispose(); // show the result System.Diagnostics.Process.Start(outputPath); }
public MemoryStream RenderToPngStream(FrameworkElement fe) { var width = (int)Math.Ceiling(fe.ActualWidth); var height = (int)Math.Ceiling(fe.ActualHeight); // pixel format with transparency/alpha channel and RGB values premultiplied by alpha var pixelFormat = WIC.PixelFormat.Format32bppPRGBA; // pixel format without transparency, but one that works with Cleartype antialiasing //var pixelFormat = WicPixelFormat.Format32bppBGR; var wicBitmap = new WIC.Bitmap( this.WicFactory, width, height, pixelFormat, WIC.BitmapCreateCacheOption.CacheOnLoad); var renderTargetProperties = new D2D.RenderTargetProperties( D2D.RenderTargetType.Default, new D2D.PixelFormat(Format.R8G8B8A8_UNorm, D2D.AlphaMode.Premultiplied), //new D2DPixelFormat(Format.Unknown, AlphaMode.Unknown), // use this for non-alpha, cleartype antialiased text 0, 0, D2D.RenderTargetUsage.None, D2D.FeatureLevel.Level_DEFAULT); var renderTarget = new D2D.WicRenderTarget( this.D2DFactory, wicBitmap, renderTargetProperties) { //TextAntialiasMode = TextAntialiasMode.Cleartype // this only works with the pixel format with no alpha channel TextAntialiasMode = D2D.TextAntialiasMode.Grayscale // this is the best we can do for bitmaps with alpha channels }; Compose(renderTarget, fe); // TODO: There is no need to encode the bitmap to PNG - we could just copy the texture pixel buffer to a WriteableBitmap pixel buffer. var ms = new MemoryStream(); var stream = new WIC.WICStream( this.WicFactory, ms); var encoder = new WIC.PngBitmapEncoder(WicFactory); encoder.Initialize(stream); var frameEncoder = new WIC.BitmapFrameEncode(encoder); frameEncoder.Initialize(); frameEncoder.SetSize(width, height); var format = WIC.PixelFormat.Format32bppBGRA; //var format = WicPixelFormat.FormatDontCare; frameEncoder.SetPixelFormat(ref format); frameEncoder.WriteSource(wicBitmap); frameEncoder.Commit(); encoder.Commit(); frameEncoder.Dispose(); encoder.Dispose(); stream.Dispose(); ms.Position = 0; return ms; }