Пример #1
0
        private void UnloadResources()
        {
            m_compositeEffect.Dispose();
            m_affineTransformEffect.Dispose();
            m_ShadowFullScreen.Dispose();
            m_Shadow.Dispose();
            m_Bitmap1FullScreen.Dispose();
            m_Bitmap1.Dispose();
            fontFamily.Dispose();
            m_textFormat15.Dispose();
            m_textFormat10.Dispose();
            roundedRecInColor.Dispose();
            roundedRecOutColor.Dispose();
            m_textBrush.Dispose();

            if (m_TitleName != null)
            {
                m_TitleName.Dispose();
            }
            if (m_VideoBitmap != null)
            {
                m_VideoBitmap.Dispose();
            }
            if (m_CDGBitmap != null)
            {
                m_CDGBitmap.Dispose();
            }
        }
Пример #2
0
 public void ReleaseDeviceResources()
 {
     Bitmaps.Dispose();
     SwapChain.Dispose();
     _solidBrush.Dispose();
     RenderTarget.Dispose();
 }
Пример #3
0
 //清除内存
 public void Dispose()
 {
     target.Dispose();
     factory.Dispose();
     rBrush.Dispose();
     pBrush.Dispose();
 }
Пример #4
0
        private void OnWindowClosing(object sender, CancelEventArgs e)
        {
            ClosedEvent.WaitOne();

            _selectedColorBrush.Dispose();
            _spacingColorBrush.Dispose();
            _notMappedColorBrush.Dispose();
            _gridColorBrush.Dispose();
        }
Пример #5
0
        private void Update(bool forceUpdate = false)
        {
            if (isUpdated || forceUpdate)
            {
                isUpdated = false;

                strokeBrush?.Dispose();
                strokeBrush = new d2.SolidColorBrush(Renderer.Device, _stroke.ToColor4());

                strokeStyle?.Dispose();
                strokeStyle = new d2.StrokeStyle(Renderer.Factory, _strokeStyleProp);
            }
        }
Пример #6
0
        private void ResetBurshes(RenderContainer renderContainer)
        {
            _selectedColorBrush?.Dispose();
            _spacingColorBrush?.Dispose();
            _notMappedColorBrush?.Dispose();
            _gridColorBrush?.Dispose();

            RenderTarget target2D = renderContainer.BackBuffer.Target2D;

            _selectedColorBrush  = new SolidColorBrush(target2D, SelectedColor.ToColor4(), null);
            _spacingColorBrush   = new SolidColorBrush(target2D, SpacingColor.ToColor4(), null);
            _notMappedColorBrush = new SolidColorBrush(target2D, NotMappedColor.ToColor4(), null);
            _gridColorBrush      = new SolidColorBrush(target2D, GridColor.ToColor4(), null);
        }
Пример #7
0
        public void Dispose()
        {
            uiInitialized = false;

            uiTexture?.Dispose();
            uiEffect?.Dispose();

            target2d?.Dispose();
            uiPrimitive?.Dispose();

            textFormat?.Dispose();
            textFormatSmall?.Dispose();
            textBrush?.Dispose();
            blueBrush?.Dispose();
        }
Пример #8
0
        public void Dispose()
        {
            brush.Dispose();

            wrFactory.Dispose();
            target.Dispose();
            bb.Dispose();
            fac.Dispose();
            d2dDevice.Dispose();
            dxgiFactory2.Dispose();
            dxgiAdapter.Dispose();
            dxgiDevice2.Dispose();
            defDevice.Dispose();
            d3device.Dispose();
            swapChain.Dispose();
            d2dContext.Dispose();
        }
Пример #9
0
        public Result DrawGlyphRun(object clientDrawingContext, float baselineOriginX, float baselineOriginY, MeasuringMode measuringMode, GlyphRun glyphRun, GlyphRunDescription glyphRunDescription, ComObject clientDrawingEffect)
        {
            var pathGeometry = new PathGeometry(_d2DFactory);
            var geometrySink = pathGeometry.Open();

            var fontFace = glyphRun.FontFace;
            if (glyphRun.Indices.Length > 0)
                fontFace.GetGlyphRunOutline(glyphRun.FontSize, glyphRun.Indices, glyphRun.Advances, glyphRun.Offsets, glyphRun.IsSideways, glyphRun.BidiLevel % 2 != 0, geometrySink);
            geometrySink.Close();
            geometrySink.Dispose();
            fontFace.Dispose();

            var matrix = new Matrix3x2()
            {
                M11 = 1,
                M12 = 0,
                M21 = 0,
                M22 = 1,
                M31 = baselineOriginX,
                M32 = baselineOriginY
            };

            var transformedGeometry = new TransformedGeometry(_d2DFactory, pathGeometry, matrix);

            var  brushColor = (Color4)Color.Black;

            if (clientDrawingEffect != null && clientDrawingEffect is ColorDrawingEffect)
                brushColor = (clientDrawingEffect as ColorDrawingEffect).Color;

            var brush = new SolidColorBrush(_renderTarget, brushColor);
            
            _renderTarget.DrawGeometry(transformedGeometry, brush);
            _renderTarget.FillGeometry(transformedGeometry, brush);

            pathGeometry.Dispose();
            transformedGeometry.Dispose();
            brush.Dispose();

            return SharpDX.Result.Ok;
        }
Пример #10
0
        protected void DisposeDirectXResources()
        {
            PreDestroyDirectXResources();
            SharedBrush.Dispose();
            BackgroundBrush.Dispose();
            ForegroundBrush.Dispose();
            CorrectColorBrush.Dispose();
            WrongColorBrush.Dispose();

            InputTextFormat.Dispose();
            ButtonLabelTextFormat.Dispose();
            SubtitleTextFormat.Dispose();
            CueTextFormat.Dispose();

            DwFactory.Dispose();
            RenderTarget.Dispose();
            RenderTargetView.Dispose();
            D2DFactory.Dispose();
            SwapChain.Dispose();
            D3DDeviceContext.Dispose();
            D3DDevice.Dispose();
        }
        private void Update(bool forceUpdate = false)
        {
            if (isUpdated || forceUpdate)
            {
                isUpdated = false;

                geometry?.Dispose();
                geometry = new d2.PathGeometry(Renderer.Factory);

                var s = geometry.Open();

                s.BeginFigure(Points[0], d2.FigureBegin.Filled);
                s.AddLines(Points.Select(v2 => new mi.RawVector2(v2.X, v2.Y)).ToArray());
                s.EndFigure(d2.FigureEnd.Closed);
                s.Close();

                strokeBrush?.Dispose();
                strokeBrush = new d2.SolidColorBrush(Renderer.Device, _stroke.ToColor4());

                fillBrush?.Dispose();
                fillBrush = new d2.SolidColorBrush(Renderer.Device, _fill.ToColor4());
            }
        }
