示例#1
0
        private static void GenerateMosaic(QuadrantMatchingTileProvider tileProvider, Stream inputStream, List <byte[]> tileImages, Stream outputStream)
        {
            SKBitmap[,] mosaicTileGrid;

            inputStream.Seek(0, SeekOrigin.Begin);

            using (var skStream = new SKManagedStream(inputStream))
                using (var bitmap = SKBitmap.Decode(skStream)) {
                    // use transparency for the source image overlay
                    var srcImagePaint = new SKPaint()
                    {
                        Color = SKColors.White.WithAlpha(200)
                    };

                    int xTileCount = bitmap.Width / MosaicBuilder.TileWidth;
                    int yTileCount = bitmap.Height / MosaicBuilder.TileHeight;

                    int tileCount = xTileCount * yTileCount;

                    mosaicTileGrid = new SKBitmap[xTileCount, yTileCount];

                    int finalTileWidth  = MosaicBuilder.TileWidth * MosaicBuilder.ScaleMultiplier;
                    int finalTileHeight = MosaicBuilder.TileHeight * MosaicBuilder.ScaleMultiplier;
                    int targetWidth     = xTileCount * finalTileWidth;
                    int targetHeight    = yTileCount * finalTileHeight;

                    var tileList = new List <(int, int)>();

                    // add coordinates for the left corner of each tile
                    for (int x = 0; x < xTileCount; x++)
                    {
                        for (int y = 0; y < yTileCount; y++)
                        {
                            tileList.Add((x, y));
                        }
                    }

                    // create output surface
                    var surface = SKSurface.Create(targetWidth, targetHeight, SKImageInfo.PlatformColorType, SKAlphaType.Premul);
                    surface.Canvas.DrawColor(SKColors.White); // clear the canvas / fill with white
                    surface.Canvas.DrawBitmap(bitmap, 0, 0, srcImagePaint);

                    // using the Darken blend mode causes colors from the source image to come through
                    var tilePaint = new SKPaint()
                    {
                        BlendMode = SKBlendMode.Darken
                    };
                    surface.Canvas.SaveLayer(tilePaint); // save layer so blend mode is applied

                    var random = new Random();

                    while (tileList.Count > 0)
                    {
                        // choose a new tile at random
                        int nextIndex = random.Next(tileList.Count);
                        var tileInfo  = tileList[nextIndex];
                        tileList.RemoveAt(nextIndex);

                        // get the tile image for this point
                        //var exclusionList = GetExclusionList(mosaicTileGrid, tileInfo.Item1, tileInfo.Item2);
                        var tileBitmap = tileProvider.GetImageForTile(tileInfo.Item1, tileInfo.Item2);
                        mosaicTileGrid[tileInfo.Item1, tileInfo.Item2] = tileBitmap;

                        // draw the tile on the surface at the coordinates
                        SKRect tileRect = SKRect.Create(tileInfo.Item1 * TileWidth, tileInfo.Item2 * TileHeight, finalTileWidth, finalTileHeight);
                        surface.Canvas.DrawBitmap(tileBitmap, tileRect);
                    }

                    surface.Canvas.Restore(); // merge layers
                    surface.Canvas.Flush();

                    var imageBytes = surface.Snapshot().Encode(SKEncodedImageFormat.Jpeg, 80);
                    imageBytes.SaveTo(outputStream);
                }
        }
 public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info)
 {
     Surface = surface;
     Info    = info;
 }
示例#3
0
 public virtual void DrawInSurface(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
 {
 }
示例#4
0
 public SkRenderer(SKSurface surface, SKCanvas canvas)
 {
     _c      = canvas;
     Surface = surface;
     Bus     = new RenderBus();
 }
        public void OnDrawFrame(IGL10 gl)
        {
            GLES10.GlClear(GLES10.GlColorBufferBit | GLES10.GlDepthBufferBit | GLES10.GlStencilBufferBit);

            // create the contexts if not done already
            if (context == null)
            {
                var glInterface = GRGlInterface.Create();
                context = GRContext.CreateGl(glInterface);
            }

            // manage the drawing surface
            if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
            {
                // create or update the dimensions
                lastSize = newSize;

                // read the info from the buffer
                var buffer = new int[3];
                GLES20.GlGetIntegerv(GLES20.GlFramebufferBinding, buffer, 0);
                GLES20.GlGetIntegerv(GLES20.GlStencilBits, buffer, 1);
                GLES20.GlGetIntegerv(GLES20.GlSamples, buffer, 2);
                var samples    = buffer[2];
                var maxSamples = context.GetMaxSurfaceSampleCount(colorType);
                if (samples > maxSamples)
                {
                    samples = maxSamples;
                }
                glInfo = new GRGlFramebufferInfo((uint)buffer[0], colorType.ToGlSizedFormat());

                // destroy the old surface
                surface?.Dispose();
                surface = null;
                canvas  = null;

                // re-create the render target
                renderTarget?.Dispose();
                renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, buffer[1], glInfo);
            }

            // create the surface
            if (surface == null)
            {
                surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType);
                canvas  = surface.Canvas;
            }

            using (new SKAutoCanvasRestore(canvas, true))
            {
                // start drawing
                var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo);
                OnPaintSurface(e);
#pragma warning disable CS0618 // Type or member is obsolete
                OnDrawFrame(e.Surface, e.RenderTarget);
#pragma warning restore CS0618 // Type or member is obsolete
            }

            // flush the SkiaSharp contents to GL
            canvas.Flush();
            context.Flush();
        }
示例#6
0
    public void SeriesRemoved()
    {
        var series = new LineSeries <int> {
            Values = new List <int> {
                1, 6, 4, 2
            }
        };

        var seriesCollection = new List <ISeries> {
            series
        };

        var chart = new TestCartesianChartView
        {
            Series = seriesCollection,
            XAxes  = new[] { new Axis() },
            YAxes  = new[] { new Axis() },
        };

        var canvas = chart.CoreCanvas;

        void DrawChart()
        {
            while (!canvas.IsValid)
            {
                canvas.DrawFrame(
                    new SkiaSharpDrawingContext(
                        canvas,
                        new SKImageInfo(100, 100),
                        SKSurface.CreateNull(100, 100),
                        new SKCanvas(new SKBitmap())));
            }
        }

        chart.Core.Update(new ChartUpdateParams {
            Throttling = false
        });
        DrawChart();

        var drawables  = canvas.DrawablesCount;
        var geometries = canvas.CountGeometries();

        seriesCollection.Add(new LineSeries <int> {
            Values = new List <int> {
                1, 6, 4, 2
            }
        });

        chart.Core.Update(new ChartUpdateParams {
            Throttling = false
        });
        DrawChart();

        seriesCollection.RemoveAt(0);
        chart.Core.Update(new ChartUpdateParams {
            Throttling = false
        });
        DrawChart();

        Assert.IsTrue(
            drawables == canvas.DrawablesCount &&
            geometries == canvas.CountGeometries());
    }
 public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
 {
     Surface      = surface;
     RenderTarget = renderTarget;
 }
