Example #1
0
        ICanvasImage CreateCheckerBoard(CanvasControl control)
        {
            var color1 = Color.FromArgb(255, 254, 254, 254);
            var color2 = Color.FromArgb(255, 250, 250, 250);

            Color[] twoByTwoChecker =
            {
                color1, color2,
                color2, color1
            };

            var checker = new DpiCompensationEffect
            {
                Source = new ScaleEffect
                {
                    Source = new BorderEffect
                    {
                        Source  = CanvasBitmap.CreateFromColors(control, twoByTwoChecker, 2, 2),
                        ExtendX = CanvasEdgeBehavior.Wrap,
                        ExtendY = CanvasEdgeBehavior.Wrap
                    },
                    Scale             = new Vector2(8, 8),
                    InterpolationMode = CanvasImageInterpolation.NearestNeighbor
                }
            };

            return(checker);
        }
Example #2
0
        private void GameCanvasDraw(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args)
        {
            if (!ViewModel.IsGameInitialized || GameCanvas == null)
            {
                return;
            }

            var dpiCompensationEffect = new DpiCompensationEffect
            {
                Source    = currentSurface,
                SourceDpi = new Vector2(GameCanvas.Dpi)
            };

            var transformEffect = new Transform2DEffect
            {
                Source            = dpiCompensationEffect,
                InterpolationMode = CanvasImageInterpolation.NearestNeighbor,
                TransformMatrix   = GetDisplayTransform(sender)
            };

            args.DrawingSession.DrawImage(transformEffect);
        }
        void CreateEffects()
        {
            // The Game of Life is a cellular automaton with very simple rules.
            // Each cell (pixel) can be either alive (white) or dead (black).
            // The state is updated by:
            //
            //  - for each cell, count how many of its 8 neighbors are alive
            //  - if less than two, the cell dies from loneliness
            //  - if exactly two, the cell keeps its current state
            //  - if exactly three, the cell become alive
            //  - if more than three, the cell dies from overcrowding

            // Step 1: use a convolve matrix to count how many neighbors are alive. This filter
            // also includes the state of the current cell, but with a lower weighting. The result
            // is an arithmetic encoding where (value / 2) indicates how many neighbors are alive,
            // and (value % 2) is the state of the cell itself. This is divided by 18 to make it
            // fit within 0-1 color range.

            countNeighborsEffect = new ConvolveMatrixEffect
            {
                KernelMatrix = new float[]
                {
                    2, 2, 2,
                    2, 1, 2,
                    2, 2, 2
                },

                Divisor    = 18,
                BorderMode = EffectBorderMode.Hard,
            };

            // Step 2: use a color transfer table to map the different states produced by the
            // convolve matrix to whether the cell should live or die. Each pair of entries in
            // this table corresponds to a certain number of live neighbors. The first of the
            // pair is the result if the current cell is dead, or the second if it is alive.

            float[] transferTable =
            {
                0, 0,   // 0 live neighbors -> dead cell
                0, 0,   // 1 live neighbors -> dead cell
                0, 1,   // 2 live neighbors -> cell keeps its current state
                1, 1,   // 3 live neighbors -> live cell
                0, 0,   // 4 live neighbors -> dead cell
                0, 0,   // 5 live neighbors -> dead cell
                0, 0,   // 6 live neighbors -> dead cell
                0, 0,   // 7 live neighbors -> dead cell
                0, 0,   // 8 live neighbors -> dead cell
            };

            liveOrDieEffect = new DiscreteTransferEffect
            {
                Source = countNeighborsEffect,

                RedTable   = transferTable,
                GreenTable = transferTable,
                BlueTable  = transferTable,
            };

            // Step 3: the algorithm is implemented in terms of white = live,
            // black = dead, but we invert these colors before displaying the
            // result, just 'cause I think it looks better that way.

            invertEffect = new LinearTransferEffect
            {
                RedSlope    = -1,
                RedOffset   = 1,
                GreenSlope  = -1,
                GreenOffset = 1,
                BlueSlope   = -1,
                BlueOffset  = 1,
            };

            // Step 4: insert our own DPI compensation effect to stop the system trying to
            // automatically convert DPI for us. The Game of Life simulation always works
            // in pixels (96 DPI) regardless of display DPI. Normally, the system would
            // handle this mismatch automatically and scale the image up as needed to fit
            // higher DPI displays. We don't want that behavior here, because it would use
            // a linear filter while we want nearest neighbor. So we insert a no-op DPI
            // converter of our own. This overrides the default adjustment by telling the
            // system the source image is already the same DPI as the destination canvas
            // (even though it really isn't). We'll handle any necessary scaling later
            // ourselves, using Transform2DEffect to control the interpolation mode.

            var dpiCompensationEffect = new DpiCompensationEffect
            {
                Source    = invertEffect,
                SourceDpi = new Vector2(canvas.Dpi),
            };

            // Step 5: a transform matrix scales up the simulation rendertarget and moves
            // it to the right part of the screen. This uses nearest neighbor filtering
            // to avoid unwanted blurring of the cell shapes.

            transformEffect = new Transform2DEffect
            {
                Source            = dpiCompensationEffect,
                InterpolationMode = CanvasImageInterpolation.NearestNeighbor,
            };
        }
