Exemplo n.º 1
0
        /// <inheritdoc/>
        public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation?orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
        {
            if (inputPath.Length == 0)
            {
                throw new ArgumentException("String can't be empty.", nameof(inputPath));
            }

            if (outputPath.Length == 0)
            {
                throw new ArgumentException("String can't be empty.", nameof(outputPath));
            }

            var skiaOutputFormat = GetImageFormat(selectedOutputFormat);

            var hasBackgroundColor = !string.IsNullOrWhiteSpace(options.BackgroundColor);
            var hasForegroundColor = !string.IsNullOrWhiteSpace(options.ForegroundLayer);
            var blur         = options.Blur ?? 0;
            var hasIndicator = options.AddPlayedIndicator || options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(0);

            using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace, autoOrient, orientation))
            {
                if (bitmap == null)
                {
                    throw new InvalidDataException($"Skia unable to read image {inputPath}");
                }

                var originalImageSize = new ImageDimensions(bitmap.Width, bitmap.Height);

                if (!options.CropWhiteSpace &&
                    options.HasDefaultOptions(inputPath, originalImageSize) &&
                    !autoOrient)
                {
                    // Just spit out the original file if all the options are default
                    return(inputPath);
                }

                var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize);

                var width  = newImageSize.Width;
                var height = newImageSize.Height;

                using (var resizedBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType))
                {
                    // scale image
                    bitmap.ScalePixels(resizedBitmap, SKFilterQuality.High);

                    // If all we're doing is resizing then we can stop now
                    if (!hasBackgroundColor && !hasForegroundColor && blur == 0 && !hasIndicator)
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
                        using (var outputStream = new SKFileWStream(outputPath))
                            using (var pixmap = new SKPixmap(new SKImageInfo(width, height), resizedBitmap.GetPixels()))
                            {
                                pixmap.Encode(outputStream, skiaOutputFormat, quality);
                                return(outputPath);
                            }
                    }

                    // create bitmap to use for canvas drawing used to draw into bitmap
                    using (var saveBitmap = new SKBitmap(width, height)) // , bitmap.ColorType, bitmap.AlphaType))
                        using (var canvas = new SKCanvas(saveBitmap))
                        {
                            // set background color if present
                            if (hasBackgroundColor)
                            {
                                canvas.Clear(SKColor.Parse(options.BackgroundColor));
                            }

                            // Add blur if option is present
                            if (blur > 0)
                            {
                                // create image from resized bitmap to apply blur
                                using (var paint = new SKPaint())
                                    using (var filter = SKImageFilter.CreateBlur(blur, blur))
                                    {
                                        paint.ImageFilter = filter;
                                        canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height), paint);
                                    }
                            }
                            else
                            {
                                // draw resized bitmap onto canvas
                                canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height));
                            }

                            // If foreground layer present then draw
                            if (hasForegroundColor)
                            {
                                if (!double.TryParse(options.ForegroundLayer, out double opacity))
                                {
                                    opacity = .4;
                                }

                                canvas.DrawColor(new SKColor(0, 0, 0, (byte)((1 - opacity) * 0xFF)), SKBlendMode.SrcOver);
                            }

                            if (hasIndicator)
                            {
                                DrawIndicator(canvas, width, height, options);
                            }

                            Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
                            using (var outputStream = new SKFileWStream(outputPath))
                            {
                                using (var pixmap = new SKPixmap(new SKImageInfo(width, height), saveBitmap.GetPixels()))
                                {
                                    pixmap.Encode(outputStream, skiaOutputFormat, quality);
                                }
                            }
                        }
                }
            }

            return(outputPath);
        }
Exemplo n.º 2
0
 public SavePhotoPage(SKPixmap skPixmap)
     : this()
 {
     pixmap = skPixmap;
 }
Exemplo n.º 3
0
        public static UIImage ToUIImage(this SKPixmap skiaPixmap, nfloat scale, UIImageOrientation orientation)
        {
            var cgImage = skiaPixmap.ToCGImage();

            return(new UIImage(cgImage, scale, orientation));
        }
Exemplo n.º 4
0
        public static UIImage ToUIImage(this SKPixmap skiaPixmap)
        {
            var cgImage = skiaPixmap.ToCGImage();

            return(new UIImage(cgImage));
        }