示例#8
0
        /// <summary>
        /// This is triggered whenever the canvas needs to redraw.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnCanvasViewPaintSurface(object sender, SkiaSharp.Views.Forms.SKPaintSurfaceEventArgs args)
        {
            if (viewModel.ChartData == null)
            {
                return;
            }
            if (viewModel.ChartData.Count == 0)
            {
                return;
            }

            SKImageInfo info    = args.Info;
            SKSurface   surface = args.Surface;
            SKCanvas    canvas  = surface.Canvas;

            var y = info.Height / 2;

            canvas.Clear();

            SKPoint center = new SKPoint(info.Width / 2, info.Height / 2);
            float   radius = Math.Min(info.Width / 2, info.Height / 2) - 2 * Constants.ExplodeOffset;
            SKRect  rect   = new SKRect(center.X - radius, center.Y - radius,
                                        center.X + radius, center.Y + radius);

            float startAngle = -90; //This is alighed to the marker to make tracking the winning prize easier.


            //for text
            float xCenter = info.Width / 2;
            float yCenter = info.Height / 2;

            foreach (ChartData item in viewModel.ChartData)
            {
                float sweepAngle = 360f / viewModel.ChartData.Count;

                using (SKPath path = new SKPath())
                    using (SKPaint fillPaint = new SKPaint())
                        using (SKPaint outlinePaint = new SKPaint())
                            using (SKPaint textPaint = new SKPaint())
                            {
                                path.MoveTo(center);
                                path.ArcTo(rect, startAngle, sweepAngle, false);


                                path.Close();

                                fillPaint.Style = SKPaintStyle.Fill;
                                fillPaint.Color = item.Color;

                                outlinePaint.Style       = SKPaintStyle.Stroke;
                                outlinePaint.StrokeWidth = 5;
                                outlinePaint.Color       = SKColors.White;

                                #region Text Writer
                                //write text to the screen
                                textPaint.TextSize    = 40;
                                textPaint.StrokeWidth = 1;
                                textPaint.Color       = SKColors.White;

                                //Adjust text size.
                                SKRect textBounds = new SKRect();
                                textPaint.MeasureText(item.Text, ref textBounds);
                                float yText = yCenter - textBounds.Height / 2 - textBounds.Top;

                                // Adjust TextSize property so text is 95% of the ARC
                                // float textWidth = textPaint.MeasureText(item.Text);
                                // textPaint.TextSize = 0.95f * info.Width * textPaint.TextSize / textWidth;

                                #endregion

                                canvas.Save();

                                DrawRotatedWithMatrices(canvas, path, fillPaint, outlinePaint, item, _degrees, (int)center.X, y);

                                //Writing Actual texts
                                var test_angle = _degrees + (360 / viewModel.ChartData.Count / 2) - (360 / viewModel.ChartData.Count * 2);

                                float sweepAngleText = 360f / viewModel.ChartData.Count;
                                float startAngleText = sweepAngleText - sweepAngleText / 2;
                                foreach (ChartData itemer in viewModel.ChartData)
                                {
                                    canvas.Save();
                                    canvas.RotateDegrees(startAngleText + _degrees - 90, xCenter, yCenter);

                                    if (itemer.Text.Trim().Length > 6)
                                    {
                                        textPaint.TextSize = 30;
                                    }
                                    else
                                    {
                                        textPaint.TextSize = 40;
                                    }
                                    canvas.DrawText(itemer.Text, xCenter, yText, textPaint);
                                    canvas.Restore();
                                    test_angle += 360 / viewModel.ChartData.Count;

                                    if (test_angle > 360)
                                    {
                                        test_angle = test_angle - 360;
                                    }

                                    if (startAngleText > 360)
                                    {
                                        startAngleText = startAngleText - 360;
                                    }
                                    startAngleText += sweepAngleText;
                                }
                                canvas.Restore();
                            }

                startAngle += sweepAngle;
            }

            #region Marker
            //draw the Mark
            using (SKPaint fillMarkCirclePaint = new SKPaint())
                using (SKPaint fillMarkCirclePaintOuter = new SKPaint())
                    using (SKPaint fillMarkTrianglePaint = new SKPaint())
                    {
                        fillMarkCirclePaint.Style      = SKPaintStyle.StrokeAndFill;
                        fillMarkCirclePaintOuter.Style = SKPaintStyle.StrokeAndFill;
                        fillMarkCirclePaintOuter.Color = Color.FromHex("#FFF180").ToSKColor();

                        // Define an array of rainbow colors
                        List <SKColor> colors = new List <SKColor>();

                        foreach (var col in viewModel.Colors)
                        {
                            colors.Add(Color.FromHex(col).ToSKColor());
                        }

                        //draw outer circle
                        canvas.DrawCircle(args.Info.Width / 2, args.Info.Height / 2, 60, fillMarkCirclePaintOuter); //outer

                        //draw triangle
                        fillMarkTrianglePaint.Style = SKPaintStyle.StrokeAndFill;
                        fillMarkTrianglePaint.Color = Color.FromHex("#FFF180").ToSKColor();
                        SKPath trianglePath = new SKPath();
                        trianglePath.MoveTo((args.Info.Width / 2) - 55, args.Info.Height / 2);
                        trianglePath.LineTo((args.Info.Width / 2) - 55, args.Info.Height / 2);
                        trianglePath.LineTo((args.Info.Width / 2) + 55, args.Info.Height / 2);
                        trianglePath.LineTo(args.Info.Width / 2, (float)(args.Info.Height / 2.5));
                        trianglePath.Close();
                        canvas.DrawPath(trianglePath, fillMarkTrianglePaint);


                        //draw inner circle
                        SKPoint circle_center = new SKPoint(info.Rect.MidX, info.Rect.MidY);
                        fillMarkCirclePaint.Shader = SKShader.CreateSweepGradient(circle_center, colors.ToArray());
                        canvas.DrawCircle(args.Info.Width / 2, args.Info.Height / 2, 50, fillMarkCirclePaint); //inner
                    }
            #endregion


            //Get the current prize.
            float prize_degree = _degrees + (360 / viewModel.ChartData.Count / 2);

            if (_degrees == 0 || Math.Round(_degrees, MidpointRounding.AwayFromZero) == 360)
            {
                prize_degree = _degrees;
            }

            var segment      = ((prize_degree / 360f) * viewModel.ChartData.Count);
            var int_segment2 = Math.Round(segment, MidpointRounding.AwayFromZero);
            var realIndex    = viewModel.ChartData.Count == viewModel.ChartData.Count - (int)int_segment2 ? 0 : viewModel.ChartData.Count - (int)int_segment2;
            viewModel.Prize = viewModel.ChartData[realIndex].Sector; //add back
            resultBox.Text  = viewModel.Prize?.Game;
            // currentBox.Text = ((int)realIndex).ToString();
            if (viewModel.EnableHaptic)
            {
                TryHaptic();
            }
            IncrementDegrees();
        }
示例#9
0
        //METHODS

        /**********************************************************************
         *********************************************************************/
        // do the drawing
        static void PaintSurface(object sender, SKPaintSurfaceEventArgs e)
        {
            //canvas object
            info = e.Info;
            SKSurface surface = e.Surface;
            SKCanvas  canvas  = surface.Canvas;

            //Important! Otherwise the drawing will look messed up in iOS
            if (canvas != null)
            {
                canvas.Clear();
            }

            //calculate some stuff and make the paint
            CalculateNeededNumbers(canvas);
            MakeSKPaint(); //depends on xe and ye and therfore has to be called after they were initialized

            /*********************HERE GOES THE DRAWING************************/
            int state = Int32.Parse(action[currentStep, 6]);

            DrawBackground(canvas, state);

            //draw fast recovery reno
            for (int i = 0; i <= currentStep; i++)
            {
                int    round  = Int32.Parse(action[i, 0]);
                String txt    = action[i, 1] + action[i, 2];
                String kind   = action[i, 1];
                String dupAck = action[i, 3];
                String cwnd   = action[i, 4];
                String tresh  = action[i, 5];
                String part   = action[i, 7];

                switch (kind)
                {
                case "Ack ":
                    DrawAckArrow(canvas, round, sk_PaintArrowAck, part, dupAck, cwnd, tresh);
                    DrawTextNextToAckArrow(canvas, round, txt, sk_TextArrowAck);
                    break;

                case "Pkt ":
                    DrawPktArrow(canvas, round, sk_PaintArrowPkt, part);
                    DrawTextNextToPktArrow(canvas, round, txt, sk_TextArrowPkt);
                    break;

                case "!Pkt ":
                    DrawPktArrow(canvas, round, sk_PaintArrowRed, part);
                    DrawTextNextToPktArrow(canvas, round, txt.Substring(1), sk_TextArrowRed);
                    break;

                case "Re-Pkt ":
                    DrawPktArrow(canvas, round, sk_PaintArrowPkt, part);
                    DrawTextNextToPktArrow(canvas, round, txt, sk_TextArrowPkt);
                    break;
                }
                //show cwnd and dupAck count in very first round
                if (i == 0)
                {
                    DrawTextTresh(canvas, round, tresh, sk_blackTextSmall);
                    DrawTextDupAck(canvas, round, dupAck, sk_blackTextSmall);
                    DrawTextCwnd(canvas, round, cwnd, sk_blackTextSmall);
                }
            }


            //execute all drawing actions
            canvas.Flush();
        }