Example #4
0
        void CreateEffects()
        {
            // The Game of Life is a cellular automaton with very simple rules.
            // Each cell (pixel) can be either alive (white) or dead (black).
            // The state is updated by:
            //
            //  - for each cell, count how many of its 8 neighbors are alive
            //  - if less than two, the cell dies from loneliness
            //  - if exactly two, the cell keeps its current state
            //  - if exactly three, the cell become alive
            //  - if more than three, the cell dies from overcrowding

            // Step 1: use a convolve matrix to count how many neighbors are alive. This filter
            // also includes the state of the current cell, but with a lower weighting. The result
            // is an arithmetic encoding where (value / 2) indicates how many neighbors are alive,
            // and (value % 2) is the state of the cell itself. This is divided by 18 to make it
            // fit within 0-1 color range.

            countNeighborsEffect = new ConvolveMatrixEffect
            {
                KernelMatrix = new float[]
                {
                    2, 2, 2,
                    2, 1, 2,
                    2, 2, 2
                },

                Divisor = 18,
                BorderMode = EffectBorderMode.Hard,
            };

            // Step 2: use a color transfer table to map the different states produced by the
            // convolve matrix to whether the cell should live or die. Each pair of entries in
            // this table corresponds to a certain number of live neighbors. The first of the
            // pair is the result if the current cell is dead, or the second if it is alive.

            float[] transferTable =
            {
                0, 0,   // 0 live neighbors -> dead cell
                0, 0,   // 1 live neighbors -> dead cell
                0, 1,   // 2 live neighbors -> cell keeps its current state
                1, 1,   // 3 live neighbors -> live cell
                0, 0,   // 4 live neighbors -> dead cell
                0, 0,   // 5 live neighbors -> dead cell
                0, 0,   // 6 live neighbors -> dead cell
                0, 0,   // 7 live neighbors -> dead cell
                0, 0,   // 8 live neighbors -> dead cell
            };

            liveOrDieEffect = new DiscreteTransferEffect
            {
                Source = countNeighborsEffect,

                RedTable = transferTable,
                GreenTable = transferTable,
                BlueTable = transferTable,
            };

            // Step 3: the algorithm is implemented in terms of white = live,
            // black = dead, but we invert these colors before displaying the
            // result, just 'cause I think it looks better that way.

            invertEffect = new LinearTransferEffect
            {
                RedSlope = -1,
                RedOffset = 1,
                GreenSlope = -1,
                GreenOffset = 1,
                BlueSlope = -1,
                BlueOffset = 1,
            };

            // Step 4: insert our own DPI compensation effect to stop the system trying to
            // automatically convert DPI for us. The Game of Life simulation always works
            // in pixels (96 DPI) regardless of display DPI. Normally, the system would
            // handle this mismatch automatically and scale the image up as needed to fit
            // higher DPI displays. We don't want that behavior here, because it would use
            // a linear filter while we want nearest neighbor. So we insert a no-op DPI
            // converter of our own. This overrides the default adjustment by telling the
            // system the source image is already the same DPI as the destination canvas
            // (even though it really isn't). We'll handle any necessary scaling later
            // ourselves, using Transform2DEffect to control the interpolation mode.

            var dpiCompensationEffect = new DpiCompensationEffect
            {
                Source = invertEffect,
                SourceDpi = new Vector2(canvas.Dpi),
            };

            // Step 5: a transform matrix scales up the simulation rendertarget and moves
            // it to the right part of the screen. This uses nearest neighbor filtering
            // to avoid unwanted blurring of the cell shapes.

            transformEffect = new Transform2DEffect
            {
                Source = dpiCompensationEffect,
                InterpolationMode = CanvasImageInterpolation.NearestNeighbor,
            };
        }
Example #5
0
        ICanvasImage CreateCheckerBoard(CanvasControl control)
        {
            var color1 = Color.FromArgb(255, 254, 254, 254);
            var color2 = Color.FromArgb(255, 250, 250, 250);

            Color[] twoByTwoChecker =
            {
                color1, color2,
                color2, color1
            };

            var checker = new DpiCompensationEffect
            {
                Source = new ScaleEffect
                {
                    Source = new BorderEffect
                    {
                        Source = CanvasBitmap.CreateFromColors(control, twoByTwoChecker, 2, 2),
                        ExtendX = CanvasEdgeBehavior.Wrap,
                        ExtendY = CanvasEdgeBehavior.Wrap
                    },
                    Scale = new Vector2(8, 8),
                    InterpolationMode = CanvasImageInterpolation.NearestNeighbor
                }
            };

            return checker;
        }