Пример #12
0
        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);
        }
Пример #13
0
        protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
        {
            // This sample should be used along side the help guide educational resource on this topic:
            // http://www.ninjatrader.com/support/helpGuides/nt8/en-us/?using_sharpdx_for_custom_chart_rendering.htm

            // Default plotting in base class. Uncomment if indicators holds at least one plot
            // in this case we would expect NOT to see the SMA plot we have as well in this sample script
            //base.OnRender(chartControl, chartScale);

            // 1.1 - SharpDX Vectors and Charting RenderTarget Coordinates

            // The SharpDX SDK uses "Vector2" objects to describe a two-dimensional point of a device (X and Y coordinates)
            SharpDX.Vector2 startPoint;
            SharpDX.Vector2 endPoint;

            // For our custom script, we need a way to determine the Chart's RenderTarget coordinates to draw our custom shapes
            // This info can be found within the NinjaTrader.Gui.ChartPanel class.
            // You can also use various chartScale and chartControl members to calculate values relative to time and price
            // However, those concepts will not be discussed or used in this sample
            // Notes:  RenderTarget is always the full ChartPanel, so we need to be mindful which sub-ChartPanel we're dealing with
            // Always use ChartPanel X, Y, W, H - as chartScale and chartControl properties WPF units, so they can be drastically different depending on DPI set
            startPoint = new SharpDX.Vector2(ChartPanel.X, ChartPanel.Y);
            endPoint   = new SharpDX.Vector2(ChartPanel.X + ChartPanel.W, ChartPanel.Y + ChartPanel.H);

            // These Vector2 objects are equivalent with WPF System.Windows.Point and can be used interchangeably depending on your requirements
            // For convenience, NinjaTrader provides a "ToVector2()" extension method to convert from WPF Points to SharpDX.Vector2
            SharpDX.Vector2 startPoint1 = new System.Windows.Point(ChartPanel.X, ChartPanel.Y + ChartPanel.H).ToVector2();
            SharpDX.Vector2 endPoint1   = new System.Windows.Point(ChartPanel.X + ChartPanel.W, ChartPanel.Y).ToVector2();

            // SharpDX.Vector2 objects contain X/Y properties which are helpful to recalculate new properties based on the initial vector
            float width  = endPoint.X - startPoint.X;
            float height = endPoint.Y - startPoint.Y;

            // Or you can recalculate a new vector from existing vector objects
            SharpDX.Vector2 center = (startPoint + endPoint) / 2;

            // Tip: This check is simply added to prevent the Indicator dialog menu from opening as a user clicks on the chart
            // The default behavior is to open the Indicator dialog menu if a user double clicks on the indicator
            // (i.e, the indicator falls within the RenderTarget "hit testing")
            // You can remove this check if you want the default behavior implemented
            if (!IsInHitTest)
            {
                // 1.2 - SharpDX Brush Resources

                // RenderTarget commands must use a special brush resource defined in the SharpDX.Direct2D1 namespace
                // These resources exist just like you will find in the WPF/Windows.System.Media namespace
                // such as SolidColorBrushes, LienarGraidentBrushes, RadialGradientBrushes, etc.
                // To begin, we will start with the most basic "Brush" type
                // Warning:  Brush objects must be disposed of after they have been used
                SharpDX.Direct2D1.Brush areaBrushDx;
                SharpDX.Direct2D1.Brush smallAreaBrushDx;
                SharpDX.Direct2D1.Brush textBrushDx;

                // for convenience, you can simply convert a WPF Brush to a DXBrush using the ToDxBrush() extension method provided by NinjaTrader
                // This is a common approach if you have a Brush property created e.g., on the UI you wish to use in custom rendering routines
                areaBrushDx      = areaBrush.ToDxBrush(RenderTarget);
                smallAreaBrushDx = smallAreaBrush.ToDxBrush(RenderTarget);
                textBrushDx      = textBrush.ToDxBrush(RenderTarget);

                // However - it should be noted that this conversion process can be rather expensive
                // If you have many brushes being created, and are not tied to WPF resources
                // You should rather favor creating the SharpDX Brush directly:
                // Warning:  SolidColorBrush objects must be disposed of after they have been used
                SharpDX.Direct2D1.SolidColorBrush customDXBrush = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget,
                                                                                                        SharpDX.Color.DodgerBlue);

                // 1.3 - Using The RenderTarget
                // before executing chart commands, you have the ability to describe how the RenderTarget should render
                // for example, we can store the existing RenderTarget AntialiasMode mode
                // then update the AntialiasMode to be the quality of non-text primitives are rendered
                SharpDX.Direct2D1.AntialiasMode oldAntialiasMode = RenderTarget.AntialiasMode;
                RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.Aliased;

                // Note: The code above stores the oldAntialiasMode as a best practices
                // i.e., if you plan on changing a property of the RenderTarget, you should plan to set it back
                // This is to make sure your requirements to no interfere with the function of another script
                // Additionally smoothing has some performance impacts

                // Once you have defined all the necessary requirements for you object
                //  You can execute a command on the RenderTarget to draw specific shapes
                // e.g., we can now use the RenderTarget's DrawLine() command to render a line
                // using the start/end points and areaBrushDx objects defined before
                RenderTarget.DrawLine(startPoint, endPoint, areaBrushDx, 4);

                // Since rendering occurs in a sequential fashion, after you have executed a command
                // you can switch a property of the RenderTarget to meet other requirements
                // For example, we can draw a second line now which uses a different AntialiasMode
                // and the changes render on the chart for both lines from the time they received commands
                RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive;
                RenderTarget.DrawLine(startPoint1, endPoint1, areaBrushDx, 4);

                // 1.4 - Rendering Custom Shapes

                // SharpDX namespace consists of several shapes you can use to draw objects more complicated than lines
                // For example, we can use the RectangleF object to draw a rectangle that covers the entire chart area
                SharpDX.RectangleF rect = new SharpDX.RectangleF(startPoint.X, startPoint.Y, width, height);

                // The RenderTarget consists of two commands related to Rectangles.
                // The FillRectangle() method is used to "Paint" the area of a Rectangle
                RenderTarget.FillRectangle(rect, areaBrushDx);

                // and DrawRectangle() is used to "Paint" the outline of a Rectangle
                RenderTarget.DrawRectangle(rect, customDXBrush, 2);

                // Another example is an ellipse which can be used to draw circles
                // The ellipse center point can be used from the Vectors calculated earlier
                // The width and height an absolute 100 device pixels
                // To ensure that pixel coordinates work across all DPI devices, we use the NinjaTrader ChartingExteions methods
                // Which will convert the "100" value from WPF pixels to Device Pixels both vertically and horizontally
                int ellipseRadiusY = ChartingExtensions.ConvertToVerticalPixels(100, ChartControl.PresentationSource);
                int ellipseRadiusX = ChartingExtensions.ConvertToHorizontalPixels(100, ChartControl.PresentationSource);

                SharpDX.Direct2D1.Ellipse ellipse = new SharpDX.Direct2D1.Ellipse(center, ellipseRadiusX, ellipseRadiusY);

                // 1.5 - Complex Brush Types and Shapes
                // For this ellipse, we can use one of the more complex brush types "RadialGradientBrush"
                // Warning:  RadialGradientBrush objects must be disposed of after they have been used
                SharpDX.Direct2D1.RadialGradientBrush radialGradientBrush;

                // However creating a RadialGradientBrush requires a few more properties than SolidColorBrush
                // First, you need to define the array gradient stops the brush will eventually use
                SharpDX.Direct2D1.GradientStop[] gradientStops = new SharpDX.Direct2D1.GradientStop[2];

                // With the gradientStops array, we can describe the color and position of the individual gradients
                gradientStops[0].Color    = SharpDX.Color.Goldenrod;
                gradientStops[0].Position = 0.0f;
                gradientStops[1].Color    = SharpDX.Color.SeaGreen;
                gradientStops[1].Position = 1.0f;

                // then declare a GradientStopCollection from our render target that uses the gradientStops array defined just before
                // Warning:  GradientStopCollection objects must be disposed of after they have been used
                SharpDX.Direct2D1.GradientStopCollection gradientStopCollection =
                    new SharpDX.Direct2D1.GradientStopCollection(RenderTarget, gradientStops);

                // we also need to tell our RadialGradientBrush to match the size and shape of the ellipse that we will be drawing
                // for convenience, SharpDX provides a RadialGradientBrushProperties structure to help define these properties
                SharpDX.Direct2D1.RadialGradientBrushProperties radialGradientBrushProperties =
                    new SharpDX.Direct2D1.RadialGradientBrushProperties
                {
                    GradientOriginOffset = new SharpDX.Vector2(0, 0),
                    Center  = ellipse.Point,
                    RadiusX = ellipse.RadiusY,
                    RadiusY = ellipse.RadiusY
                };

                // we now have everything we need to create a radial gradient brush
                radialGradientBrush = new SharpDX.Direct2D1.RadialGradientBrush(RenderTarget, radialGradientBrushProperties,
                                                                                gradientStopCollection);

                // Finally, we can use this radialGradientBrush to "Paint" the area of the ellipse
                RenderTarget.FillEllipse(ellipse, radialGradientBrush);

                // 1.6 - Simple Text Rendering

                // For rendering custom text to the Chart, there are a few ways you can approach depending on your requirements
                // The most straight forward way is to "borrow" the existing chartControl font provided as a "SimpleFont" class
                // Using the chartControl LabelFont, your custom object will also change to the user defined properties allowing
                // your object to match different fonts if defined by user.

                // The code below will use the chartControl Properties Label Font if it exists,
                // or fall back to a default property if it cannot obtain that value
                NinjaTrader.Gui.Tools.SimpleFont simpleFont = chartControl.Properties.LabelFont ?? new NinjaTrader.Gui.Tools.SimpleFont("Arial", 12);

                // the advantage of using a SimpleFont is they are not only very easy to describe
                // but there is also a convenience method which can be used to convert the SimpleFont to a SharpDX.DirectWrite.TextFormat used to render to the chart
                // Warning:  TextFormat objects must be disposed of after they have been used
                SharpDX.DirectWrite.TextFormat textFormat1 = simpleFont.ToDirectWriteTextFormat();

                // Once you have the format of the font, you need to describe how the font needs to be laid out
                // Here we will create a new Vector2() which draws the font according to the to top left corner of the chart (offset by a few pixels)
                SharpDX.Vector2 upperTextPoint = new SharpDX.Vector2(ChartPanel.X + 10, ChartPanel.Y + 20);
                // Warning:  TextLayout objects must be disposed of after they have been used
                SharpDX.DirectWrite.TextLayout textLayout1 =
                    new SharpDX.DirectWrite.TextLayout(NinjaTrader.Core.Globals.DirectWriteFactory,
                                                       NinjaTrader.Custom.Resource.SampleCustomPlotUpperLeftCorner, textFormat1, ChartPanel.X + ChartPanel.W,
                                                       textFormat1.FontSize);

                // With the format and layout of the text completed, we can now render the font to the chart
                RenderTarget.DrawTextLayout(upperTextPoint, textLayout1, textBrushDx,
                                            SharpDX.Direct2D1.DrawTextOptions.NoSnap);

                // 1.7 - Advanced Text Rendering

                // Font formatting and text layouts can get as complex as you need them to be
                // This example shows how to use a complete custom font unrelated to the existing user-defined chart control settings
                // Warning:  TextLayout and TextFormat objects must be disposed of after they have been used
                SharpDX.DirectWrite.TextFormat textFormat2 =
                    new SharpDX.DirectWrite.TextFormat(NinjaTrader.Core.Globals.DirectWriteFactory, "Century Gothic", FontWeight.Bold,
                                                       FontStyle.Italic, 32f);
                SharpDX.DirectWrite.TextLayout textLayout2 =
                    new SharpDX.DirectWrite.TextLayout(NinjaTrader.Core.Globals.DirectWriteFactory,
                                                       NinjaTrader.Custom.Resource.SampleCustomPlotLowerRightCorner, textFormat2, 400, textFormat1.FontSize);

                // the textLayout object provides a way to measure the described font through a "Metrics" object
                // This allows you to create new vectors on the chart which are entirely dependent on the "text" that is being rendered
                // For example, we can create a rectangle that surrounds our font based off the textLayout which would dynamically change if the text used in the layout changed dynamically
                SharpDX.Vector2 lowerTextPoint = new SharpDX.Vector2(ChartPanel.W - textLayout2.Metrics.Width - 5,
                                                                     ChartPanel.Y + (ChartPanel.H - textLayout2.Metrics.Height));
                SharpDX.RectangleF rect1 = new SharpDX.RectangleF(lowerTextPoint.X, lowerTextPoint.Y, textLayout2.Metrics.Width,
                                                                  textLayout2.Metrics.Height);

                // We can draw the Rectangle based on the TextLayout used above
                RenderTarget.FillRectangle(rect1, smallAreaBrushDx);
                RenderTarget.DrawRectangle(rect1, smallAreaBrushDx, 2);

                // And render the advanced text layout using the DrawTextLayout() method
                // Note:  When drawing the same text repeatedly, using the DrawTextLayout() method is more efficient than using the DrawText()
                // because the text doesn't need to be formatted and the layout processed with each call
                RenderTarget.DrawTextLayout(lowerTextPoint, textLayout2, textBrushDx, SharpDX.Direct2D1.DrawTextOptions.NoSnap);

                // 1.8 - Cleanup
                // This concludes all of the rendering concepts used in the sample
                // However - there are some final clean up processes we should always provided before we are done

                // If changed, do not forget to set the AntialiasMode back to the default value as described above as a best practice
                RenderTarget.AntialiasMode = oldAntialiasMode;

                // We also need to make sure to dispose of every device dependent resource on each render pass
                // Failure to dispose of these resources will eventually result in unnecessary amounts of memory being used on the chart
                // Although the effects might not be obvious as first, if you see issues related to memory increasing over time
                // Objects such as these should be inspected first
                areaBrushDx.Dispose();
                customDXBrush.Dispose();
                gradientStopCollection.Dispose();
                radialGradientBrush.Dispose();
                smallAreaBrushDx.Dispose();
                textBrushDx.Dispose();
                textFormat1.Dispose();
                textFormat2.Dispose();
                textLayout1.Dispose();
                textLayout2.Dispose();
            }
        }
        public Result DrawUnderline(object clientDrawingContext, float baselineOriginX, float baselineOriginY, ref Underline underline, ComObject clientDrawingEffect)
        {
            var rect = new SharpDX.RectangleF(0, underline.Offset, underline.Width, underline.Offset + underline.Thickness);
            var rectangleGeometry = new RectangleGeometry(_d2DFactory, rect);
            var matrix = new Matrix3x2()
            {
                M11 = 1,
                M12 = 0,
                M21 = 0,
                M22 = 1,
                M31 = baselineOriginX,
                M32 = baselineOriginY
            };
            var transformedGeometry = new TransformedGeometry(_d2DFactory, rectangleGeometry, matrix);

            var brushColor = new Color4(1, 0, 0, 0);
            if (clientDrawingEffect != null && clientDrawingEffect is ColorDrawingEffect)
                brushColor = (clientDrawingEffect as ColorDrawingEffect).Color;

            var brush = new SolidColorBrush(_renderTarget, brushColor);

            _renderTarget.DrawGeometry(transformedGeometry, brush);
            _renderTarget.FillGeometry(transformedGeometry, brush);

            rectangleGeometry.Dispose();
            transformedGeometry.Dispose();
            brush.Dispose();

            return SharpDX.Result.Ok;
        }