示例#10
0
        void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info    = args.Info;
            SKSurface   surface = args.Surface;
            SKCanvas    canvas  = surface.Canvas;

            canvas.Clear();


            if (info.Width > info.Height)
            {
                this.graphMinHeightPercentage = Graph.graphTopPaddingPercentage;
            }
            else
            {
                this.graphMinHeightPercentage = Graph.defaultGraphMinHeightPercentage;
            }

            DateTime startDate = new DateTime(2018, 11, 1);
            DateTime endDate   = new DateTime(2018, 12, 8);

            bool success = this.graph.CalculatePoints(Graph.defaultGraphWidthPercentage, this.graphMinHeightPercentage * 100, info.Width, info.Height, startDate, endDate);


            List <List <SKPoint> > graphLines       = this.graph.GetGraphLines();
            List <List <SKPoint> > graphLinesFill   = this.graph.GetGraphLinesFill();
            List <List <SKPoint> > graphHelperLines = this.graph.GetGraphHelperLines();

            SKPaint paint = new SKPaint {
                Color       = SKColors.LightGray.WithAlpha(0xAA),
                StrokeWidth = 1,
                StrokeCap   = SKStrokeCap.Square,
                Style       = SKPaintStyle.Stroke,
                IsAntialias = true
            };

            foreach (List <SKPoint> graphHelperLine in graphHelperLines)
            {
                canvas.DrawPoints(SKPointMode.Lines, graphHelperLine.ToArray(), paint);
            }

            paint.StrokeCap = SKStrokeCap.Round;

            for (int i = 0; i < graphLines.Count; ++i)
            {
                paint.Color       = graph.colorList[i];
                paint.Style       = SKPaintStyle.Stroke;
                paint.StrokeWidth = 2;
                canvas.DrawPoints(SKPointMode.Polygon, graphLines[i].ToArray(), paint);
                paint.StrokeWidth = 6;
                canvas.DrawPoints(SKPointMode.Points, graphLines[i].ToArray(), paint);
                paint.Color = paint.Color.WithAlpha(0x50);
                paint.Style = SKPaintStyle.Fill;
                SKPath path = new SKPath();
                path.AddPoly(graphLinesFill[i].ToArray());
                canvas.DrawPath(path, paint);
            }

            paint.StrokeWidth = 4;
            paint.Color       = SKColors.Black;


            float bottomY = (1 - this.graphMinHeightPercentage) * info.Height;
            float topY    = (Graph.graphTopPaddingPercentage - axisExtensionPercentage) * info.Height;
            float leftX   = Graph.graphLeftPaddingPercentage * info.Width;
            float rightX  = (Graph.graphLeftPaddingPercentage + this.graphWidthPercentage + axisExtensionPercentage) * info.Width;

            List <SKPoint> horizontalAxis = new List <SKPoint> {
                //Axis
                new SKPoint(leftX, bottomY),
                new SKPoint(rightX, bottomY),


                //Arrow
                new SKPoint(rightX, bottomY),
                new SKPoint(rightX - arrowOffset, bottomY - arrowOffset),

                new SKPoint(rightX, bottomY),
                new SKPoint(rightX - arrowOffset, bottomY + arrowOffset),
            };
            List <SKPoint> verticalAxis = new List <SKPoint> {
                //Axis
                new SKPoint(leftX, bottomY),
                new SKPoint(leftX, topY),

                //Arrow

                new SKPoint(leftX, topY),
                new SKPoint(leftX - arrowOffset, topY + arrowOffset),

                new SKPoint(leftX, topY),
                new SKPoint(leftX + arrowOffset, topY + arrowOffset),
            };

            canvas.DrawPoints(SKPointMode.Lines, horizontalAxis.ToArray(), paint);
            canvas.DrawPoints(SKPointMode.Lines, verticalAxis.ToArray(), paint);
            if (success)
            {
                List <Graph.GraphValue> graphValues = this.graph.GetGraphValues();
                List <Graph.GraphValue> xValues     = this.graph.GetXValues();

                SKPaint textPaint = new SKPaint {
                    Color       = SKColors.Blue,
                    IsAntialias = true,
                };

                float textWidth = textPaint.MeasureText("22.22");
                textPaint.TextSize = Graph.graphLeftPaddingPercentage * info.Width * textScalePercentage * textPaint.TextSize / textWidth;
                SKRect textBounds = new SKRect();

                foreach (Graph.GraphValue graphValue in graphValues)
                {
                    textPaint.MeasureText(graphValue.Value, ref textBounds);

                    float xText = info.Width * (Graph.graphLeftPaddingPercentage + Graph.graphLeftPaddingPercentage * textPaddingPercentage) / 2 - textBounds.MidX;

                    canvas.DrawText(graphValue.Value, xText, (float)graphValue.anchor.Y - textBounds.MidY, textPaint);
                }

                foreach (Graph.GraphValue xValue in xValues)
                {
                    textPaint.MeasureText(xValue.Value, ref textBounds);
                    float yText = bottomY + textBounds.Height + 10;
                    canvas.DrawText(xValue.Value, (float)xValue.anchor.X - textBounds.MidX, yText, textPaint);
                }
            }
        }
示例#11
0
 public override void DrawView(SKSurface canvas)
 {
     //do nothing
 }
示例#12
0
        public ResizeResult ResizeFolder(string directoryPath, string directoryExportPath, float width, float height)
        {
            if (!Directory.Exists(directoryPath))
            {
                return(new ResizeResult()
                {
                    Success = false,
                    ErrorMessage = "Directory is not exists"
                });
            }

            if (!Directory.Exists(directoryExportPath))
            {
                if (Directory.CreateDirectory(directoryExportPath).Exists)
                {
                    return(new ResizeResult()
                    {
                        Success = false,
                        ErrorMessage = "Cannot create output folder"
                    });
                }
            }

            foreach (var file in Directory.GetFiles(directoryPath))
            {
                if (file.EndsWith(".png") || file.EndsWith(".jpg"))
                {
                    try
                    {
                        var bitmap = SKBitmap.Decode(file);
                        Console.WriteLine("Image Path: " + file);
                        var info    = new SKImageInfo((int)width, (int)height);
                        var surface = SKSurface.Create(info);
                        // the the canvas and properties
                        var canvas = surface.Canvas;

                        // make sure the canvas is blank
                        canvas.Clear(SKColors.Transparent);

                        var resizeFactor = 1f;
                        if (bitmap.Width * height / width > bitmap.Height)
                        {
                            resizeFactor = width / bitmap.Width;
                        }
                        else
                        {
                            resizeFactor = height / bitmap.Height;
                        }
                        Console.WriteLine($"OWidth: {bitmap.Width}, OHeight: {bitmap.Height}, ratio: {resizeFactor}, destWidth: {(int)(bitmap.Width * resizeFactor)}, destHeight: {(int)(bitmap.Height * resizeFactor)}");

                        var         targetSize = (int)Math.Min(width, height);
                        SKImageInfo nearest    = new SKImageInfo((int)(bitmap.Width * resizeFactor), (int)(bitmap.Height * resizeFactor));
                        //SKImageInfo nearest = new SKImageInfo(targetSize, targetSize);
                        var newImage = bitmap.Resize(nearest, SKFilterQuality.High);
                        canvas.DrawBitmap(newImage, new SKPoint((width - newImage.Width) / 2f, (height - newImage.Height) / 2f));
                        var image = surface.Snapshot();
                        //var image = SKImage.FromBitmap(toBitmap);
                        var data = image.Encode(SKEncodedImageFormat.Png, 90);



                        using (var stream = new FileStream(Path.Combine(directoryExportPath, Path.ChangeExtension(Path.GetFileName(file), ".png")), FileMode.OpenOrCreate, FileAccess.Write))
                            data.SaveTo(stream);

                        bitmap.Dispose();
                    }
                    catch (Exception e)
                    {
                        return(new ResizeResult()
                        {
                            Success = false,
                            ErrorMessage = "Error on file: " + file + "\n Exception: " + e.ToString()
                        });
                    }
                }
            }


            return(new ResizeResult()
            {
                Success = true,
                ErrorMessage = "Resize Success"
            });
        }
 public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget)
     : this(surface, renderTarget, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888)
 {
 }