Exemplo n.º 5
0
        public static unsafe SKPixmap OtsuThreshold(this SKImage image)
        {
            SKPixmap pixmap = image.PeekPixels();
            byte *   bmpPtr = (byte *)pixmap.GetPixels().ToPointer();
            int      width  = image.Width;
            int      height = image.Height;

            int[]    intHistogram = new int[256];
            double[] histogram    = new double[256];
            int      threshold    = 0;

            // Build a histogram
            for (int row = 0; row < height; row++)
            {
                for (int col = 0; col < width; col++)
                {
                    byte red   = *bmpPtr++;
                    byte green = *bmpPtr++;
                    byte blue  = *bmpPtr++;

                    // Assuming SKColorType.Rgba8888 - used by iOS and Android
                    // (UWP uses SKColorType.Bgra8888)
                    int result = (byte)(0.2126 * red + 0.7152 * green + 0.0722 * blue);
                    intHistogram[result]++;
                }
            }

            int    pixelCount = width * height;
            double imageMean  = 0;

            for (int i = 0; i < 256; i++)
            {
                histogram[i] = (double)intHistogram[i] / pixelCount;
                imageMean   += histogram[i] * i;
            }

            double max        = double.MinValue;
            double c1Prob     = 0;
            double c2Prob     = 1;
            double c1MeanInit = 0;

            for (int i = 0; i < 256 && c2Prob > 0; i++)
            {
                double c1Mean        = c1MeanInit;
                double c2Mean        = (imageMean - (c1Mean * c1Prob)) / c2Prob;
                double classVariance = c1Prob * (1.0 - c1Prob) * Math.Pow(c1Mean - c2Mean, 2);

                if (classVariance > max)
                {
                    max       = classVariance;
                    threshold = i;
                }

                c1MeanInit *= c1Prob;
                c1Prob     += histogram[i];
                c2Prob     -= histogram[i];
                c1MeanInit += (double)i * (double)histogram[i];

                if (Math.Abs(c1Prob) > 0)
                {
                    c1MeanInit /= c1Prob;
                }
            }

            bmpPtr = (byte *)pixmap.GetPixels().ToPointer();

            // Apply threshold
            for (int row = 0; row < height; row++)
            {
                for (int col = 0; col < width; col++)
                {
                    if (*bmpPtr <= threshold)
                    {
                        *bmpPtr++ = 0; // red
                        *bmpPtr++ = 0; // green
                        *bmpPtr++ = 0; // blue
                    }
                    else
                    {
                        *bmpPtr++ = 255; // red
                        *bmpPtr++ = 255; // green
                        *bmpPtr++ = 255; // blue
                    }
                    bmpPtr += 1;
                }
            }

            return(pixmap);
        }
Exemplo n.º 6
0
 public static CIImage ToCIImage(this SKPixmap skiaPixmap)
 {
     return(skiaPixmap.ToCGImage());
 }