Пример #15
0
        public void EndDraw()
        {
            if (_sbObj.IsFinished || _timing.Offset < _sbObj.MinTime || _sbObj.F.RealTime <= 0)
            {
                if (_flag)
                {
                    _sbObj.ResetRealTime();
                    _flag = false;
                }
                return;
            }

            _flag = true;
            if (_sbObj is AnimatedObject ani && _timing.Offset >= ani.MinTime && _timing.Offset <= ani.MaxTime)
            {
                int imgIndex;
                if (ani.Loop)
                {
                    imgIndex = (int)((_timing.Offset - ani.MinTime) / ani.Delay % ani.Times);
                }
                else
                {
                    imgIndex = (int)((_timing.Offset - ani.MinTime) / ani.Delay);
                    if (imgIndex >= ani.Times)
                    {
                        imgIndex = ani.Times - 1;
                    }
                }

                if (imgIndex != ani.PrevIndex)
                {
                    ani.PrevIndex = imgIndex;
                    ani.Texture   = ani.TextureList[imgIndex];
                }
            }


            var translateMtx    = Matrix3x2.Translation(-_sbObj.X.RealTime, -_sbObj.Y.RealTime);
            var scaleMtx        = Matrix3x2.Scaling((_sbObj.UseH ? -1 : 1) * _sbObj.Vx.RealTime, (_sbObj.UseV ? -1 : 1) * _sbObj.Vy.RealTime);
            var rotateMtx       = Matrix3x2.Rotation(_sbObj.Rad.RealTime);
            var negTranslateMtx = Matrix3x2.Translation(_sbObj.X.RealTime, _sbObj.Y.RealTime);

            _target.Transform = translateMtx * scaleMtx * rotateMtx * negTranslateMtx;

            float rectL = _sbObj.Rect.RealTime.Left - _sbObj.OriginOffsetX - (_sbObj.UseH ? 2 * (_sbObj.Width / 2 - _sbObj.OriginOffsetX) : 0);
            float rectT = _sbObj.Rect.RealTime.Top - _sbObj.OriginOffsetY - (_sbObj.UseV ? 2 * (_sbObj.Height / 2 - _sbObj.OriginOffsetY) : 0);
            float rectW = _sbObj.Rect.RealTime.Right - _sbObj.Rect.RealTime.Left;
            float rectH = _sbObj.Rect.RealTime.Bottom - _sbObj.Rect.RealTime.Top;

            var realRect = new RectangleF(rectL, rectT, rectW, rectH);

            if (_sbObj.Texture != null)
            {
                if (_sbObj.R.RealTime != 255 || _sbObj.G.RealTime != 255 || _sbObj.B.RealTime != 255)
                {
                    //JUST FAKE THING
                    var sb = new D2D.SolidColorBrush(_target,
                                                     new Mathe.RawColor4(_sbObj.R.RealTime / 255f, _sbObj.G.RealTime / 255f,
                                                                         _sbObj.B.RealTime / 255f, _sbObj.F.RealTime));
                    _target.FillOpacityMask(_sbObj.Texture, sb, D2D.OpacityMaskContent.Graphics, realRect, null);
                    sb.Dispose();
                    sb = null;
                }
                else
                {
                    _target.DrawBitmap(_sbObj.Texture, realRect, _sbObj.F.RealTime, D2D.BitmapInterpolationMode.Linear);
                }
            }

#if DEBUG
            //_target.DrawRectangle(realRect, _redBrush, 1);
#endif
            _target.Transform = new Matrix3x2(1, 0, 0, 1, 0, 0);
        }
 public override void Dispose()
 {
     tFormat?.Dispose();
     foregroundBrush?.Dispose();
     Font?.Dispose();
 }