示例#14
0
        public async Task <SKImage> GenerateChartAsync(ChartSettings chart)
        {
            try
            {
                await chart.Albums.ParallelForEachAsync(async album =>
                {
                    var encodedId    = StringExtensions.ReplaceInvalidChars(album.Url.LocalPath.Replace("/music/", ""));
                    var localAlbumId = StringExtensions.TruncateLongString(encodedId, 60);

                    SKBitmap chartImage;
                    var validImage     = true;
                    Color?primaryColor = null;

                    var fileName  = localAlbumId + ".png";
                    var localPath = FMBotUtil.GlobalVars.CacheFolder + fileName;

                    if (File.Exists(localPath))
                    {
                        chartImage = SKBitmap.Decode(localPath);
                        Statistics.LastfmCachedImageCalls.Inc();
                    }
                    else
                    {
                        if (album.Images.Any() && album.Images.Large != null)
                        {
                            var url = album.Images.Large.AbsoluteUri;

                            SKBitmap bitmap;
                            try
                            {
                                var httpClient = new System.Net.Http.HttpClient();
                                var bytes      = await httpClient.GetByteArrayAsync(url);

                                Statistics.LastfmImageCalls.Inc();

                                var stream = new MemoryStream(bytes);

                                bitmap = SKBitmap.Decode(stream);
                            }
                            catch
                            {
                                bitmap     = SKBitmap.Decode(FMBotUtil.GlobalVars.ImageFolder + "loading-error.png");
                                validImage = false;
                            }

                            chartImage = bitmap;

                            if (validImage)
                            {
                                using var image        = SKImage.FromBitmap(bitmap);
                                using var data         = image.Encode(SKEncodedImageFormat.Png, 100);
                                await using var stream = File.OpenWrite(localPath);
                                data.SaveTo(stream);
                            }
                        }
                        else
                        {
                            chartImage = SKBitmap.Decode(FMBotUtil.GlobalVars.ImageFolder + "unknown.png");
                            validImage = false;
                        }
                    }

                    switch (chart.TitleSetting)
                    {
                    case TitleSetting.Titles:
                        AddTitleToChartImage(chartImage, album);
                        break;

                    case TitleSetting.ClassicTitles:
                        AddClassicTitleToChartImage(chartImage, album);
                        break;

                    case TitleSetting.TitlesDisabled:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    if (chart.RainbowSortingEnabled)
                    {
                        primaryColor = chartImage.GetAverageRgbColor();
                    }

                    chart.ChartImages.Add(new ChartImage(chartImage, chart.Albums.IndexOf(album), validImage, primaryColor));
                });


                SKImage finalImage = null;

                using (var tempSurface = SKSurface.Create(new SKImageInfo(chart.ChartImages.First().Image.Width *chart.Width, chart.ChartImages.First().Image.Height *chart.Height)))
                {
                    var canvas = tempSurface.Canvas;

                    var offset    = 0;
                    var offsetTop = 0;
                    var heightRow = 0;

                    for (var i = 0; i < Math.Min(chart.ImagesNeeded, chart.ChartImages.Count); i++)
                    {
                        IOrderedEnumerable <ChartImage> imageList;
                        if (chart.RainbowSortingEnabled)
                        {
                            imageList = chart.ChartImages
                                        .OrderBy(o => o.PrimaryColor.Value.GetHue())
                                        .ThenBy(o =>
                                                (o.PrimaryColor.Value.R * 3 +
                                                 o.PrimaryColor.Value.G * 2 +
                                                 o.PrimaryColor.Value.B * 1));
                        }
                        else
                        {
                            imageList = chart.ChartImages.OrderBy(o => o.Index);
                        }

                        var image = imageList
                                    .Where(w => !chart.SkipArtistsWithoutImage || w.ValidImage)
                                    .ElementAt(i).Image;

                        canvas.DrawBitmap(image, SKRect.Create(offset, offsetTop, image.Width, image.Height));

                        if (i == (chart.Width - 1) || i - (chart.Width) * heightRow == chart.Width - 1)
                        {
                            offsetTop += image.Height;
                            heightRow += 1;
                            offset     = 0;
                        }
                        else
                        {
                            offset += image.Width;
                        }
                    }

                    finalImage = tempSurface.Snapshot();
                }

                return(finalImage);
            }

            finally
            {
                foreach (var image in chart.ChartImages.Select(s => s.Image))
                {
                    image.Dispose();
                }
            }
        }
示例#15
0
        public void Animate(Action <float> reportProgress, SongConfiguration config, DirectoryInfo outputDirectory, string pngOutputPath = null)
        {
            var desiredReadingY = height * 3 / 4;

            if (!File.Exists(config.AudioFilePath))
            {
                throw new FileNotFoundException($"Song file not found: '{config.AudioFilePath}'");
            }

            using (var titleTypeface = SKTypeface.FromFamilyName(appConfig.TitleFont.Family, SKFontStyleWeight.Light, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright))
                using (var lyricTypeface = SKTypeface.FromFamilyName(appConfig.LyricsFont.Family, SKFontStyleWeight.Light, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright))
                    using (var verseTypeface = SKTypeface.FromFamilyName(appConfig.VerseFont.Family, SKFontStyleWeight.Light, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright))
                    {
                        var timingRegex      = new Regex(@"^(?:\[(\d{1,2}:\d{1,2}:\d{1,2})\])?\s*(?:\{([^}]+)\})?\s*(.*)$");
                        var unprocessedLines = config.Lyrics;

                        var speedChangeEasingFrames = appConfig.FramesPerSecond * 4;

                        var processedLines = new List <(TimeSpan arrivalTime, TimeSpan nextArrivalTime, IEnumerable <string> lines)>();
                        var verseLabels    = new List <VerseLabel>();

                        var      segmentLines   = new List <string>();
                        TimeSpan?segmentArrival = null;

                        foreach (var line in unprocessedLines)
                        {
                            var match            = timingRegex.Match(line);
                            var nextArrivalGroup = match.Groups[1];

                            if (nextArrivalGroup.Success)
                            {
                                var nextArrivalTime = TimeSpan.Parse(nextArrivalGroup.Value);

                                if (segmentLines.Any())
                                {
                                    processedLines.Add((segmentArrival.Value, nextArrivalTime, segmentLines));
                                    segmentLines = new List <string>();
                                }

                                segmentArrival = nextArrivalTime;

                                // TODO: Make it clearer/explicit that verse text requires a paired segment timing
                                if (match.Groups[2].Success)
                                {
                                    var arrivalFrame = (int)(segmentArrival.Value.TotalSeconds * appConfig.FramesPerSecond);

                                    if (verseLabels.Any())
                                    {
                                        verseLabels.Last().HiddenFrame = arrivalFrame - (int)(verseLabelHideBeforeVerseEnd.TotalSeconds * appConfig.FramesPerSecond);
                                    }

                                    verseLabels.Add(new VerseLabel
                                    {
                                        ArrivalFrame = arrivalFrame,
                                        Text         = match.Groups[2].Value
                                    });
                                }
                            }

                            var lyricText = match.Groups[3].Value;

                            segmentLines.Add(lyricText);
                        }

                        if (verseLabels.Any())
                        {
                            verseLabels.Last().HiddenFrame = (int)(processedLines.Last().nextArrivalTime.TotalSeconds *appConfig.FramesPerSecond);
                        }

                        float?previousPixelsPerFrame = null;

                        var speedChanges = new List <(int arrivalFrame, float fromPixelsPerFrame, float toPixelsPerFrame)>();

                        var lyrics = new List <Lyric>();

                        foreach (var timingSegment in processedLines)
                        {
                            // Calculate the speed of this segment, defined by (distance / duration)
                            var segmentHeight = CalculateTextHeight(
                                lyricTypeface,
                                appConfig.LyricsFont.Size,
                                timingSegment.lines,
                                appConfig.LyricsFont.Size + appConfig.LyricsFont.LineMargin,
                                width - sideMargin * 2
                                );

                            var segmentDuration = timingSegment.nextArrivalTime - timingSegment.arrivalTime;
                            var pixelsPerFrame  = (float)(segmentHeight / segmentDuration.TotalSeconds / appConfig.FramesPerSecond);
                            var arrivalFrame    = (int)(timingSegment.arrivalTime.TotalSeconds * appConfig.FramesPerSecond);

                            speedChanges.Add((
                                                 arrivalFrame,
                                                 previousPixelsPerFrame.GetValueOrDefault(pixelsPerFrame),
                                                 pixelsPerFrame
                                                 ));

                            var segmentDurationFrames = segmentDuration.TotalSeconds * appConfig.FramesPerSecond;

                            previousPixelsPerFrame = pixelsPerFrame;

                            lyrics.Add(new Lyric
                            {
                                VisibleFrame = (int)(arrivalFrame - (appConfig.OutputDimensions.Height - desiredReadingY) / pixelsPerFrame - 100),
                                HiddenFrame  = (int)(arrivalFrame + segmentDurationFrames + appConfig.OutputDimensions.Height / pixelsPerFrame),
                                ArrivalFrame = arrivalFrame,
                                Lines        = timingSegment.lines,
                                Height       = segmentHeight
                            });
                        }

                        var currentPixelsPerFrame = speedChanges.First().fromPixelsPerFrame;

                        var   currentSpeedChangeIndex = 1;
                        var   speedChangeStartFrame   = speedChanges.Count > 1 ? speedChanges[1].arrivalFrame - speedChangeEasingFrames / 2 : new int?();
                        float?accelerationPerFrame    = null;

                        var endTransitionDissolveDurationFrames = (int)(endTransitionDuration.TotalSeconds * appConfig.FramesPerSecond);

                        // TODO: Can we calculate total frames required from the song end time automatically?
                        // Or do we need an explicit "end of audio" timestamp in the lyrics file?
                        var duration = TimeSpan.Parse(config.Duration);

                        var totalFramesRequired = duration.TotalSeconds * appConfig.FramesPerSecond;
                        var outputFilePath      = Path.Combine(outputDirectory.FullName, config.OutputFilename);

                        File.Delete(outputFilePath);

                        var ffmpegProcess = StartFfmpeg(appConfig, config.AudioFilePath, outputFilePath);

                        var info = new SKImageInfo(width, height);
                        using (var surface = SKSurface.Create(info))
                        {
                            var canvas = surface.Canvas;

                            for (var frame = 0; frame <= totalFramesRequired; frame++)
                            {
                                reportProgress(frame / (float)totalFramesRequired);

                                canvas.Clear(SKColors.Black);

                                if (speedChangeStartFrame.HasValue)
                                {
                                    if (frame == speedChangeStartFrame.Value + speedChangeEasingFrames)
                                    {
                                        currentSpeedChangeIndex++;
                                        speedChangeStartFrame = speedChanges.Count > currentSpeedChangeIndex
                                    ? speedChanges[currentSpeedChangeIndex].arrivalFrame - speedChangeEasingFrames / 2
                                    : new int?();
                                        accelerationPerFrame = null;
                                    }
                                    else if (frame >= speedChangeStartFrame)
                                    {
                                        accelerationPerFrame   = accelerationPerFrame ?? (speedChanges[currentSpeedChangeIndex].toPixelsPerFrame - currentPixelsPerFrame) / speedChangeEasingFrames;
                                        currentPixelsPerFrame += accelerationPerFrame.Value;
                                    }
                                }

                                for (var i = 0; i < lyrics.Count; i++)
                                {
                                    var lyric = lyrics[i];

                                    if (frame < lyric.VisibleFrame)
                                    {
                                        continue;
                                    }

                                    if (frame == lyric.VisibleFrame)
                                    {
                                        lyric.Y = i > 0
                                    ? lyrics[i - 1].Y + lyrics[i - 1].Height
                                    : desiredReadingY + (lyric.ArrivalFrame - lyric.VisibleFrame) * currentPixelsPerFrame;
                                    }
                                    else
                                    {
                                        lyric.Y -= currentPixelsPerFrame;
                                    }

                                    DrawLyric(
                                        canvas,
                                        lyricTypeface,
                                        appConfig.LyricsFont.Size,
                                        appConfig.LyricsFont.Size + appConfig.LyricsFont.LineMargin,
                                        lyric.Lines,
                                        x: sideMargin,
                                        y: lyric.Y
                                        );
                                }

                                DrawGradientOverlays(canvas);

                                var framesToArrivalPointAtCurrentSpeed = (int)((appConfig.OutputDimensions.Height - desiredReadingY) / currentPixelsPerFrame);

                                for (var i = 0; i < verseLabels.Count; i++)
                                {
                                    var verseLabel = verseLabels[i];
                                    var opacity    = 1f;

                                    if (frame < verseLabel.ArrivalFrame - framesToArrivalPointAtCurrentSpeed)
                                    {
                                        continue;
                                    }

                                    if (frame == verseLabel.ArrivalFrame - framesToArrivalPointAtCurrentSpeed)
                                    {
                                        verseLabel.Y = appConfig.OutputDimensions.Height;
                                    }
                                    else if (frame > verseLabel.ArrivalFrame - framesToArrivalPointAtCurrentSpeed &&
                                             verseLabel.Y > appConfig.OutputDimensions.HeaderHeight + appConfig.OutputDimensions.GradientHeight)
                                    {
                                        verseLabel.Y -= currentPixelsPerFrame;
                                    }
                                    else if (frame >= verseLabel.HiddenFrame)
                                    {
                                        opacity = Math.Max(0, 1 - (frame - verseLabel.HiddenFrame) / (float)DissolveAnimationDurationFrames);
                                    }

                                    DrawVerseLabel(
                                        canvas,
                                        verseTypeface,
                                        appConfig.VerseFont.Size,
                                        SKColor.Parse(appConfig.VerseFont.HexColor),
                                        verseLabel.Text,
                                        width - sideMargin,
                                        verseLabel.Y,
                                        opacity
                                        );
                                }

                                DrawTitleAndFooterBars(canvas, titleTypeface, appConfig.TitleFont.Size, SKColor.Parse(appConfig.TitleFont.HexColor), config.SongTitle);

                                if (totalFramesRequired - frame <= endTransitionDissolveDurationFrames)
                                {
                                    var alpha = (1 - (totalFramesRequired - frame) / endTransitionDissolveDurationFrames) * 255;
                                    using (var paint = new SKPaint
                                    {
                                        Color = SKColors.Black.WithAlpha((byte)alpha)
                                    })
                                    {
                                        canvas.DrawRect(new SKRect(0, 0, width, height), paint);
                                    }
                                }

                                using (var image = surface.Snapshot())
                                    using (var data = image.Encode(SKEncodedImageFormat.Png, 100))
                                        using (var ms = new MemoryStream(data.ToArray())
                                        {
                                            Position = 0
                                        })
                                        {
                                            ms.WriteTo(ffmpegProcess.StandardInput.BaseStream);
                                            ms.Flush();
                                            ffmpegProcess.StandardInput.BaseStream.Flush();

                                            if (pngOutputPath != null)
                                            {
                                                using (var fs = new FileStream(Path.Combine(pngOutputPath, $"{frame:D5}.png"), FileMode.Create, FileAccess.Write))
                                                {
                                                    ms.Position = 0;
                                                    ms.WriteTo(fs);
                                                    ms.Flush();

                                                    fs.Close();
                                                }
                                            }

                                            ms.Close();
                                        }
                            }
                        }

                        ffmpegProcess.StandardInput.BaseStream.Close();
                        ffmpegProcess.WaitForExit();
                    }
        }
示例#16
0
 public virtual void DrawInSurface(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
 {
     PaintSurface?.Invoke(this, new SKPaintGLSurfaceEventArgs(surface, renderTarget));
 }
示例#17
0
        private void Render(int cornerCount = 100, int maxVisibleDistance = 200)
        {
            // create the field if needed or if the size changed
            if (field == null || field.width != glControl1.Width || field.height != glControl1.Height)
            {
                field = new IntroAnimation.Field(glControl1.Width, glControl1.Height, cornerCount);
            }

            // step the field forward in time
            field.StepForward(3);

            // Create a Skia surface using the OpenGL control
            SKColorType colorType     = SKColorType.Rgba8888;
            GRContext   contextOpenGL = GRContext.Create(GRBackend.OpenGL, GRGlInterface.CreateNativeGlInterface());

            GL.GetInteger(GetPName.FramebufferBinding, out var framebuffer);
            GRGlFramebufferInfo glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

            GL.GetInteger(GetPName.StencilBits, out var stencil);
            GRBackendRenderTarget renderTarget = new GRBackendRenderTarget(glControl1.Width, glControl1.Height, contextOpenGL.GetMaxSurfaceSampleCount(colorType), stencil, glInfo);
            SKSurface             surface      = SKSurface.Create(contextOpenGL, renderTarget, GRSurfaceOrigin.BottomLeft, colorType);
            SKCanvas canvas = surface.Canvas;

            // draw the stuff
            var bgColor = field.GetBackgroundColor();

            canvas.Clear(new SKColor(bgColor.R, bgColor.G, bgColor.B));

            // draw circles at every corner
            var paint = new SKPaint {
                Color = new SKColor(255, 255, 255), IsAntialias = true
            };
            float radius = 2;

            for (int cornerIndex = 0; cornerIndex < field.corners.Length; cornerIndex++)
            {
                canvas.DrawCircle((float)field.corners[cornerIndex].X, (float)field.corners[cornerIndex].Y, radius, paint);
            }

            // draw lines between every corner and every other corner
            for (int i = 0; i < field.corners.Length; i++)
            {
                for (int j = 0; j < field.corners.Length; j++)
                {
                    double distance = field.GetDistance(i, j);
                    if (distance < maxVisibleDistance && distance != 0)
                    {
                        SKPoint pt1 = new SKPoint((float)field.corners[i].X, (float)field.corners[i].Y);
                        SKPoint pt2 = new SKPoint((float)field.corners[j].X, (float)field.corners[j].Y);
                        double  distanceFraction = distance / maxVisibleDistance;
                        byte    alpha            = (byte)(255 - distanceFraction * 256);
                        var     linePaint        = new SKPaint {
                            Color = new SKColor(255, 255, 255, alpha), IsAntialias = true
                        };
                        canvas.DrawLine(pt1, pt2, linePaint);
                    }
                }
            }

            // Force a display
            surface.Canvas.Flush();
            glControl1.SwapBuffers();

            // dispose to prevent memory access violations while exiting
            renderTarget?.Dispose();
            contextOpenGL?.Dispose();
            canvas?.Dispose();
            surface?.Dispose();

            // update the FPS display
            Text = field.GetBenchmarkMessage();
        }
示例#18
0
 public SkiaPainter(SKSurface surface, IImageLoader imageLoader)
 {
     this.surface = surface;
     skCanvas     = surface.Canvas;
     _imageLoader = imageLoader;
 }
示例#19
0
        private static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Usage AlphaTab.Samples.PngDump.exe Path");
                return;
            }

            // load score
            var score = ScoreLoader.LoadScoreFromBytes(File.ReadAllBytes(args[0]));

            // render score with svg engine and desired rendering width
            var settings = new Settings();

            settings.Core.Engine = "skia";
            var renderer = new ScoreRenderer(settings)
            {
                Width = 970
            };

            // iterate tracks
            for (var i = 0; i < score.Tracks.Count; i++)
            {
                var track = score.Tracks[i];

                // render track
                Console.WriteLine("Rendering track {0} - {1}", i + 1, track.Name);
                var images      = new List <SKImage>();
                var totalWidth  = 0;
                var totalHeight = 0;
                renderer.PartialRenderFinished.On(r => { images.Add((SKImage)r.RenderResult); });
                renderer.RenderFinished.On(r =>
                {
                    totalWidth  = (int)r.TotalWidth;
                    totalHeight = (int)r.TotalHeight;
                });
                renderer.RenderScore(score, new List <double> {
                    track.Index
                });

                // write png
                var info = new FileInfo(args[0]);
                var path = Path.Combine(info.DirectoryName,
                                        Path.GetFileNameWithoutExtension(info.Name) + "-" + i + ".png");

                using var full = SKSurface.Create(new SKImageInfo(totalWidth, totalHeight,
                                                                  SKImageInfo.PlatformColorType, SKAlphaType.Premul));

                var y = 0;
                foreach (var image in images)
                {
                    full.Canvas.DrawImage(image, new SKRect(0, 0, image.Width, image.Height),
                                          new SKRect(0, y, image.Width, y + image.Height));
                    y += image.Height;
                }

                using var fullImage = full.Snapshot();
                using var data      = fullImage.Encode(SKEncodedImageFormat.Png, 100)
                                      .AsStream(true);
                using var fileStream =
                          new FileStream(path, FileMode.Create, FileAccess.Write);
                data.CopyTo(fileStream);
            }
        }