Exemplo n.º 7
0
        private static void CompareVisualResult(double totalWidth, double totalHeight,
                                                List <RenderFinishedEventArgs> result, string referenceFileName,
                                                Uint8Array referenceFileData, string?message)
        {
            // TODO: get Skia to render like Chrome
            // https://github.com/mono/SkiaSharp/issues/1253
            return;

            // ReSharper disable once HeuristicUnreachableCode
#pragma warning disable 162
            SKBitmap finalBitmap;

            using (var finalImageSurface = SKSurface.Create(new SKImageInfo((int)totalWidth,
                                                                            (int)totalHeight,
                                                                            SKImageInfo.PlatformColorType, SKAlphaType.Premul)))
            {
                var point     = new SKPoint();
                var rowHeight = 0;
                foreach (var partialResult in result)
                {
                    var partialCanvas = partialResult.RenderResult;
                    if (partialCanvas is SKImage img)
                    {
                        finalImageSurface.Canvas.DrawImage(img, point);
                        if (partialResult.Height > rowHeight)
                        {
                            rowHeight = img.Height;
                        }

                        point.X += img.Width;

                        if (point.X >= totalWidth)
                        {
                            point.X   = 0;
                            point.Y  += rowHeight;
                            rowHeight = 0;
                        }
                    }
                }

                using var finalImage = finalImageSurface.Snapshot();
                finalBitmap          = SKBitmap.FromImage(finalImage);
            }

            var finalImageFileName = Path.ChangeExtension(referenceFileName, ".new.png");
            using (finalBitmap)
            {
                var dir = Path.GetDirectoryName(finalImageFileName);
                Directory.CreateDirectory(dir);

                using (var fileStream = new SKFileWStream(finalImageFileName))
                {
                    SKPixmap.Encode(fileStream, finalBitmap, SKEncodedImageFormat.Png, 100);
                }

                SKBitmap referenceBitmap;
                using (var data = SKData.CreateCopy(referenceFileData.Buffer.Raw))
                {
                    referenceBitmap = SKBitmap.Decode(data);
                }

                using (referenceBitmap)
                {
                    var compareResult = PixelMatch.Run(finalBitmap, referenceBitmap,
                                                       new PixelMatchOptions
                    {
                        Threshold         = 0.8,
                        IncludeAntiAlias  = false,
                        IgnoreTransparent = true,
                        CreateOutputImage = true
                    });


                    using (compareResult.Output)
                    {
                        Assert.IsTrue(compareResult.SizesMatch, "Dimensions differ");
                        if (compareResult.Mismatch > 0.01)
                        {
                            var diffImageName =
                                Path.ChangeExtension(referenceFileName, ".diff.png");
                            using (var fileStream = new SKFileWStream(diffImageName))
                            {
                                SKPixmap.Encode(fileStream, compareResult.Output,
                                                SKEncodedImageFormat.Png, 100);
                            }

                            Assert.Fail(
                                $"Difference between original and new image is too big: {compareResult.Mismatch:P}, {compareResult.DifferentPixels}/{compareResult.TotalPixels}");
                        }
                    }
                }
            }

            File.Delete(finalImageFileName);
#pragma warning restore 162
        }
Exemplo n.º 8
0
        static unsafe SKPixmap ToRGBAPixmap(this SKImage image, float[,] y, float[,] cb, float[,] cr, float[,] a)
        {
            if (y == null)
            {
                throw new ArgumentException("y can't be null");
            }
            if (cb == null)
            {
                throw new ArgumentException("cb can't be null");
            }
            if (cr == null)
            {
                throw new ArgumentException("cr can't be null");
            }
            if (a == null)
            {
                throw new ArgumentException("a can't be null");
            }

            SKPixmap pixmap = image.PeekPixels();
            byte *   bmpPtr = (byte *)pixmap.GetPixels().ToPointer();
            int      width  = image.Width;
            int      height = image.Height;

            for (int row = 0; row < height; row++)
            {
                for (int col = 0; col < width; col++)
                {
                    float yValue  = y[col, row];
                    float cbValue = cb[col, row] - 127.5f;
                    float crValue = cr[col, row] - 127.5f;
                    float aValue  = a[col, row];

                    int red   = (int)(yValue + 1.40200f * crValue + 0.5f);
                    int green = (int)(yValue - 0.34414f * cbValue - 0.71417f * crValue + 0.5f);
                    int blue  = (int)(yValue + 1.77200f * cbValue + 0.5f);
                    int alpha = (int)aValue;

                    if (red < 0)
                    {
                        red = 0;
                    }
                    else if (red > 255)
                    {
                        red = 255;
                    }

                    if (green < 0)
                    {
                        green = 0;
                    }
                    else if (green > 255)
                    {
                        green = 255;
                    }

                    if (blue < 0)
                    {
                        blue = 0;
                    }
                    else if (blue > 255)
                    {
                        blue = 255;
                    }

                    if (alpha < 0)
                    {
                        alpha = 0;
                    }
                    else if (alpha > 255)
                    {
                        alpha = 255;
                    }

                    *bmpPtr++ = (byte)red;
                    *bmpPtr++ = (byte)green;
                    *bmpPtr++ = (byte)blue;
                    *bmpPtr++ = (byte)alpha;
                }
            }
            return(pixmap);
        }
Exemplo n.º 9
0
 public static IHtmlContent Render(this SKPixmap pixmap)
 {
     using var image = SKImage.FromPixels(pixmap);
     return(Render(image));
 }
Exemplo n.º 10
0
        private void UpdateMarkerIcon(SKPin pin, Marker marker)
        {
            SKPixmap markerBitmap = DrawMarker(pin);

            marker.SetIcon(BitmapDescriptorFactory.FromBitmap(markerBitmap.ToBitmap()));
        }