Пример #17
0
 public void Destroy() => _brush.Dispose();
Пример #18
0
        internal CCTexture2D CreateTextSprite(string text, CCFontDefinition textDefinition)
        {
            if (string.IsNullOrEmpty(text))
                return new CCTexture2D();

            int imageWidth;
            int imageHeight;
            var textDef = textDefinition;
            var contentScaleFactorWidth = CCLabel.DefaultTexelToContentSizeRatios.Width;
            var contentScaleFactorHeight = CCLabel.DefaultTexelToContentSizeRatios.Height;
            textDef.FontSize *= contentScaleFactorWidth;
            textDef.Dimensions.Width *= contentScaleFactorWidth;
            textDef.Dimensions.Height *= contentScaleFactorHeight;

            var font = CreateFont(textDef.FontName, textDef.FontSize);
            if (font == null)
            {
                CCLog.Log("Can not create font {0} with size {1}.", textDef.FontName, textDef.FontSize);
                return new CCTexture2D();
            }


            var _currentFontSizeEm = textDef.FontSize;
            var _currentDIP = ConvertPointSizeToDIP(_currentFontSizeEm);

            // color
            var foregroundColor = Color4.White;

            // alignment
            var horizontalAlignment = textDef.Alignment;
            var verticleAlignement = textDef.LineAlignment;

            var textAlign = (CCTextAlignment.Right == horizontalAlignment) ? TextAlignment.Trailing
                : (CCTextAlignment.Center == horizontalAlignment) ? TextAlignment.Center
                : TextAlignment.Leading;

            var paragraphAlign = (CCVerticalTextAlignment.Bottom == vertAlignment) ? ParagraphAlignment.Far
                : (CCVerticalTextAlignment.Center == vertAlignment) ? ParagraphAlignment.Center
                : ParagraphAlignment.Near;

            // LineBreak
            var lineBreak = (CCLabelLineBreak.Character == textDef.LineBreak) ? WordWrapping.Wrap
                : (CCLabelLineBreak.Word == textDef.LineBreak) ? WordWrapping.Wrap
                : WordWrapping.NoWrap;

            // LineBreak
            // TODO: Find a way to specify the type of line breaking if possible.

            var dimensions = new CCSize(textDef.Dimensions.Width, textDef.Dimensions.Height);

            var layoutAvailable = true;
            if (dimensions.Width <= 0)
            {
                dimensions.Width = 8388608;
                layoutAvailable = false;
            }

            if (dimensions.Height <= 0)
            {
                dimensions.Height = 8388608;
                layoutAvailable = false;
            }

            var fontName = font.FontFamily.FamilyNames.GetString(0);
            var textFormat = new TextFormat(FactoryDWrite, fontName,
                _currentFontCollection, FontWeight.Regular, FontStyle.Normal, FontStretch.Normal, _currentDIP);

            textFormat.TextAlignment = textAlign;
            textFormat.ParagraphAlignment = paragraphAlign;

            var textLayout = new TextLayout(FactoryDWrite, text, textFormat, dimensions.Width, dimensions.Height);

            var boundingRect = new RectangleF();

            // Loop through all the lines so we can find our drawing offsets
            var textMetrics = textLayout.Metrics;
            var lineCount = textMetrics.LineCount;

            // early out if something went wrong somewhere and nothing is to be drawn
            if (lineCount == 0)
                return new CCTexture2D();

            // Fill out the bounding rect width and height so we can calculate the yOffset later if needed
            boundingRect.X = 0; 
            boundingRect.Y = 0; 
            boundingRect.Width = textMetrics.Width;
            boundingRect.Height = textMetrics.Height;

            if (!layoutAvailable)
            {
                if (dimensions.Width == 8388608)
                {
                    dimensions.Width = boundingRect.Width;
                }
                if (dimensions.Height == 8388608)
                {
                    dimensions.Height = boundingRect.Height;
                }
            }

            imageWidth = (int)dimensions.Width;
            imageHeight = (int)dimensions.Height;

            // Recreate our layout based on calculated dimensions so that we can draw the text correctly
            // in our image when Alignment is not Left.
            if (textAlign != TextAlignment.Leading)
            {
                textLayout.MaxWidth = dimensions.Width;
                textLayout.MaxHeight = dimensions.Height;
            }

            // Line alignment
            var yOffset = (CCVerticalTextAlignment.Bottom == verticleAlignement
                || boundingRect.Bottom >= dimensions.Height) ? dimensions.Height - boundingRect.Bottom  // align to bottom
                : (CCVerticalTextAlignment.Top == verticleAlignement) ? 0                    // align to top
                : (imageHeight - boundingRect.Bottom) * 0.5f;                                   // align to center


            SharpDX.WIC.Bitmap sharpBitmap = null;
            WicRenderTarget sharpRenderTarget = null;
            SolidColorBrush solidBrush = null;

            try
            {
                // Select our pixel format
                var pixelFormat = SharpDX.WIC.PixelFormat.Format32bppPRGBA;

                // create our backing bitmap
                sharpBitmap = new SharpDX.WIC.Bitmap(FactoryImaging, imageWidth, imageHeight, pixelFormat, BitmapCreateCacheOption.CacheOnLoad);

                // Create the render target that we will draw to
                sharpRenderTarget = new WicRenderTarget(Factory2D, sharpBitmap, new RenderTargetProperties());
                // Create our brush to actually draw with
                solidBrush = new SolidColorBrush(sharpRenderTarget, foregroundColor);

                // Begin the drawing
                sharpRenderTarget.BeginDraw();

                if (textDefinition.isShouldAntialias)
                    sharpRenderTarget.AntialiasMode = AntialiasMode.Aliased;

                // Clear it
                sharpRenderTarget.Clear(TransparentColor);

                // Draw the text to the bitmap
                sharpRenderTarget.DrawTextLayout(new Vector2(boundingRect.X, yOffset), textLayout, solidBrush);

                // End our drawing which will commit the rendertarget to the bitmap
                sharpRenderTarget.EndDraw();

                // Debugging purposes
                //var s = "Label4";
                //SaveToFile(@"C:\Xamarin\" + s + ".png", _bitmap, _renderTarget);

                // The following code creates a .png stream in memory of our Bitmap and uses it to create our Textue2D
                Texture2D tex = null;

                using (var memStream = new MemoryStream())
                {
                    using (var encoder = new PngBitmapEncoder(FactoryImaging, memStream))
                    using (var frameEncoder = new BitmapFrameEncode(encoder))
                    {
                        frameEncoder.Initialize();
                        frameEncoder.WriteSource(sharpBitmap);
                        frameEncoder.Commit();
                        encoder.Commit();
                    }
                    // Create the Texture2D from the png stream
                    tex = Texture2D.FromStream(CCDrawManager.SharedDrawManager.XnaGraphicsDevice, memStream);
                }

                // Return our new CCTexture2D created from the Texture2D which will have our text drawn on it.
                return new CCTexture2D(tex);
            }
            catch (Exception exc)
            {
                CCLog.Log("CCLabel-Windows: Unable to create the backing image of our text.  Message: {0}", exc.StackTrace);
            }
            finally
            {
                if (sharpBitmap != null)
                {
                    sharpBitmap.Dispose();
                    sharpBitmap = null;
                }

                if (sharpRenderTarget != null)
                {
                    sharpRenderTarget.Dispose();
                    sharpRenderTarget = null;
                }

                if (solidBrush != null)
                {
                    solidBrush.Dispose();
                    solidBrush = null;
                }

                if (textFormat != null)
                {
                    textFormat.Dispose();
                    textFormat = null;
                }

                if (textLayout != null)
                {
                    textLayout.Dispose();
                    textLayout = null;
                }
            }

            // If we have reached here then something has gone wrong.
            return new CCTexture2D();
        }