示例#20
0
        public virtual void Render()
        {
            if (glContext == null)
            {
                PrepareGLContexts();
            }

            EAGLContext.SetCurrentContext(glContext);

            // get the new surface size
            var newSize = lastSize;

            if (recreateSurface)
            {
                Gles.glGetRenderbufferParameteriv(Gles.GL_RENDERBUFFER, Gles.GL_RENDERBUFFER_WIDTH, out var bufferWidth);
                Gles.glGetRenderbufferParameteriv(Gles.GL_RENDERBUFFER, Gles.GL_RENDERBUFFER_HEIGHT, out var bufferHeight);
                newSize = new SKSizeI(bufferWidth, bufferHeight);
            }

            // manage the drawing surface
            if (recreateSurface || renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
            {
                // create or update the dimensions
                lastSize = newSize;

                // read the info from the buffer
                Gles.glGetIntegerv(Gles.GL_FRAMEBUFFER_BINDING, out var framebuffer);
                Gles.glGetIntegerv(Gles.GL_STENCIL_BITS, out var stencil);
                Gles.glGetIntegerv(Gles.GL_SAMPLES, out var samples);
                var maxSamples = context.GetMaxSurfaceSampleCount(colorType);
                if (samples > maxSamples)
                {
                    samples = maxSamples;
                }
                glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

                // destroy the old surface
                surface?.Dispose();
                surface = null;
                canvas  = null;

                // re-create the render target
                renderTarget?.Dispose();
                renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, stencil, glInfo);
            }

            // create the surface
            if (surface == null)
            {
                surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType);
                canvas  = surface.Canvas;
            }

            using (new SKAutoCanvasRestore(canvas, true))
            {
                // start drawing
#pragma warning disable CS0618 // Type or member is obsolete
                var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo);
                OnPaintSurface(e);
                DrawInSurface(e.Surface, e.RenderTarget);
                SKDelegate?.DrawInSurface(e.Surface, e.RenderTarget);