Exemplo n.º 11
0
        public async Task <DataResolverResult> Resolve(string identifier, TaskParameter parameters, CancellationToken token)
        {
            ImageSource source = parameters.Source;

            if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier)
            {
                source = parameters.LoadingPlaceholderSource;
            }
            else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier)
            {
                source = parameters.ErrorPlaceholderSource;
            }

            var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory())
                               .GetResolver(identifier, source, parameters, Configuration)
                               .Resolve(identifier, parameters, token).ConfigureAwait(false);

            if (resolvedData?.Stream == null)
            {
                throw new FileNotFoundException(identifier);
            }

            var svg = new SKSvg()
            {
                ThrowOnUnsupportedElement = false,
            };
            SKPicture picture;

            if (ReplaceStringMap == null || ReplaceStringMap.Count == 0)
            {
                using (var svgStream = resolvedData.Stream)
                {
                    picture = svg.Load(svgStream);
                }
            }
            else
            {
                using (var svgStream = resolvedData.Stream)
                    using (var reader = new StreamReader(svgStream))
                    {
                        var inputString = await reader.ReadToEndAsync();

                        foreach (var map in ReplaceStringMap
                                 .Where(v => v.Key.StartsWith("regex:")))
                        {
                            inputString = Regex.Replace(inputString, map.Key.Substring(6), map.Value);
                        }

                        var builder = new StringBuilder(inputString);

                        foreach (var map in ReplaceStringMap
                                 .Where(v => !v.Key.StartsWith("regex:", StringComparison.OrdinalIgnoreCase)))
                        {
                            builder.Replace(map.Key, map.Value);
                        }

                        using (var svgFinalStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
                        {
                            picture = svg.Load(svgFinalStream);
                        }
                    }
            }

            double sizeX = 0;
            double sizeY = 0;

            if (VectorWidth <= 0 && VectorHeight <= 0)
            {
                if (picture.CullRect.Width > 0)
                {
                    sizeX = picture.CullRect.Width;
                }
                else
                {
                    sizeX = 300;
                }

                if (picture.CullRect.Height > 0)
                {
                    sizeY = picture.CullRect.Height;
                }
                else
                {
                    sizeY = 300;
                }
            }
            else if (VectorWidth > 0 && VectorHeight > 0)
            {
                sizeX = VectorWidth;
                sizeY = VectorHeight;
            }
            else if (VectorWidth > 0)
            {
                sizeX = VectorWidth;
                sizeY = (VectorWidth / picture.CullRect.Width) * picture.CullRect.Height;
            }
            else
            {
                sizeX = (VectorHeight / picture.CullRect.Height) * picture.CullRect.Width;
                sizeY = VectorHeight;
            }

            if (UseDipUnits)
            {
                sizeX = sizeX.DpToPixels();
                sizeY = sizeY.DpToPixels();
            }

            resolvedData.ImageInformation.SetType(ImageInformation.ImageType.SVG);

            using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY)))
                using (var canvas = new SKCanvas(bitmap))
                    using (var paint = new SKPaint())
                    {
                        canvas.Clear(SKColors.Transparent);
                        float scaleX = (float)sizeX / picture.CullRect.Width;
                        float scaleY = (float)sizeY / picture.CullRect.Height;
                        var   matrix = SKMatrix.MakeScale(scaleX, scaleY);
                        canvas.DrawPicture(picture, ref matrix, paint);
                        canvas.Flush();
#if __IOS__
                        var     info = bitmap.Info;
                        CGImage cgImage;
                        IntPtr  size;
                        using (var provider = new CGDataProvider(bitmap.GetPixels(out size), size.ToInt32()))
                            using (var colorSpace = CGColorSpace.CreateDeviceRGB())
                                using (cgImage = new CGImage(info.Width, info.Height, 8, info.BitsPerPixel, info.RowBytes,
                                                             colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big,
                                                             provider, null, false, CGColorRenderingIntent.Default))
                                {
                                    IDecodedImage <object> container = new DecodedImage <object>()
                                    {
                                        Image = new UIImage(cgImage),
                                    };
                                    return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation));
                                }