Пример #19
0
        public Result DrawStrikethrough(object clientDrawingContext, float baselineOriginX, float baselineOriginY, ref Strikethrough strikethrough, ComObject clientDrawingEffect)
        {
            var rect = new SharpDX.RectangleF(0, strikethrough.Offset, strikethrough.Width, strikethrough.Offset + strikethrough.Thickness);
            var rectangleGeometry = new RectangleGeometry(_d2DFactory, rect);
            var matrix = new Matrix3x2()
            {
                M11 = 1,
                M12 = 0,
                M21 = 0,
                M22 = 1,
                M31 = baselineOriginX,
                M32 = baselineOriginY
            };
            var transformedGeometry = new TransformedGeometry(_d2DFactory, rectangleGeometry, matrix);
            
            var  brushColor = (Color4)Color.Black;

            if (clientDrawingEffect != null && clientDrawingEffect is ColorDrawingEffect)
                brushColor = (Color4)(clientDrawingEffect as ColorDrawingEffect).Color;

            var brush = new SolidColorBrush(_renderTarget, brushColor);

            _renderTarget.DrawGeometry(transformedGeometry, brush);
            _renderTarget.FillGeometry(transformedGeometry, brush);

            rectangleGeometry.Dispose();
            transformedGeometry.Dispose();
            brush.Dispose();

            return Result.Ok;
        }
