private void CreateResizedImage() { using var image = _surface.Snapshot(); var boundary = SKRectI.Create(0, 0, Width, Height); Result = image.Subset(boundary); }
async Task ProcessImage(MediaFile image) { if (image != null) { //ImageCollection.Add(image); //if (this.PhotoCommandParameter.PhotoType == PhotoTypes.CUSTOMER_PHOTO) //{ var bitmap = SKBitmap.Decode(image.GetStreamWithImageRotatedForExternalStorage()); var altImage = SKImage.FromBitmap(bitmap); var length = Math.Min(bitmap.Width, bitmap.Height); var subset = altImage.Subset(SKRectI.Create((bitmap.Width - length) / 2, (bitmap.Height - length) / 2, length, length)); ImageStream = subset.Encode(SKEncodedImageFormat.Jpeg, 100).AsStream(); //} //else //{ // ImageStream = image.GetStreamWithImageRotatedForExternalStorage(); //} IsAcceptVisible = true; try { // TODO: load image from Azure //ImageSource = AzureStorage.GetImageSource(ImageStream); } catch //(Exception ex) { //Logger.I.LogError(ex, "An error occured while processing the image"); } } }
private void Initialize(IEnumerable <Layer> layers, string undoChangeLocation, bool saveOnStartup, bool useDocumentSize = false) { var layersArray = layers as Layer[] ?? layers.ToArray(); LayerChunk[] layerChunks = new LayerChunk[layersArray.Length]; for (var i = 0; i < layersArray.Length; i++) { var layer = layersArray[i]; int width = layer.Width; int height = layer.Height; int offsetX = layer.OffsetX; int offsetY = layer.OffsetY; if (useDocumentSize) { width = layer.MaxWidth; height = layer.MaxHeight; offsetX = 0; offsetY = 0; } layerChunks[i] = new LayerChunk(layer, SKRectI.Create(offsetX, offsetY, width, height)); layersToStore.Add(layer.GuidValue); } UndoChangeLocation = undoChangeLocation; GenerateUndoLayers(layerChunks); if (saveOnStartup) { SaveLayersOnDevice(); } }
protected void OnDrawSample(SKCanvas canvas, int width, int height) { canvas.Clear(SKColors.White); // decode the bitmap var desiredInfo = new SKImageInfo(386, 395, SKImageInfo.PlatformColorType, SKAlphaType.Premul); using (var stream = new SKManagedStream(SampleMedia.Images.BabyTux)) using (var bitmap = SKBitmap.Decode(stream, desiredInfo)) { // draw directly on the bitmap using (var annotationCanvas = new SKCanvas(bitmap)) using (var paint = new SKPaint()) { paint.StrokeWidth = 3; paint.Color = SampleMedia.Colors.XamarinLightBlue; paint.Style = SKPaintStyle.Stroke; var face = SKRectI.Create(100, 50, 190, 170); annotationCanvas.DrawRect(face, paint); } // draw the modified bitmap to the screen canvas.DrawBitmap(bitmap, 10, 10); } }
public void Crop(int size) { int width, height; if (_bitmap.Width > _bitmap.Height) { height = size; width = _bitmap.Width * size / _bitmap.Height; } else { width = size; height = _bitmap.Height * size / _bitmap.Width; } using (var resizedBitmap = _bitmap.Resize(new SKImageInfo(width, height), SKFilterQuality.High)) { int x = (width - size) / 2; int y = (height - size) / 2; var image = SKImage.FromBitmap(resizedBitmap); _image = image.Subset(SKRectI.Create(x, y, size, size)); _bitmap = SKBitmap.FromImage(_image); } }
public static SKBitmap CropImageAtMidPoint(SKBitmap inImg) { int w = inImg.Width; int h = inImg.Height; int shortestLen = 0; int longestLen = 0; int x = 0; int y = 0; if (w < h) { shortestLen = w; longestLen = h; x = 0; y = (h - w) / 2; } else if (h < w) { shortestLen = h; longestLen = w; y = 0; x = (w - h) / 2; } else { // already square. return. return(inImg); } SKRectI square = SKRectI.Create(x, y, shortestLen, shortestLen); SKBitmap finalBmp = new SKBitmap(shortestLen, shortestLen); Debug.WriteLine("DHB:GlobalSingletonHelpers:rotateAndCrop pre extract"); inImg.ExtractSubset(finalBmp, square); return(finalBmp); }
private static byte[] CreateThumbnail(Pattern pattern, int thumbnailWidth, int thumbnailHeight) { var size = GetStitchSize((int)pattern.Width, (int)pattern.Height, thumbnailWidth, thumbnailHeight); var width = pattern.Width * size; var height = pattern.Height * size; var bitmap = new SKBitmap((int)width, (int)height); var canvas = new SKCanvas(bitmap); canvas.Clear(); foreach (var stitch in pattern.Stitches) { var configuration = pattern.Configurations[stitch.ConfigurationIndex]; var paint = new SKPaint { Color = SKColor.Parse(configuration.HexColor) }; var rect = new SKRect { Left = stitch.X * size, Top = stitch.Y * size, Right = (stitch.X + 1) * size, Bottom = (stitch.Y + 1) * size }; canvas.DrawRect(rect, paint); } var x = (int)(width - thumbnailWidth) / 2; var y = (int)(height - thumbnailHeight) / 2; var image = SKImage.FromBitmap(bitmap).Subset(SKRectI.Create(x, y, thumbnailWidth, thumbnailHeight)); return(image.Encode(SKEncodedImageFormat.Png, 100).ToArray()); }
// Preprocess the quadrants of the input image public void ProcessInputImageColors(int tileWidth, int tileHeight) { using (var skStream = new SKManagedStream(inputStream)) using (var bitmap = SKBitmap.Decode(skStream)) { int xTileCount = bitmap.Width / tileWidth; int yTileCount = bitmap.Height / tileHeight; int tileDivisionWidth = tileWidth / quadrantDivisionCount; int tileDivisionHeight = tileHeight / quadrantDivisionCount; int quadrantsCompleted = 0; int quadrantsTotal = xTileCount * yTileCount * quadrantDivisionCount * quadrantDivisionCount; inputImageRGBGrid = new SKColor[xTileCount, yTileCount][, ]; //Divide the input image into separate tile sections and calculate the average pixel value for each one for (int yTileIndex = 0; yTileIndex < yTileCount; yTileIndex++) { for (int xTileIndex = 0; xTileIndex < xTileCount; xTileIndex++) { var rect = SKRectI.Create(xTileIndex * tileWidth, yTileIndex * tileHeight, tileWidth, tileHeight); inputImageRGBGrid[xTileIndex, yTileIndex] = GetAverageColorGrid(bitmap, rect); quadrantsCompleted += (quadrantDivisionCount * quadrantDivisionCount); } } } }
private void InitializeStorageBasedChange(SKRectI toolSessionRect) { Document doc = ViewModels.ViewModelMain.Current.BitmapManager.ActiveDocument; var toolSize = Toolbar.GetSetting <SizeSetting>("ToolSize"); SKRectI finalRect = toolSessionRect; if (toolSize != null && toolSize.Value > 1) { int halfSize = (int)Math.Ceiling(toolSize.Value / 2f); finalRect.Inflate(halfSize, halfSize); } if (toolSessionRect.IsEmpty) { finalRect = SKRectI.Create(doc.ActiveLayer.OffsetX, doc.ActiveLayer.OffsetY, doc.ActiveLayer.Width, doc.ActiveLayer.Height); } if (UseDocumentRectForUndo) { finalRect = SKRectI.Create(0, 0, doc.Width, doc.Height); } if (_customRectReported) { _customRectReported = false; finalRect = _rectReportedByTool; _rectReportedByTool = SKRectI.Empty; } _change = new StorageBasedChange(doc, new[] { new LayerChunk(doc.ActiveLayer, finalRect) }); }
public void SaveLayersOnDevice() { int i = 0; foreach (var layerGuid in layersToStore) { Layer layer = Document.Layers.First(x => x.GuidValue == layerGuid); UndoLayer storedLayer = StoredLayers[i]; if (Directory.Exists(Path.GetDirectoryName(storedLayer.StoredPngLayerName))) { // Calculate absolute rect to relative rect SKRectI finalRect = SKRectI.Create( storedLayer.SerializedRect.Left - layer.OffsetX, storedLayer.SerializedRect.Top - layer.OffsetY, storedLayer.SerializedRect.Width, storedLayer.SerializedRect.Height); using var image = layer.LayerBitmap.SkiaSurface.Snapshot(); using Surface targetSizeSurface = new Surface(finalRect.Width, finalRect.Height); targetSizeSurface.SkiaSurface.Canvas.DrawImage(image, finalRect, SKRect.Create(0, 0, finalRect.Width, finalRect.Height), Surface.ReplacingPaint); //DebugSavePng(targetSizeSurface, storedLayer); Exporter.SaveAsGZippedBytes(storedLayer.StoredPngLayerName, targetSizeSurface); } i++; } layersToStore = new List <Guid>(); }
public void RectIteratorHasCorrectRects() { var rectA = SKRectI.Create(10, 10, 100, 100); var rectB = SKRectI.Create(50, 50, 100, 100); using var region = new SKRegion(rectA); region.Op(rectB, SKRegionOperation.Union); using var iterator = region.CreateRectIterator(); Assert.True(iterator.Next(out var rect)); Assert.Equal(SKRectI.Create(10, 10, 100, 40), rect); Assert.True(iterator.Next(out rect)); Assert.Equal(SKRectI.Create(10, 50, 140, 60), rect); Assert.True(iterator.Next(out rect)); Assert.Equal(SKRectI.Create(50, 110, 100, 40), rect); Assert.False(iterator.Next(out rect)); Assert.Equal(SKRect.Empty, rect); Assert.False(iterator.Next(out rect)); Assert.Equal(SKRect.Empty, rect); }
protected override void OnDrawSample(SKCanvas canvas, int width, int height) { canvas.Clear(SKColors.White); if (bitmap != null) { var bmpRect = SKRectI.Create(width, height).AspectFit(bitmap.Info.Size); using (var resized = new SKBitmap(bmpRect.Width, bmpRect.Height)) using (var paint = new SKPaint()) { bitmap.Resize(resized, method); canvas.DrawBitmap(resized, bmpRect); paint.TextAlign = SKTextAlign.Center; paint.TextSize = 36; paint.IsAntialias = true; paint.Color = new SKColor(0, 0, 0, 127); canvas.DrawRect(new SKRect(0, 0, width, (paint.TextSize * 2) + 30), paint); paint.Color = SKColors.White; canvas.DrawText(method.ToString(), width / 2, paint.TextSize + 10, paint); canvas.DrawText("(tap to change)", width / 2, (paint.TextSize * 2) + 10, paint); } } }
protected override void OnDrawSample(SKCanvas canvas, int width, int height) { canvas.Clear(SKColors.White); var paint = new SKPaint { IsStroke = true, StrokeWidth = 3, Color = SampleMedia.Colors.XamarinLightBlue }; using (var stream = new SKManagedStream(SampleMedia.Images.BabyTux)) using (var bigBitmap = SKBitmap.Decode(stream)) { canvas.DrawBitmap(bigBitmap, 10, 10); } using (var stream = new SKManagedStream(SampleMedia.Images.BabyTux)) using (var codec = SKCodec.Create(stream)) { var info = codec.Info; var subset = SKRectI.Create(100, 50, 190, 170); var options = new SKCodecOptions(subset); using (var bitmap = new SKBitmap(subset.Width, subset.Height, info.ColorType, SKAlphaType.Premul)) { var result = codec.GetPixels(bitmap.Info, bitmap.GetPixels(), options); if (result == SKCodecResult.Success || result == SKCodecResult.IncompleteInput) { canvas.DrawBitmap(bitmap, info.Width + 20, subset.Top + 10); } } } }
public void QuickRejectIsCorrect() { using var region = new SKRegion(SKRectI.Create(10, 10, 100, 100)); Assert.False(region.QuickReject(SKRectI.Create(50, 50, 100, 100))); Assert.False(region.QuickReject(SKRectI.Create(20, 20, 50, 50))); Assert.True(region.QuickReject(SKRectI.Create(200, 20, 50, 50))); }
public void RectRegionIsRect() { using var region = new SKRegion(SKRectI.Create(10, 10, 100, 100)); Assert.False(region.IsEmpty); Assert.True(region.IsRect); Assert.False(region.IsComplex); }
public void GetBoundaryPathReturnsNotNullPath() { using var region = new SKRegion(SKRectI.Create(10, 10, 100, 100)); region.Op(SKRectI.Create(50, 50, 100, 100), SKRegionOperation.Union); using var path = region.GetBoundaryPath(); Assert.NotNull(path); }
public void TwoRectRegionIsComplex() { using var region = new SKRegion(SKRectI.Create(10, 10, 100, 100)); region.Op(SKRectI.Create(50, 50, 100, 100), SKRegionOperation.Union); Assert.False(region.IsEmpty); Assert.False(region.IsRect); Assert.True(region.IsComplex); }
private SpriteComponent CreateTileSprite(Node parent, InitialNodeTransform transform) { var sprite = parent .CreateChild(transform) .AddComponent( new SpriteComponent(TilesetImage, new SpriteData(SKRectI.Create(0, 0, 8, 8))) ) .AddToCamera(_camera1) .AddToCamera(_camera2); return(sprite); }
// Convert tile images to average color public void ProcessTileColors(List <byte[]> tileImages) { foreach (var bytes in tileImages) { var bitmap = SKBitmap.Decode(bytes); if (bitmap != null) { var rect = SKRectI.Create(0, 0, bitmap.Width, bitmap.Height); tileImageRGBGridList.Add((bitmap, GetAverageColorGrid(bitmap, rect))); } } }
public override void Use(Layer activeLayer, Layer previewLayer, IEnumerable <Layer> allLayers, IReadOnlyList <Coordinates> recordedMouseMovement, SKColor color) { int thickness = Toolbar.GetSetting <SizeSetting>("ToolSize").Value; SKColor?fillColor = null; if (Toolbar.GetSetting <BoolSetting>("Fill").Value) { var temp = Toolbar.GetSetting <ColorSetting>("FillColor").Value; fillColor = new SKColor(temp.R, temp.G, temp.B, temp.A); } var dirtyRect = CreateRectangle(previewLayer, color, fillColor, recordedMouseMovement, thickness); ReportCustomSessionRect(SKRectI.Create(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height)); }
public Task <byte[]> CropProportionally(byte[] imageData, RectangleF proportionalCropRect) { using (var skBitmap = SKBitmap.Decode(imageData)) { var absRect = proportionalCropRect.GetAbsoluteRectangle(new Size(skBitmap.Width, skBitmap.Height)); var image = SKImage.FromBitmap(skBitmap); var subset = image.Subset(SKRectI.Create((int)absRect.X, (int)absRect.Y, (int)absRect.Width, (int)absRect.Height)); // encode the image var encodedData = subset.Encode(SKEncodedImageFormat.Jpeg, 100); return(Task.FromResult(encodedData.ToArray())); } }
F9PImageData(SKBitmap skBitamp, string key) { RangeLists = skBitamp.PatchRanges(); if (RangeLists?.PatchesX != null && RangeLists.PatchesX.Count > 0 && RangeLists.PatchesY != null && RangeLists.PatchesY.Count > 0) { SKBitmap unmarkedBitmap = new SKBitmap(skBitamp.Width - 1, skBitamp.Height - 1, SKColorType.Rgba8888, SKAlphaType.Unpremul); skBitamp.ExtractSubset(unmarkedBitmap, SKRectI.Create(1, 1, skBitamp.Width - 2, skBitamp.Height - 2)); skBitamp.Dispose(); skBitamp = unmarkedBitmap.Copy(); } _width = skBitamp.Width; _height = skBitamp.Height; SKBitmap = skBitamp; Key = key; }
public static SKBitmap SquareFromTop(SKBitmap inImg) { int w = inImg.Width; int h = inImg.Height; int shortestLen = ((w < h) ? w : h); /* * SKImage image = SKImage.FromBitmap(inImg); * SKImage subset = image.Subset(SKRectI.Create(0, yOffset, shortestLen, shortestLen)); * return subset;*/ SKRectI square = SKRectI.Create(0, h - shortestLen, shortestLen, shortestLen); SKBitmap finalBmp = new SKBitmap(shortestLen, shortestLen); Debug.WriteLine("DHB:GlobalSingletonHelpers:rotateAndCrop pre extract"); inImg.ExtractSubset(finalBmp, square); return(finalBmp); }
private SKBitmap BuildThumbCollageBitmap(string[] paths, int width, int height) { var bitmap = new SKBitmap(width, height); using (var canvas = new SKCanvas(bitmap)) { canvas.Clear(SKColors.Black); // number of images used in the thumbnail var iCount = 3; // determine sizes for each image that will composited into the final image var iSlice = Convert.ToInt32(width / iCount); int iHeight = Convert.ToInt32(height * 1.00); int imageIndex = 0; for (int i = 0; i < iCount; i++) { using (var currentBitmap = GetNextValidImage(paths, imageIndex, out int newIndex)) { imageIndex = newIndex; if (currentBitmap == null) { continue; } // resize to the same aspect as the original int iWidth = Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height); using (var resizeBitmap = new SKBitmap(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType)) { currentBitmap.ScalePixels(resizeBitmap, SKFilterQuality.High); // crop image int ix = Math.Abs((iWidth - iSlice) / 2); using (var image = SKImage.FromBitmap(resizeBitmap)) using (var subset = image.Subset(SKRectI.Create(ix, 0, iSlice, iHeight))) { // draw image onto canvas canvas.DrawImage(subset ?? image, iSlice * i, 0); } } } } } return(bitmap); }
[Arguments("t.jpg", "t2.jpg")] // SkiaSharp doesn't have TIFF support public void SkiaSharp(string input, string output) { using (var bitmap = SKBitmap.Decode(input)) { bitmap.ExtractSubset(bitmap, SKRectI.Create(100, 100, bitmap.Width - 200, bitmap.Height - 200)); var targetWidth = (int)Math.Round(bitmap.Width * .9F); var targetHeight = (int)Math.Round(bitmap.Height * .9F); // bitmap.Resize(new SKImageInfo(targetWidth, targetHeight), SKBitmapResizeMethod.Triangle) // is deprecated, so we use `SKFilterQuality.Low` instead, see: // https://github.com/mono/SkiaSharp/blob/1527bf392ebc7b4b57c992ef8bfe14c9899f76a3/binding/Binding/SKBitmap.cs#L24 using (var resized = bitmap.Resize(new SKImageInfo(targetWidth, targetHeight), SKFilterQuality.Low)) { using (var surface = SKSurface.Create(new SKImageInfo(targetWidth, targetHeight, bitmap.ColorType, bitmap.AlphaType))) using (var canvas = surface.Canvas) using (var paint = new SKPaint { FilterQuality = SKFilterQuality.High }) { var kernel = new[] { -1f, -1f, -1f, -1f, 16f, -1f, -1f, -1f, -1f }; var kernelSize = new SKSizeI(3, 3); var kernelOffset = new SKPointI(1, 1); paint.ImageFilter = SKImageFilter.CreateMatrixConvolution(kernelSize, kernel, 0.125f, 0f, kernelOffset, SKMatrixConvolutionTileMode.Repeat, false); canvas.DrawBitmap(resized, 0, 0, paint); canvas.Flush(); using (var fileStream = File.OpenWrite(output)) { surface.Snapshot() .Encode(SKEncodedImageFormat.Jpeg, Quality) .SaveTo(fileStream); } } } } }
private SKImage GenerateHomographyMask(FixedCameraEnhancedData configuration, int sourceWidth, int sourceHeight) { var polygons = GetPolygons(configuration, sourceWidth, sourceHeight); using (var tempSurface = SKSurface.Create(new SKImageInfo(sourceWidth, sourceHeight))) { //get the drawing canvas of the surface var canvas = tempSurface.Canvas; canvas.Clear(SKColors.Black); var fillPaint = new SKPaint { Style = SKPaintStyle.Fill, Color = SKColors.Transparent, BlendMode = SKBlendMode.Clear }; using (fillPaint) { var path = new SKPath(); foreach (var points in polygons) { path.MoveTo(points.First()); for (var i = 1; i < points.Length; i++) { path.LineTo(points[i]); } } canvas.DrawPath(path, fillPaint); } using (var image = tempSurface.Snapshot()) { _croppedSize = new Size(_maxX.Value - _minX.Value, _maxY.Value - _minY.Value); var croppingRectI = SKRectI.Create(_minX.Value, _minY.Value, _croppedSize.Width, _croppedSize.Height); var mask = image.Subset(croppingRectI); return(mask); } } }
protected byte[] CropImage(byte[] data, int left, int top, int width, int height, int imageQuality) { (int actualWidth, int actualHeight) = GetImageSize(data); width = width > actualWidth ? actualWidth : width; height = height > actualHeight ? actualHeight : height; top = top >= 0 ? top : 0; top = top < actualHeight ? top : 0; left = left >= 0 ? left : 0; left = left < actualWidth ? left : 0; using var bitmap = SKBitmap.Decode(data); using var img = SKImage.FromBitmap(bitmap); using var cropped = img.Subset(SKRectI.Create(left, top, width, height)); using var jpeg = cropped.Encode(SKEncodedImageFormat.Jpeg, imageQuality); using var memoryStream = new MemoryStream(); jpeg.AsStream().CopyTo(memoryStream); return(memoryStream.ToArray()); }
private static (ProcessState state, SKImage image) ReadFullImage(T.Tiff tiff, ImageRequest request, bool allowSizeAboveFull) { int width = tiff.GetField(T.TiffTag.IMAGEWIDTH)[0].ToInt(); int height = tiff.GetField(T.TiffTag.IMAGELENGTH)[0].ToInt(); var restag = tiff.GetField(T.TiffTag.RESOLUTIONUNIT); var xrestag = tiff.GetField(T.TiffTag.XRESOLUTION); var yrestag = tiff.GetField(T.TiffTag.YRESOLUTION); var resunit = restag == null ? 2 : restag[0].ToShort(); var xres = xrestag == null ? 96 : xrestag[0].ToDouble(); var yres = yrestag == null ? 96 : yrestag[0].ToDouble(); // pixels per metre if (resunit == 3) { xres = xres / 0.0254; yres = yres / 0.0254; } var isTileable = tiff.IsTiled(); var state = ImageRequestInterpreter.GetInterpretedValues(request, width, height, allowSizeAboveFull); state.HorizontalResolution = Convert.ToUInt16(xres); state.VerticalResolution = Convert.ToUInt16(yres); var raster = new int[width * height]; if (!tiff.ReadRGBAImageOriented(width, height, raster, T.Orientation.TOPLEFT)) { throw new IOException("Unable to decode TIFF file"); } using (var bmp = CreateBitmapFromPixels(raster, width, height)) { var desiredWidth = Math.Max(1, (int)Math.Round(state.RegionWidth * state.ImageScale)); var desiredHeight = Math.Max(1, (int)Math.Round(state.RegionHeight * state.ImageScale)); Log.Debug("Desired size {@DesiredWidth}, {@DesiredHeight}", desiredWidth, desiredHeight); var regionWidth = state.RegionWidth; var regionHeight = state.RegionHeight; var srcRegion = SKRectI.Create(state.StartX, state.StartY, regionWidth, regionHeight); return(state, CopyImageRegion2(bmp, desiredWidth, desiredHeight, srcRegion)); } }
private static List <SKImage> SplitImageBySeparators(SKImage image, IReadOnlyList <int> separators) { var subsets = new List <SKImage>(); for (var i = 0; i < separators.Count - 1; i++) { var left = separators[i]; var right = separators[i + 1]; var width = right - left; var height = image.Height; var crop = SKRectI.Create(width, height); crop.Left = left; crop.Right = right; subsets.Add(image.Subset(crop)); } return(subsets); }
public static void sliceTiles(FileStream image, Tuple <double, double> topLeft, Tuple <double, double> bottomRight, string writePath) { const int tileLength = 256; const int bottomLevel = 3; int tilesPerDim = Convert.ToInt32(Math.Pow(2, Convert.ToDouble(bottomLevel))); int pixelsPerDim = tilesPerDim * tileLength; double degreesLatPerPixel = 180d / pixelsPerDim; double degreesLonPerPixel = degreesLatPerPixel * 2; Tuple <int, int> imageTopLeft = new Tuple <int, int>(Convert.ToInt32((90 - topLeft.Item1) / degreesLatPerPixel), Convert.ToInt32((180 + topLeft.Item2) / degreesLonPerPixel)); Tuple <int, int> imageBottomRight = new Tuple <int, int>(Convert.ToInt32((90 - bottomRight.Item1) / degreesLatPerPixel), Convert.ToInt32((180 + bottomRight.Item2) / degreesLonPerPixel)); SKImage sKImage = SKImage.FromEncodedData(image); var fullSurface = SKSurface.Create(new SKImageInfo(pixelsPerDim, pixelsPerDim)); var canvas = fullSurface.Canvas; SKBitmap scaledImage = new SKBitmap(imageBottomRight.Item2 - imageTopLeft.Item2, imageBottomRight.Item1 - imageTopLeft.Item1); SKBitmap.FromImage(sKImage).ScalePixels(scaledImage, SKFilterQuality.High); canvas.DrawBitmap(scaledImage, new SKPoint(imageTopLeft.Item2, imageTopLeft.Item1)); SKImage fullImage = fullSurface.Snapshot(); var tileSurface = SKSurface.Create(new SKImageInfo(tileLength, tileLength)); canvas = tileSurface.Canvas; for (int y = 0; y < fullImage.Height; y += tileLength) { for (int x = 0; x < fullImage.Width; x += tileLength) { SKBitmap tile = SKBitmap.FromImage(fullImage.Subset(SKRectI.Create(x, y, tileLength, tileLength))); canvas.Clear(SKColors.Transparent); canvas.DrawBitmap(tile, SKRect.Create(0, 0, tileLength, tileLength)); var stream = File.OpenWrite($"{writePath}/aqlatestL{bottomLevel}T{(x / tileLength).ToString("D2")}{(y / tileLength).ToString("D2")}.png"); var data = tileSurface.Snapshot().Encode(); data.SaveTo(stream); } } }