#elif __MACOS__
                        var     info = bitmap.Info;
                        CGImage cgImage;
                        IntPtr  size;
                        using (var provider = new CGDataProvider(bitmap.GetPixels(out size), size.ToInt32()))
                            using (var colorSpace = CGColorSpace.CreateDeviceRGB())
                                using (cgImage = new CGImage(info.Width, info.Height, 8, info.BitsPerPixel, info.RowBytes,
                                                             colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big,
                                                             provider, null, false, CGColorRenderingIntent.Default))
                                {
                                    IDecodedImage <object> container = new DecodedImage <object>()
                                    {
                                        Image = new NSImage(cgImage, CGSize.Empty),
                                    };
                                    return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation));
                                }
#elif __ANDROID__
                        using (var skiaPixmap = bitmap.PeekPixels())
                        {
                            var info = skiaPixmap.Info;

                            // destination values
                            var config  = Bitmap.Config.Argb8888;
                            var dstInfo = new SKImageInfo(info.Width, info.Height);

                            // try keep the pixel format if we can
                            switch (info.ColorType)
                            {
                            case SKColorType.Alpha8:
                                config            = Bitmap.Config.Alpha8;
                                dstInfo.ColorType = SKColorType.Alpha8;
                                break;

                            case SKColorType.Rgb565:
                                config            = Bitmap.Config.Rgb565;
                                dstInfo.ColorType = SKColorType.Rgb565;
                                dstInfo.AlphaType = SKAlphaType.Opaque;
                                break;

                            case SKColorType.Argb4444:
                                config            = Bitmap.Config.Argb4444;
                                dstInfo.ColorType = SKColorType.Argb4444;
                                break;
                            }

                            // destination bitmap
                            var bmp = Bitmap.CreateBitmap(info.Width, info.Height, config);
                            var ptr = bmp.LockPixels();

                            // copy
                            var success = skiaPixmap.ReadPixels(dstInfo, ptr, dstInfo.RowBytes);

                            // confirm
                            bmp.UnlockPixels();
                            if (!success)
                            {
                                bmp.Recycle();
                                bmp.Dispose();
                                bmp = null;
                            }

                            IDecodedImage <object> container = new DecodedImage <object>()
                            {
                                Image = bmp,
                            };
                            return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation));
                        }
#elif __WINDOWS__
                        if (parameters.Transformations == null || parameters.Transformations.Count == 0)
                        {
                            WriteableBitmap writeableBitmap = null;

                            await Configuration.MainThreadDispatcher.PostAsync(async() =>
                            {
                                using (var skiaImage = SKImage.FromPixels(bitmap.PeekPixels()))
                                {
                                    var info        = new SKImageInfo(skiaImage.Width, skiaImage.Height);
                                    writeableBitmap = new WriteableBitmap(info.Width, info.Height);

                                    var buffer = writeableBitmap.PixelBuffer as IBufferByteAccess;
                                    if (buffer == null)
                                    {
                                        throw new InvalidCastException("Unable to convert WriteableBitmap.PixelBuffer to IBufferByteAccess.");
                                    }

                                    IntPtr ptr;
                                    var hr = buffer.Buffer(out ptr);
                                    if (hr < 0)
                                    {
                                        throw new InvalidCastException("Unable to retrieve pixel address from WriteableBitmap.PixelBuffer.");
                                    }

                                    using (var pixmap = new SKPixmap(info, ptr))
                                    {
                                        skiaImage.ReadPixels(pixmap, 0, 0);
                                    }
                                    writeableBitmap.Invalidate();
                                }
                            });

                            IDecodedImage <object> container = new DecodedImage <object>()
                            {
                                Image = writeableBitmap,
                            };
                            return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation));
                        }