Пример #20
0
        public void DisplayName(string name)
        {
            var brush = new SolidColorBrush(renderTarget, Color4.White);
            var layoutRect = new SharpDX.RectangleF(0, 0, bounds.Width, bounds.Height);

            renderTarget.BeginDraw();
            renderTarget.Clear(Color4.Black);
            renderTarget.DrawRectangle(new SharpDX.RectangleF(0, 0, bounds.Width, bounds.Height), brush, 10f);
            renderTarget.DrawText(name, textFormat, layoutRect, solidColorBrush);

            //int nx = 4;
            //int ny = 4;
            //for (int i = 0; i < nx - 1; i++)
            //    for (int j = 0; j < ny - 1; j++)
            //    {
            //        float x = (float)bounds.Width / (float)nx * (i + 1);
            //        float y = (float)bounds.Height / (float)ny * (j + 1);

            //        const int w = 10;
            //        renderTarget.DrawLine(new Vector2(x - w, y), new Vector2(x + w, y), brush, 1);
            //        renderTarget.DrawLine(new Vector2(x, y - w), new Vector2(x, y + w), brush, 1);
            //    }

            int nx = 4;
            int ny = 4;
            for (int i = 0; i < nx - 1; i++)
            {
                float x = (float)bounds.Width / (float)nx * (i + 1);
                renderTarget.DrawLine(new Vector2(x, 0), new Vector2(x, bounds.Height), brush, 1);
            }
            for (int i = 0; i < ny - 1; i++)
            {
                float y = (float)bounds.Height / (float)ny * (i + 1);
                renderTarget.DrawLine(new Vector2(0, y), new Vector2(bounds.Width, y), brush, 1);
            }
            renderTarget.EndDraw();

            brush.Dispose();
        }
Пример #21
0
        public override void OnRender(ChartControl chartControl, ChartScale chartScale, ChartBars chartBars)
        {
            Bars bars = chartBars.Bars;

            if (chartBars.FromIndex > 0)
            {
                chartBars.FromIndex--;
            }

            SharpDX.Direct2D1.PathGeometry lineGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory);
            AntialiasMode oldAliasMode = RenderTarget.AntialiasMode;
            GeometrySink  sink         = lineGeometry.Open();

            sink.BeginFigure(new Vector2(chartControl.GetXByBarIndex(chartBars, chartBars.FromIndex > -1 ? chartBars.FromIndex : 0), chartScale.GetYByValue(bars.GetClose(chartBars.FromIndex > -1 ? chartBars.FromIndex : 0))), FigureBegin.Filled);

            for (int idx = chartBars.FromIndex + 1; idx <= chartBars.ToIndex; idx++)
            {
                double closeValue = bars.GetClose(idx);
                float  close      = chartScale.GetYByValue(closeValue);
                float  x          = chartControl.GetXByBarIndex(chartBars, idx);
                sink.AddLine(new Vector2(x, close));
            }

            sink.EndFigure(FigureEnd.Open);
            sink.Close();
            RenderTarget.AntialiasMode = AntialiasMode.PerPrimitive;
            RenderTarget.DrawGeometry(lineGeometry, UpBrushDX, (float)Math.Max(1, chartBars.Properties.ChartStyle.BarWidth));
            lineGeometry.Dispose();

            SharpDX.Direct2D1.SolidColorBrush fillOutline  = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget, SharpDX.Color.Transparent);
            SharpDX.Direct2D1.PathGeometry    fillGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory);
            GeometrySink fillSink = fillGeometry.Open();

            fillSink.BeginFigure(new Vector2(chartControl.GetXByBarIndex(chartBars, chartBars.FromIndex > -1 ? chartBars.FromIndex : 0), chartScale.GetYByValue(chartScale.MinValue)), FigureBegin.Filled);
            float fillx = float.NaN;

            for (int idx = chartBars.FromIndex; idx <= chartBars.ToIndex; idx++)
            {
                double closeValue = bars.GetClose(idx);
                float  close      = chartScale.GetYByValue(closeValue);
                fillx = chartControl.GetXByBarIndex(chartBars, idx);
                fillSink.AddLine(new Vector2(fillx, close));
            }
            if (!double.IsNaN(fillx))
            {
                fillSink.AddLine(new Vector2(fillx, chartScale.GetYByValue(chartScale.MinValue)));
            }

            fillSink.EndFigure(FigureEnd.Open);
            fillSink.Close();
            DownBrushDX.Opacity = Opacity / 100f;
            if (!(DownBrushDX is SharpDX.Direct2D1.SolidColorBrush))
            {
                TransformBrush(DownBrushDX, new RectangleF(0, 0, (float)chartScale.Width, (float)chartScale.Height));
            }
            RenderTarget.FillGeometry(fillGeometry, DownBrushDX);
            RenderTarget.DrawGeometry(fillGeometry, fillOutline, (float)chartBars.Properties.ChartStyle.BarWidth);
            fillOutline.Dispose();
            RenderTarget.AntialiasMode = oldAliasMode;
            fillGeometry.Dispose();
        }