#pragma warning restore CS0618 // Type or member is obsolete
            }

            // flush the SkiaSharp context to the GL context
            canvas.Flush();
            context.Flush();

            // present the GL buffers
            glContext.PresentRenderBuffer(Gles.GL_RENDERBUFFER);
            EAGLContext.SetCurrentContext(null);
        }
示例#21
0
        void OnPaintSurface(SKSurface surface, int width, int height)
        {
            // Get the canvas
            SKCanvas canvas = surface.Canvas;

            // These two dimensions should be the same.
            int canvasSize = Math.Min(width, height);

            // If bitmap does not exist, create it
            if (bitmap == null)
            {
                // Set three fields
                bitmapSize   = canvasSize;
                bitmap       = new SKBitmap(bitmapSize, bitmapSize);
                bitmapCanvas = new SKCanvas(bitmap);

                // Establishes circular clipping and colors background
                PrepBitmap(bitmapCanvas, bitmapSize);
            }

            // If the canvas has become larger, make a new bitmap of that size.
            else if (bitmapSize < canvasSize)
            {
                // New versions of the three fields
                int      newBitmapSize   = canvasSize;
                SKBitmap newBitmap       = new SKBitmap(newBitmapSize, newBitmapSize);
                SKCanvas newBitmapCanvas = new SKCanvas(newBitmap);

                // New circular clipping and background
                PrepBitmap(newBitmapCanvas, newBitmapSize);

                // Copy old bitmap to new bitmap
                float diff = (newBitmapSize - bitmapSize) / 2f;
                newBitmapCanvas.DrawBitmap(bitmap, diff, diff);

                // Dispose old bitmap and its canvas
                bitmapCanvas.Dispose();
                bitmap.Dispose();

                // Set fields to new values
                bitmap       = newBitmap;
                bitmapCanvas = newBitmapCanvas;
                bitmapSize   = newBitmapSize;
            }

            // Clear the canvas
            canvas.Clear(SKColors.White);

            // Set the rotate transform
            float radius = canvasSize / 2;

            canvas.RotateDegrees(angle, radius, radius);

            // Set a circular clipping area
            clipPath.Reset();
            clipPath.AddCircle(radius, radius, radius);
            canvas.ClipPath(clipPath);

            // Draw the bitmap
            float offset = (canvasSize - bitmapSize) / 2f;

            canvas.DrawBitmap(bitmap, offset, offset);

            // Draw the cross hairs
            canvas.DrawLine(radius, 0, radius, canvasSize, thinLinePaint);
            canvas.DrawLine(0, radius, canvasSize, radius, thinLinePaint);
        }