#endif
                        lock (_encodingLock)
                        {
                            using (var image = SKImage.FromBitmap(bitmap))
                                //using (var data = image.Encode(SKImageEncodeFormat.Png, 100))  //TODO disabled because of https://github.com/mono/SkiaSharp/issues/285
                                using (var data = image.Encode())
                                {
                                    var stream = new MemoryStream();
                                    data.SaveTo(stream);
                                    stream.Position = 0;
                                    return(new DataResolverResult(stream, resolvedData.LoadingResult, resolvedData.ImageInformation));
                                }
                        }
                    }
        }
        public void DrawImage(Image img, Rectangle rectangle, float srcX, float srcY, float srcWidth, float srcHeight,
                              GraphicsUnit graphicsUnit, ImageAttributes tileFlipXYAttributes)
        {
            var coltype = SKColorType.Bgra8888;

            ((Bitmap)img).MakeTransparent(Color.Transparent);
            var data = ((Bitmap)img).LockBits(new Rectangle(0, 0, img.Width, img.Height),
                                              ImageLockMode.ReadOnly,
                                              SKColorType.Bgra8888);

            if (CompositingMode == CompositingMode.SourceOver)
            {
                _paint.BlendMode = SKBlendMode.SrcOver;
            }
            if (CompositingMode == CompositingMode.SourceCopy)
            {
                _paint.BlendMode = SKBlendMode.Src;
            }
            //if(img.PixelFormat == PixelFormat.Format32bppArgb)
            _paint.Color = SKColors.Black;



            var imginfo = new SKImageInfo(img.Width, img.Height, coltype, SKAlphaType.Premul);

            var pxmap = new SKPixmap(imginfo, data.Scan0, data.Stride);

            var image = SKImage.FromPixels(pxmap);

            if (image == null)
            {
                return;
            }


            _image.DrawImage(image, new SKRect(srcX, srcY, srcX + srcWidth, srcY + srcHeight),
                             new SKRect(rectangle.X, rectangle.Y, rectangle.Right, rectangle.Bottom), _paint);
            ((Bitmap)img).UnlockBits(data);
            data = null;

            return;

            try
            {
                using (var skbmp =
                           new SKBitmap(new SKImageInfo(img.Width, img.Height, coltype, SKAlphaType.Unpremul)))
                {
                    skbmp.SetPixels(data.Scan0);



                    _image.DrawBitmap(skbmp, new SKRect(srcX, srcY, srcX + srcWidth, srcY + srcHeight),
                                      new SKRect(rectangle.X, rectangle.Y, rectangle.Right, rectangle.Bottom), _paint);
                }
            }
            catch
            {
            }

            ((Bitmap)img).UnlockBits(data);
            data = null;
        }
 public static string Serialize(SKPixmap image, int componentsX, int componentsY)
 {
     using var wrapper = SKImage.FromPixels(image);
     return(Serialize(wrapper, componentsX, componentsY));
 }
Exemplo n.º 14
0
        public byte[] GetImage(string referenceName, int zoomLevel, int chunk)
        {
            var refer  = _service._references.First(r => r.Name == referenceName);
            var height = (_service._histograms[refer.Name].Max() + 1) * 15;

            using var surface     = SKSurface.Create(new SKImageInfo(WIDTH, height));
            using SKCanvas canvas = surface.Canvas;
            canvas.Clear();

            using SKPaint paint = new SKPaint
                  {
                      Style       = SKPaintStyle.Stroke,
                      Color       = SKColors.Black,
                      StrokeWidth = 1
                  };

            using SKPaint fillPaint = new SKPaint
                  {
                      Style       = SKPaintStyle.Fill,
                      Color       = SKColors.Blue,
                      StrokeWidth = 1
                  };

            using SKPaint reverseFillPaint = new SKPaint
                  {
                      Style       = SKPaintStyle.Fill,
                      Color       = SKColors.Red,
                      StrokeWidth = 1
                  };

            var startY = 7;
            var list   = new List <long> {
                0
            };

            using var reader = new StreamReader($"{_service._references.IndexOf(refer)}.tmp");
            string line;

            while ((line = reader.ReadLine()) != null)
            {
                var splitLine = line.Split('\t');

                var read = new SamFile
                {
                    QueryName       = splitLine[0],
                    ReferenceName   = splitLine[1],
                    StartingPos     = int.Parse(splitLine[2]),
                    DrawExpressions = DataService.GetDrawExpressions(splitLine[3]),
                    Reverse         = bool.Parse(splitLine[4])
                };

                var realStartingX = zoomLevel * read.StartingPos;

                if (realStartingX >= (chunk + 1) * WIDTH)
                {
                    break;
                }

                var index      = list.FindIndex(i => realStartingX > i + 1);
                var y          = startY * (index != -1 ? index : list.Count);
                var lineLength = read.DrawExpressions.Sum(de => de.Length) * zoomLevel;

                if (index == -1)
                {
                    list.Add(realStartingX + lineLength);
                }
                else
                {
                    list[index] = realStartingX + lineLength;
                }

                realStartingX -= chunk * WIDTH;

                if (realStartingX < 0 && realStartingX + lineLength < 0)
                {
                    continue;
                }

                canvas.DrawLine(new SKPoint(realStartingX, y + 3), new SKPoint(realStartingX + lineLength, y + 3), paint);

                var currentX = realStartingX;
                foreach (var draw in read.DrawExpressions)
                {
                    if (draw.Type == DrawType.Rectangle)
                    {
                        canvas.DrawRect(currentX, y, draw.Length * zoomLevel, 5, read.Reverse ? reverseFillPaint : fillPaint);
                        canvas.DrawRect(currentX, y, draw.Length * zoomLevel, 5, paint);
                    }
                    currentX += draw.Length * zoomLevel;
                }

                canvas.Flush();
            }

            var      width      = (chunk + 1) * WIDTH * zoomLevel > refer.Length * zoomLevel ? refer.Length * zoomLevel % WIDTH : WIDTH;
            var      realHeight = 7 * (list.Count + 1);
            SKPixmap pixmap     = surface.Snapshot().Subset(SKRectI.Create(0, 0, width, realHeight)).PeekPixels();

            SKData data;

            if (realHeight > 15000)
            {
                data = pixmap.Encode(SKPngEncoderOptions.Default);
            }
            else
            {
                var options = new SKWebpEncoderOptions(SKWebpEncoderCompression.Lossless, 100);
                data = pixmap.Encode(options);
            }

            return(data.ToArray());
        }