Пример #22
0
        public void Run()
        {
            var form = new RenderForm("2d and 3d combined...it's like magic");
            form.KeyDown += (sender, args) => { if (args.KeyCode == Keys.Escape) form.Close(); };

            // DirectX DXGI 1.1 factory
            var factory1 = new Factory1();

            // The 1st graphics adapter
            var adapter1 = factory1.GetAdapter1(0);

            // ---------------------------------------------------------------------------------------------
            // Setup direct 3d version 11. It's context will be used to combine the two elements
            // ---------------------------------------------------------------------------------------------

            var description = new SwapChainDescription
                {
                    BufferCount = 1,
                    ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
                    IsWindowed = true,
                    OutputHandle = form.Handle,
                    SampleDescription = new SampleDescription(1, 0),
                    SwapEffect = SwapEffect.Discard,
                    Usage = Usage.RenderTargetOutput,
                    Flags = SwapChainFlags.AllowModeSwitch
                };

            Device11 device11;
            SwapChain swapChain;

            Device11.CreateWithSwapChain(adapter1, DeviceCreationFlags.None, description, out device11, out swapChain);

            // create a view of our render target, which is the backbuffer of the swap chain we just created
            RenderTargetView renderTargetView;
            using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0))
                renderTargetView = new RenderTargetView(device11, resource);

            // setting a viewport is required if you want to actually see anything
            var context = device11.ImmediateContext;

            var viewport = new Viewport(0.0f, 0.0f, form.ClientSize.Width, form.ClientSize.Height);
            context.OutputMerger.SetTargets(renderTargetView);
            context.Rasterizer.SetViewports(viewport);

            //
            // Create the DirectX11 texture2D. This texture will be shared with the DirectX10 device.
            //
            // The DirectX10 device will be used to render text onto this texture.
            // DirectX11 will then draw this texture (blended) onto the screen.
            // The KeyedMutex flag is required in order to share this resource between the two devices.
            var textureD3D11 = new Texture2D(device11, new Texture2DDescription
            {
                Width = form.ClientSize.Width,
                Height = form.ClientSize.Height,
                MipLevels = 1,
                ArraySize = 1,
                Format = Format.B8G8R8A8_UNorm,
                SampleDescription = new SampleDescription(1, 0),
                Usage = ResourceUsage.Default,
                BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.SharedKeyedmutex
            });

            // ---------------------------------------------------------------------------------------------
            // Setup a direct 3d version 10.1 adapter
            // ---------------------------------------------------------------------------------------------
            var device10 = new Device10(adapter1, SharpDX.Direct3D10.DeviceCreationFlags.BgraSupport, FeatureLevel.Level_10_0);

            // ---------------------------------------------------------------------------------------------
            // Setup Direct 2d
            // ---------------------------------------------------------------------------------------------

            // Direct2D Factory
            var factory2D = new SharpDX.Direct2D1.Factory(FactoryType.SingleThreaded, DebugLevel.Information);

            // Here we bind the texture we've created on our direct3d11 device through the direct3d10
            // to the direct 2d render target....
            var sharedResource = textureD3D11.QueryInterface<SharpDX.DXGI.Resource>();
            var textureD3D10 = device10.OpenSharedResource<SharpDX.Direct3D10.Texture2D>(sharedResource.SharedHandle);

            var surface = textureD3D10.AsSurface();
            var rtp = new RenderTargetProperties
                {
                    MinLevel = SharpDX.Direct2D1.FeatureLevel.Level_10,
                    Type = RenderTargetType.Hardware,
                    PixelFormat = new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)
                };

            var renderTarget2D = new RenderTarget(factory2D, surface, rtp);
            var solidColorBrush = new SolidColorBrush(renderTarget2D, Colors.Red);

            // ---------------------------------------------------------------------------------------------------
            // Setup the rendering data
            // ---------------------------------------------------------------------------------------------------

            // Load Effect. This includes both the vertex and pixel shaders.
            // Also can include more than one technique.
            ShaderBytecode shaderByteCode = ShaderBytecode.CompileFromFile(
                "effectDx11.fx",
                "fx_5_0",
                ShaderFlags.EnableStrictness);

            var effect = new Effect(device11, shaderByteCode);

            // create triangle vertex data, making sure to rewind the stream afterward
            var verticesTriangle = new DataStream(VertexPositionColor.SizeInBytes * 3, true, true);
            verticesTriangle.Write(new VertexPositionColor(new Vector3(0.0f, 0.5f, 0.5f),new Color4(1.0f, 0.0f, 0.0f, 1.0f)));
            verticesTriangle.Write(new VertexPositionColor(new Vector3(0.5f, -0.5f, 0.5f),new Color4(0.0f, 1.0f, 0.0f, 1.0f)));
            verticesTriangle.Write(new VertexPositionColor(new Vector3(-0.5f, -0.5f, 0.5f),new Color4(0.0f, 0.0f, 1.0f, 1.0f)));

            verticesTriangle.Position = 0;

            // create the triangle vertex layout and buffer
            var layoutColor = new InputLayout(device11, effect.GetTechniqueByName("Color").GetPassByIndex(0).Description.Signature, VertexPositionColor.inputElements);
            var vertexBufferColor = new Buffer(device11, verticesTriangle, (int)verticesTriangle.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
            verticesTriangle.Close();

            // create overlay vertex data, making sure to rewind the stream afterward
            // Top Left of screen is -1, +1
            // Bottom Right of screen is +1, -1
            var verticesText = new DataStream(VertexPositionTexture.SizeInBytes * 4, true, true);
            verticesText.Write(new VertexPositionTexture(new Vector3(-1, 1, 0),new Vector2(0, 0f)));
            verticesText.Write(new VertexPositionTexture(new Vector3(1, 1, 0),new Vector2(1, 0)));
            verticesText.Write(new VertexPositionTexture(new Vector3(-1, -1, 0),new Vector2(0, 1)));
            verticesText.Write(new VertexPositionTexture(new Vector3(1, -1, 0),new Vector2(1, 1)));

            verticesText.Position = 0;

            // create the overlay vertex layout and buffer
            var layoutOverlay = new InputLayout(device11, effect.GetTechniqueByName("Overlay").GetPassByIndex(0).Description.Signature, VertexPositionTexture.inputElements);
            var vertexBufferOverlay = new Buffer(device11, verticesText, (int)verticesText.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
            verticesText.Close();

            // Think of the shared textureD3D10 as an overlay.
            // The overlay needs to show the 2d content but let the underlying triangle (or whatever)
            // show thru, which is accomplished by blending.
            var bsd = new BlendStateDescription();
            bsd.RenderTarget[0].IsBlendEnabled = true;
            bsd.RenderTarget[0].SourceBlend = BlendOption.SourceColor;
            bsd.RenderTarget[0].DestinationBlend = BlendOption.BlendFactor;
            bsd.RenderTarget[0].BlendOperation = BlendOperation.Add;
            bsd.RenderTarget[0].SourceAlphaBlend = BlendOption.One;
            bsd.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero;
            bsd.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add;
            bsd.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All;

            var blendStateTransparent = new BlendState(device11, bsd);

            // ---------------------------------------------------------------------------------------------------
            // Create and tesselate an ellipse
            // ---------------------------------------------------------------------------------------------------
            var center = new DrawingPointF(form.ClientSize.Width/2.0f, form.ClientSize.Height/2.0f);
            var ellipse = new EllipseGeometry(factory2D, new Ellipse(center, form.ClientSize.Width / 2.0f, form.ClientSize.Height / 2.0f));

            // Populate a PathGeometry from Ellipse tessellation
            var tesselatedGeometry = new PathGeometry(factory2D);
            _geometrySink = tesselatedGeometry.Open();

            // Force RoundLineJoin otherwise the tesselated looks buggy at line joins
            _geometrySink.SetSegmentFlags(PathSegment.ForceRoundLineJoin);

            // Tesselate the ellipse to our TessellationSink
            ellipse.Tessellate(1, this);

            _geometrySink.Close();

            // ---------------------------------------------------------------------------------------------------
            // Acquire the mutexes. These are needed to assure the device in use has exclusive access to the surface
            // ---------------------------------------------------------------------------------------------------

            var device10Mutex = textureD3D10.QueryInterface<KeyedMutex>();
            var device11Mutex = textureD3D11.QueryInterface<KeyedMutex>();

            // ---------------------------------------------------------------------------------------------------
            // Main rendering loop
            // ---------------------------------------------------------------------------------------------------

            bool first = true;

            RenderLoop
                .Run(form,
                     () =>
                         {
                             if(first)
                             {
                                 form.Activate();
                                 first = false;
                             }

                             // clear the render target to black
                             context.ClearRenderTargetView(renderTargetView, Colors.DarkSlateGray);

                             // Draw the triangle
                             context.InputAssembler.InputLayout = layoutColor;
                             context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
                             context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBufferColor, VertexPositionColor.SizeInBytes, 0));
                             context.OutputMerger.BlendState = null;
                             var currentTechnique = effect.GetTechniqueByName("Color");
                             for (var pass = 0; pass < currentTechnique.Description.PassCount; ++pass)
                             {
                                 using (var effectPass = currentTechnique.GetPassByIndex(pass))
                                 {
                                     System.Diagnostics.Debug.Assert(effectPass.IsValid, "Invalid EffectPass");
                                     effectPass.Apply(context);
                                 }
                                 context.Draw(3, 0);
                             };

                             // Draw Ellipse on the shared Texture2D
                             device10Mutex.Acquire(0, 100);
                             renderTarget2D.BeginDraw();
                             renderTarget2D.Clear(Colors.Black);
                             renderTarget2D.DrawGeometry(tesselatedGeometry, solidColorBrush);
                             renderTarget2D.DrawEllipse(new Ellipse(center, 200, 200), solidColorBrush, 20, null);
                             renderTarget2D.EndDraw();
                             device10Mutex.Release(0);

                             // Draw the shared texture2D onto the screen, blending the 2d content in
                             device11Mutex.Acquire(0, 100);
                             var srv = new ShaderResourceView(device11, textureD3D11);
                             effect.GetVariableByName("g_Overlay").AsShaderResource().SetResource(srv);
                             context.InputAssembler.InputLayout = layoutOverlay;
                             context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;
                             context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBufferOverlay, VertexPositionTexture.SizeInBytes, 0));
                             context.OutputMerger.BlendState = blendStateTransparent;
                             currentTechnique = effect.GetTechniqueByName("Overlay");

                             for (var pass = 0; pass < currentTechnique.Description.PassCount; ++pass)
                             {
                                 using (var effectPass = currentTechnique.GetPassByIndex(pass))
                                 {
                                     System.Diagnostics.Debug.Assert(effectPass.IsValid, "Invalid EffectPass");
                                     effectPass.Apply(context);
                                 }
                                 context.Draw(4, 0);
                             }
                             srv.Dispose();
                             device11Mutex.Release(0);

                             swapChain.Present(0, PresentFlags.None);
                         });

            // dispose everything
            vertexBufferColor.Dispose();
            vertexBufferOverlay.Dispose();
            layoutColor.Dispose();
            layoutOverlay.Dispose();
            effect.Dispose();
            shaderByteCode.Dispose();
            renderTarget2D.Dispose();
            swapChain.Dispose();
            device11.Dispose();
            device10.Dispose();
            textureD3D10.Dispose();
            textureD3D11.Dispose();
            factory1.Dispose();
            adapter1.Dispose();
            sharedResource.Dispose();
            factory2D.Dispose();
            surface.Dispose();
            solidColorBrush.Dispose();
            blendStateTransparent.Dispose();

            device10Mutex.Dispose();
            device11Mutex.Dispose();
        }
Пример #23
0
        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);
        }
Пример #24
0
        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);
        }