示例#22
0
 public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info)
     : this(surface, info, info)
 {
 }
示例#23
0
 protected virtual void OnDrawFrame(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
 {
 }
示例#24
0
        public static Image buildBackground(string patternSource, Assembly assembly, int Width, int Height,
                                            double bottomAdjustment = GlobalStatusSingleton.PATTERN_PCT, double sideAdjustment = GlobalStatusSingleton.PATTERN_FULL_COVERAGE)
        {
            Image result = null;

            if ((Width == -1) || (Height == -1))
            {
                return(result);
            }

            using (var resource = assembly.GetManifestResourceStream(patternSource))
                using (var stream = new SKManagedStream(resource)) {
                    var bitmap    = SKBitmap.Decode(stream);
                    int tilesWide = (int)((Width * sideAdjustment) / bitmap.Width);
                    int tilesHigh = (int)((Height * bottomAdjustment) / bitmap.Height);

                    try {
                        using (var tempSurface = SKSurface.Create(new SKImageInfo((int)Width, (int)Height))) {
                            var canvas = tempSurface.Canvas;
                            canvas.Clear(SKColors.White);

                            SKBitmap bottomEdge = new SKBitmap();
                            SKBitmap rightEdge  = new SKBitmap();
                            SKBitmap corner     = new SKBitmap();
                            int      excessH    = (int)(Height * bottomAdjustment) - (tilesHigh * bitmap.Height);
                            int      excessW    = (int)(Width * sideAdjustment) - (tilesWide * bitmap.Width);
                            if (excessH > 0)
                            {
                                bitmap.ExtractSubset(bottomEdge, new SKRectI(0, 0, bitmap.Width, excessH));
                            }
                            if (excessW > 0)
                            {
                                bitmap.ExtractSubset(rightEdge, new SKRectI(0, 0, excessW, bitmap.Height));
                            }
                            if ((excessH > 0) && (excessW > 0))
                            {
                                bitmap.ExtractSubset(corner, new SKRectI(0, 0, excessW, excessH));
                            }

                            for (int i = 0; i < tilesWide; i++)
                            {
                                for (int j = 0; j < tilesHigh; j++)
                                {
                                    canvas.DrawBitmap(bitmap, SKRect.Create(i * bitmap.Width, j * bitmap.Height, bitmap.Width, bitmap.Height));
                                }
                                // this covers the bottom except lower right corner.
                                if (Height > tilesHigh * bitmap.Height)
                                {
                                    canvas.DrawBitmap(bottomEdge, SKRect.Create(i * bitmap.Width, tilesHigh * bitmap.Height, bitmap.Width, excessH));
                                }
                            }

                            // this is the far side, but not lower right corner.
                            if (Width > tilesWide * bitmap.Width)
                            {
                                for (int k = 0; k < tilesHigh; k++)
                                {
                                    canvas.DrawBitmap(rightEdge, SKRect.Create(tilesWide * bitmap.Width, k * bitmap.Height, excessW, bitmap.Height));
                                }
                            }

                            // and finally the bottom right corner.
                            if ((Height > tilesHigh * bitmap.Height) && (Width > tilesWide * bitmap.Width))
                            {
                                canvas.DrawBitmap(corner, SKRect.Create(tilesWide * bitmap.Width, tilesHigh * bitmap.Height, excessW, excessH));
                            }
                            SKImage skImage = tempSurface.Snapshot();
                            result = SKImageToXamarinImage(skImage);
                        }
                    } catch (Exception e) {
                        string msg = e.ToString();
                    }
                }
            return(result);
        }
示例#25
0
        public MapInfo GetMapInfo(double x, double y, IReadOnlyViewport viewport, IEnumerable <ILayer> layers, int margin = 0)
        {
            // todo: use margin to increase the pixel area

            // todo: We will need to select on style instead of layer
            layers = layers.Where(l => l.IsMapInfoLayer);

            var list   = new List <MapInfoRecord>();
            var result = new MapInfo()
            {
                ScreenPosition = new Point(x, y),
                WorldPosition  = viewport.ScreenToWorld(x, y),
                Resolution     = viewport.Resolution
            };

            try
            {
                var width  = (int)viewport.Width;
                var height = (int)viewport.Height;

                var imageInfo = new SKImageInfo(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Unpremul);

                var intX = (int)x;
                var intY = (int)y;

                using (var surface = SKSurface.Create(imageInfo))
                {
                    if (surface == null)
                    {
                        return(null);
                    }

                    surface.Canvas.ClipRect(new SKRect((float)(x - 1), (float)(y - 1), (float)(x + 1), (float)(y + 1)));
                    surface.Canvas.Clear(SKColors.Transparent);

                    var pixmap = surface.PeekPixels();
                    var color  = pixmap.GetPixelColor(intX, intY);

                    VisibleFeatureIterator.IterateLayers(viewport, layers, (v, layer, style, feature, opacity) => {
                        // 1) Clear the entire bitmap
                        surface.Canvas.Clear(SKColors.Transparent);
                        // 2) Render the feature to the clean canvas
                        RenderFeature(surface.Canvas, v, layer, style, feature, opacity);
                        // 3) Check if the pixel has changed.
                        if (color != pixmap.GetPixelColor(intX, intY))
                        {
                            // 4) Add feature and style to result
                            list.Add(new MapInfoRecord(feature, style, layer));
                        }
                    });
                }

                if (list.Count == 0)
                {
                    return(result);
                }

                list.Reverse();
                var itemDrawnOnTop = list.First();

                result.Feature        = itemDrawnOnTop.Feature;
                result.Style          = itemDrawnOnTop.Style;
                result.Layer          = itemDrawnOnTop.Layer;
                result.MapInfoRecords = list;
            }
            catch (Exception exception)
            {
                Logger.Log(LogLevel.Error, "Unexpected error in skia renderer", exception);
            }

            return(result);
        }
示例#26
0
        public static Image buildBackgroundFromBytes(byte[] patternSource, Assembly assembly, int Width, int Height,
                                                     double bottomAdjustment = GlobalStatusSingleton.PATTERN_PCT, double sideAdjustment = GlobalStatusSingleton.PATTERN_FULL_COVERAGE)
        {
            Image result = null;

            if ((Width == -1) || (Height == -1))
            {
                return(result);
            }
            if (patternSource == null)
            {
                return(result);
            }

            SKBitmap bitmap         = new SKBitmap(new SKImageInfo(Width, Height));
            var      bitmapFullSize = buildFixedRotationSKBitmapFromBytes(patternSource);

            if ((bitmapFullSize.Width > Width) || (bitmapFullSize.Height > Height))
            {
                // passed in image is larger than the screen.  shrink to fit.
                bitmapFullSize.Resize(bitmap, SKBitmapResizeMethod.Box);
            }
            else
            {
                bitmap = bitmapFullSize;
            }
            int tilesWide = (int)((Width * sideAdjustment) / bitmap.Width);
            int tilesHigh = (int)((Height * bottomAdjustment) / bitmap.Height);

            try {
                using (var tempSurface = SKSurface.Create(new SKImageInfo((int)Width, (int)Height))) {
                    var canvas = tempSurface.Canvas;
                    canvas.Clear(SKColors.White);

                    SKBitmap bottomEdge = new SKBitmap();
                    SKBitmap rightEdge  = new SKBitmap();
                    SKBitmap corner     = new SKBitmap();
                    int      excessH    = (int)(Height * bottomAdjustment) - (tilesHigh * bitmap.Height);
                    int      excessW    = (int)(Width * sideAdjustment) - (tilesWide * bitmap.Width);
                    if (excessH > 0)
                    {
                        bitmap.ExtractSubset(bottomEdge, new SKRectI(0, 0, bitmap.Width, excessH));
                    }
                    if (excessW > 0)
                    {
                        bitmap.ExtractSubset(rightEdge, new SKRectI(0, 0, excessW, bitmap.Height));
                    }
                    if ((excessH > 0) && (excessW > 0))
                    {
                        bitmap.ExtractSubset(corner, new SKRectI(0, 0, excessW, excessH));
                    }

                    for (int i = 0; i < tilesWide; i++)
                    {
                        for (int j = 0; j < tilesHigh; j++)
                        {
                            canvas.DrawBitmap(bitmap, SKRect.Create(i * bitmap.Width, j * bitmap.Height, bitmap.Width, bitmap.Height));
                        }
                        // this covers the bottom except lower right corner.
                        if (Height > tilesHigh * bitmap.Height)
                        {
                            canvas.DrawBitmap(bottomEdge, SKRect.Create(i * bitmap.Width, tilesHigh * bitmap.Height, bitmap.Width, excessH));
                        }
                    }
                    // this is the far side, but not lower right corner.
                    if (Width > tilesWide * bitmap.Width)
                    {
                        for (int k = 0; k < tilesHigh; k++)
                        {
                            canvas.DrawBitmap(rightEdge, SKRect.Create(tilesWide * bitmap.Width, k * bitmap.Height, excessW, bitmap.Height));
                        }
                    }
                    // and finally the bottom right corner.
                    if ((Height > tilesHigh * bitmap.Height) && (Width > tilesWide * bitmap.Width))
                    {
                        canvas.DrawBitmap(corner, SKRect.Create(tilesWide * bitmap.Width, tilesHigh * bitmap.Height, excessW, excessH));
                    }
                    SKImage skImage = tempSurface.Snapshot();
                    result = SKImageToXamarinImage(skImage);
                }
            } catch (Exception e) {
                string msg = e.ToString();
            }
            return(result);
        }
示例#27
0
 public SkiaDrawingContext(int width, int height, SKColor background, SKTypeface typeface)
 {
     this.typeface = typeface;
     surface       = SKSurface.Create(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Opaque);
     surface.Canvas.Clear(background);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="SkiaSharpDrawingContext"/> class.
 /// </summary>
 /// <param name="info">The information.</param>
 /// <param name="surface">The surface.</param>
 /// <param name="canvas">The canvas.</param>
 public SkiaSharpDrawingContext(SKImageInfo info, SKSurface surface, SKCanvas canvas)
 {
     Info    = info;
     Surface = surface;
     Canvas  = canvas;
 }
示例#29
0
        public new void DrawInRect(GLKView view, CGRect rect)
        {
            if (designMode)
            {
                return;
            }

            // create the contexts if not done already
            if (context == null)
            {
                var glInterface = GRGlInterface.Create();
                context = GRContext.CreateGl(glInterface);
            }

            // get the new surface size
            var newSize = new SKSizeI((int)DrawableWidth, (int)DrawableHeight);

            // manage the drawing surface
            if (renderTarget == null || lastSize != newSize || !renderTarget.IsValid)
            {
                // create or update the dimensions
                lastSize = newSize;

                // read the info from the buffer
                Gles.glGetIntegerv(Gles.GL_FRAMEBUFFER_BINDING, out var framebuffer);
                Gles.glGetIntegerv(Gles.GL_STENCIL_BITS, out var stencil);
                Gles.glGetIntegerv(Gles.GL_SAMPLES, out var samples);
                var maxSamples = context.GetMaxSurfaceSampleCount(colorType);
                if (samples > maxSamples)
                {
                    samples = maxSamples;
                }
                glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());

                // destroy the old surface
                surface?.Dispose();
                surface = null;
                canvas  = null;

                // re-create the render target
                renderTarget?.Dispose();
                renderTarget = new GRBackendRenderTarget(newSize.Width, newSize.Height, samples, stencil, glInfo);
            }

            // create the surface
            if (surface == null)
            {
                surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType);
                canvas  = surface.Canvas;
            }

            using (new SKAutoCanvasRestore(canvas, true))
            {
                // start drawing
                var e = new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo);
                OnPaintSurface(e);
#pragma warning disable CS0618 // Type or member is obsolete
                DrawInSurface(e.Surface, e.RenderTarget);
#pragma warning restore CS0618 // Type or member is obsolete
            }

            // flush the SkiaSharp contents to GL
            canvas.Flush();
            context.Flush();
        }
示例#30
0
 protected abstract void PaintSurface(SKSurface surface);