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 async Task<System.IO.MemoryStream> RenderLabelToStream( float imageWidth, float imageHeight, Color4 foregroundColor, Vector2 origin, TextLayout textLayout, float dpi = DEFAULT_DPI, SharpDX.DXGI.Format format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode alpha = AlphaMode.Premultiplied) { // Get stream var pngStream = new MemoryStream(); using (var renderTarget = RenderLabel( imageWidth, imageHeight, foregroundColor, origin, textLayout, dpi, format, alpha)) { pngStream.Position = 0; // Create a WIC outputstream using (var wicStream = new WICStream(FactoryImaging, pngStream)) { var size = renderTarget.PixelSize; // Initialize a Png encoder with this stream using (var wicBitmapEncoder = new PngBitmapEncoder(FactoryImaging, wicStream)) { // Create a Frame encoder using (var wicFrameEncoder = new BitmapFrameEncode(wicBitmapEncoder)) { wicFrameEncoder.Initialize(); // Create image encoder ImageEncoder wicImageEncoder; ImagingFactory2 factory2 = new ImagingFactory2(); wicImageEncoder = new ImageEncoder(factory2, D2DDevice); var imgParams = new ImageParameters(); imgParams.PixelFormat = new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied); imgParams.PixelHeight = (int)size.Height; imgParams.PixelWidth = (int)size.Width; wicImageEncoder.WriteFrame(renderTarget, wicFrameEncoder, imgParams); //// Commit changes wicFrameEncoder.Commit(); wicBitmapEncoder.Commit(); byte[] buffer = new byte[pngStream.Length]; pngStream.Position = 0; await pngStream.ReadAsync(buffer, 0, (int)pngStream.Length); } } } } return pngStream; }
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); }
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); }
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 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; }
/// <summary> /// 将 Direct2D 位图保存到文件中。 /// </summary> /// <param name="image">要保存的位图。</param> /// <param name="fileName">要保存的文件名。</param> public void SaveBitmapToFile(Bitmap image, string fileName) { using (ImagingFactory2 factory = new ImagingFactory2()) { using (WICStream stream = new WICStream(factory, fileName, NativeFileAccess.Write)) { using (BitmapEncoder encoder = new PngBitmapEncoder(factory)) { encoder.Initialize(stream); using (BitmapFrameEncode bitmapFrameEncode = new BitmapFrameEncode(encoder)) { bitmapFrameEncode.Initialize(); int width = image.PixelSize.Width; int height = image.PixelSize.Height; bitmapFrameEncode.SetSize(width, height); Guid wicPixelFormat = WICPixelFormat; bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat); using (ImageEncoder imageEncoder = new ImageEncoder(factory, this.d2DDevice)) { imageEncoder.WriteFrame(image, bitmapFrameEncode, new ImageParameters(D2PixelFormat, 96, 96, 0, 0, width, height)); bitmapFrameEncode.Commit(); encoder.Commit(); } } } } } }
public void Start() { if (ProcessStarted != null) ProcessStarted(); int index = 0; var rendererUtil = new RendererUtil(); // obtain file list var regionList = Directory.GetFiles(Path.Combine(worldLocation, "region"), "*.mca").ToList(); var regionEntries = new List<RegionEntry>(); foreach (string region in regionList) { try { // load the region using (RegionFile regionFile = RegionFile.OpenRegion(File.OpenRead(region))) { var renderedChunks = new List<ChunkEntry>(); if (RegionLoaded != null) RegionLoaded(regionFile); Debug.WriteLine("Rendering region"); DateTime sTime = DateTime.Now; #region Chunk render using (var renderTarget = new BitmapRenderTarget(rendererUtil.D2DDeviceContext, CompatibleRenderTargetOptions.None, new DrawingSizeF(16, 16), new DrawingSize(16, 16), new PixelFormat(Format.R8G8B8A8_UNorm, AlphaMode.Premultiplied))) { foreach (var anvilChunk in regionFile.Content.Select(chunk => new Anvil(chunk))) { ChunkEntry entry; RenderSegment(anvilChunk, renderTarget, out entry); renderedChunks.Add(entry); } } #endregion #region Region compositor using (var renderTarget = new BitmapRenderTarget(rendererUtil.D2DDeviceContext, CompatibleRenderTargetOptions.None, new DrawingSizeF(512, 512), new DrawingSize(512, 512), new PixelFormat(Format.R8G8B8A8_UNorm, AlphaMode.Premultiplied))) { renderTarget.BeginDraw(); renderTarget.Clear(Color.Transparent); // compose the images foreach (ChunkEntry chunk in renderedChunks) { int cxPos = chunk.XPos % 32; int czPos = chunk.ZPos % 32; if (cxPos < 0) cxPos = 32 + cxPos; if (czPos < 0) czPos = 32 + czPos; int xPos = cxPos * 16; int zPos = czPos * 16; renderTarget.Transform = Matrix3x2.Translation(xPos, zPos); renderTarget.DrawBitmap(chunk.RenderedChunk, 1, BitmapInterpolationMode.Linear); } // ReSharper disable PossibleNullReferenceException string[] info = Path.GetFileNameWithoutExtension(region).Split('.'); // ReSharper restore PossibleNullReferenceException regionEntries.Add(new RegionEntry { RenderedRegion = renderTarget.Bitmap, XPos = Convert.ToInt32(info[1]), ZPos = Convert.ToInt32(info[2]) }); renderTarget.EndDraw(); } #endregion Debug.WriteLine("Render time is: " + (DateTime.Now - sTime).Seconds + " seconds."); if (RegionRendered != null) RegionRendered(); #region Cleanup foreach (ChunkEntry chunk in renderedChunks) chunk.RenderedChunk.Dispose(); renderedChunks.Clear(); #endregion } } catch (Exception exception) { if (ProcessFailed != null) ProcessFailed(exception.Message + "\nAt:\n" + exception); } if (ProgressChanged != null) ProgressChanged(++index / (float)regionList.Count); } #region Extrema processor int xMin = 0; int zMin = 0; int xMax = 0; int zMax = 0; foreach (RegionEntry entry in regionEntries) { if (xMin > entry.XPos) xMin = entry.XPos; if (xMax < entry.XPos) xMax = entry.XPos; if (zMin > entry.ZPos) zMin = entry.ZPos; if (zMax < entry.ZPos) zMax = entry.ZPos; } int wSizeX = (xMax - xMin) * 512 + 512; int wSizeZ = (zMax - zMin) * 512 + 512; xMin = Math.Abs(xMin); zMin = Math.Abs(zMin); #endregion #region World compositor var ResultingBitmap = new Bitmap1(rendererUtil.D2DDeviceContext, new DrawingSize(wSizeX, wSizeZ), new BitmapProperties1 { BitmapOptions = BitmapOptions.Target, PixelFormat = new PixelFormat(Format.R8G8B8A8_UNorm, AlphaMode.Premultiplied) }); rendererUtil.D2DDeviceContext.Target = ResultingBitmap; rendererUtil.D2DDeviceContext.BeginDraw(); rendererUtil.D2DDeviceContext.Clear(Color.Transparent); foreach (RegionEntry entry in regionEntries) { int xPos = ((xMin + entry.XPos) * 512); int zPos = ((zMin + entry.ZPos) * 512); rendererUtil.D2DDeviceContext.Transform = Matrix3x2.Translation(xPos, zPos); rendererUtil.D2DDeviceContext.DrawBitmap(entry.RenderedRegion, 1, BitmapInterpolationMode.Linear); } rendererUtil.D2DDeviceContext.EndDraw(); #endregion #region File save FileStream file = File.OpenWrite(Path.GetFileName(worldLocation) + ".png"); var encoder = new PngBitmapEncoder(rendererUtil.ImagingFactory); encoder.Initialize(file); var frameEncode = new BitmapFrameEncode(encoder); frameEncode.Initialize(); var imageEncoder = new ImageEncoder(rendererUtil.ImagingFactory, rendererUtil.D2DDevice); imageEncoder.WriteFrame(ResultingBitmap, frameEncode, new ImageParameters( new PixelFormat(Format.R8G8B8A8_UNorm, AlphaMode.Premultiplied), 96, 96, 0, 0, wSizeX, wSizeZ)); frameEncode.Commit(); encoder.Commit(); #endregion #region Cleanup file.Close(); file.Dispose(); foreach (RegionEntry bitmap in regionEntries) { bitmap.RenderedRegion.Dispose(); } regionEntries.Clear(); rendererUtil.Dispose(); theBlocks.Dispose(); ResultingBitmap.Dispose(); #endregion if (ProcessComplete != null) ProcessComplete(); }