Exemplo n.º 15
0
        public SKData DrawHistogram(string referenceName, int zoom, int chunk)
        {
            var refer = _service._references.FirstOrDefault(r => r.Name == referenceName);

            if (chunk == 0 && zoom == 10)
            {
                LoadReference(referenceName);
            }

            using var surface     = SKSurface.Create(new SKImageInfo(refer.Length * zoom, 220));
            using SKCanvas canvas = surface.Canvas;

            canvas.Clear();

            using SKPaint paint = new SKPaint
                  {
                      Style       = SKPaintStyle.StrokeAndFill,
                      Color       = SKColors.Blue,
                      StrokeWidth = 1
                  };

            using SKPaint linePaint = new SKPaint
                  {
                      Style       = SKPaintStyle.Stroke,
                      Color       = SKColors.Black,
                      StrokeWidth = 1
                  };

            using SKPaint dashPaint = new SKPaint
                  {
                      Style       = SKPaintStyle.Stroke,
                      Color       = SKColors.Black,
                      StrokeWidth = 1,
                      PathEffect  = SKPathEffect.CreateDash(new[] { 20f, 5f }, 0)
                  };

            var histData = _service._histograms[refer.Name];

            var scale = (float)(100 / histData.Average());

            for (int i = 0; i < refer.Length; i++)
            {
                canvas.DrawRect(i * zoom + 5, 200 - (histData[i] * scale), zoom, histData[i] * scale, paint);
            }

            canvas.DrawLine(5, 0, 5, 200, linePaint);
            canvas.DrawLine(5, 199, refer.Length * zoom, 199, linePaint);

            var average = (int)(Math.Round(histData.Average()));

            canvas.DrawLine(5, average * scale, refer.Length * zoom, average * scale, dashPaint);

            using SKPaint textPaint = new SKPaint
                  {
                      Style        = SKPaintStyle.StrokeAndFill,
                      Color        = SKColors.Black,
                      StrokeWidth  = 1,
                      TextSize     = 20,
                      Typeface     = SKTypeface.FromFamilyName("Courier New"),
                      SubpixelText = true
                  };
            canvas.DrawText(average.ToString(), 6, average * scale - 2, textPaint);

            var cnt = textPaint.MeasureText("ACGT");

            if (zoom == 10)
            {
                textPaint.TextSize = textPaint.TextSize * 40 / cnt;
                var shaper = new SKShaper(SKTypeface.FromFamilyName("Courier New"));

                canvas.DrawShapedText(shaper, reference, 5, 215, textPaint);
            }

            var      width  = (chunk + 1) * WIDTH * zoom > refer.Length * zoom ? refer.Length * zoom % WIDTH : WIDTH;
            SKPixmap pixmap = surface.Snapshot().Subset(SKRectI.Create(chunk * WIDTH, 0, width, canvas.DeviceClipBounds.Height)).PeekPixels();

            var options = new SKWebpEncoderOptions(SKWebpEncoderCompression.Lossless, 100);

            return(pixmap.Encode(options));
        }