public static BitmapInfo LoadBitmap(object bitmapStream) { // todo: Our BitmapRegistry stores not only bitmaps. Perhaps we should store a class in it // which has all information. So we should have a SymbolImageRegistry in which we store a // SymbolImage. Which holds the type, data and other parameters. if (bitmapStream is Stream stream) { if (stream.IsSvg()) { var svg = new SKSvg(); svg.Load(stream); return(new BitmapInfo { Svg = svg }); } var image = SKImage.FromEncodedData(SKData.CreateCopy(stream.ToBytes())); return(new BitmapInfo { Bitmap = image }); } if (bitmapStream is Sprite sprite) { return(new BitmapInfo { Sprite = sprite }); } return(null); }
public static BitmapInfo LoadBitmap(object bitmapStream) { if (bitmapStream is Stream stream) { byte[] buffer = new byte[4]; stream.Position = 0; stream.Read(buffer, 0, 4); stream.Position = 0; if (System.Text.Encoding.UTF8.GetString(buffer, 0, 4).ToLower().Equals("<svg")) { var svg = new SkiaSharp.Extended.Svg.SKSvg(); svg.Load(stream); return(new BitmapInfo { Svg = svg }); } var image = SKImage.FromEncodedData(SKData.CreateCopy(stream.ToBytes())); return(new BitmapInfo { Bitmap = image }); } if (bitmapStream is Sprite sprite) { return(new BitmapInfo { Sprite = sprite }); } return(null); }
public void ValidDataProperties() { var data = SKData.CreateCopy(OddData); Assert.Equal(OddData.Length, data.Size); Assert.Equal(OddData, data.ToArray()); }
protected override SKData OnEncode(SKPixmap pixmap) { DidEncode++; EncodedInfo = pixmap.Info; return(SKData.CreateCopy(pixmap.GetPixels(), (ulong)pixmap.Info.BytesSize)); }
private SKImage GetBitmap(byte[] Pixels) { using (SKData Data = SKData.CreateCopy(Pixels)) { SKImageInfo ImageInfo = new SKImageInfo(this.width, this.height, SKColorType.Rgba8888, SKAlphaType.Premul); return(SKImage.FromPixelData(ImageInfo, Data, this.width << 2)); } }
private static readonly SKPaint Paint = new SKPaint(); // Reuse for performance. Only for opacity public static BitmapInfo LoadBitmap(Stream bitmapStream) { bitmapStream.Position = 0; var image = SKImage.FromEncodedData(SKData.CreateCopy(bitmapStream.ToBytes())); return(new BitmapInfo { Bitmap = image }); }
private void initFonts() { fonts.forEach(s => { var buf = App.LoadData($"fonts/{s}"); var data = SKData.CreateCopy(buf); faces[s] = SKTypeface.FromData(data); data.Dispose(); }); }
public void CanReadData() { var bytes = File.ReadAllBytes(Path.Combine(PathToFonts, "Distortable.ttf")); using (var data = SKData.CreateCopy(bytes)) using (var typeface = SKTypeface.FromData(data)) { Assert.NotNull(typeface); } }
public void CanReadData() { var fonts = SKFontManager.Default; var bytes = File.ReadAllBytes(Path.Combine(PathToFonts, "Distortable.ttf")); using (var data = SKData.CreateCopy(bytes)) using (var typeface = fonts.CreateTypeface(data)) { Assert.NotNull(typeface); } }
/// <summary> /// Encodes an image for storage. /// </summary> /// <param name="imageStream">The image to encode.</param> /// <returns>The encoded image, or null if decoding fails.</returns> /// <remarks> /// The image returned is guaranteed to have no side longer than /// <see cref="F:HospitalAllocation.Providers.Image.Database.DbImageProvider.MaxSideLength"/> pixels. /// </remarks> private static SKData EncodeImage(IImageStream imageStream) { // Get the image var imageArray = new byte[imageStream.Length]; var stream = new MemoryStream(imageArray); imageStream.CopyTo(stream); var data = SKData.CreateCopy(imageArray); var image = SKImage.FromEncodedData(data); // Decode failed if (image == null) { return(null); } // Resize the image if required if (Math.Max(image.Height, image.Width) > MaxSideLength) { int resizedHeight; int resizedWidth; float scale; if (image.Height > image.Width) { resizedHeight = MaxSideLength; scale = ((float)resizedHeight / image.Height); resizedWidth = (int)Math.Round(image.Width * scale); } else { resizedWidth = MaxSideLength; scale = ((float)resizedWidth / image.Width); resizedHeight = (int)Math.Round(image.Height * scale); } var surface = SKSurface.Create(new SKImageInfo(resizedWidth, resizedHeight)); var paint = new SKPaint { FilterQuality = SKFilterQuality.High }; surface.Canvas.Scale(scale); surface.Canvas.DrawImage(image, 0, 0, paint); surface.Canvas.Flush(); image = surface.Snapshot(); } // Encode the image return(image.Encode(SKEncodedImageFormat.Jpeg, JpegQualityLevel)); }
}; // Only for high/med/low quality resizing of tiles public static BitmapInfo LoadBitmap(Stream bitmapStream, bool isSvg = false) { bitmapStream.Position = 0; if (isSvg) { var svg = new SkiaSharp.Extended.Svg.SKSvg(); svg.Load(bitmapStream); return(new BitmapInfo { Svg = svg }); } var image = SKImage.FromEncodedData(SKData.CreateCopy(bitmapStream.ToBytes())); return(new BitmapInfo { Bitmap = image }); }
public void DataDisposedReturnsInvalidStream() { // create data var data = SKData.CreateCopy(OddData); // get the stream var stream = data.AsStream(); // nuke the data data.Dispose(); Assert.Equal(IntPtr.Zero, data.Handle); // read the stream var buffer = new byte[OddData.Length]; stream.Read(buffer, 0, buffer.Length); // since the data was nuked, they will differ Assert.NotEqual(OddData, buffer); }
public static BitmapInfo LoadBitmap(object bitmapStream) { // todo: Our BitmapRegistry stores not only bitmaps. Perhaps we should store a class in it // which has all information. So we should have a SymbolImageRegistry in which we store a // SymbolImage. Which holds the type, data and other parameters. if (bitmapStream is Stream stream) { byte[] buffer = new byte[4]; stream.Position = 0; stream.Read(buffer, 0, 4); stream.Position = 0; if (System.Text.Encoding.UTF8.GetString(buffer, 0, 4).ToLower().Equals("<svg")) { var svg = new SkiaSharp.Extended.Svg.SKSvg(); svg.Load(stream); return(new BitmapInfo { Svg = svg }); } var image = SKImage.FromEncodedData(SKData.CreateCopy(stream.ToBytes())); return(new BitmapInfo { Bitmap = image }); } if (bitmapStream is Sprite sprite) { return(new BitmapInfo { Sprite = sprite }); } return(null); }
public Bitmap(byte[] largeIconsImage, Size clientSizeHeight) { nativeSkBitmap = SKBitmap.Decode(SKData.CreateCopy(largeIconsImage)).Resize( new SKImageInfo(clientSizeHeight.Width, clientSizeHeight.Height), SKFilterQuality.High); }
private SKData GetImageData(string imagePath, ResizeParams resizeParams, DateTime lastWriteTimeUtc) { // check cache and return if cached long cacheKey; unchecked { cacheKey = imagePath.GetHashCode() + lastWriteTimeUtc.ToBinary() + resizeParams.ToString().GetHashCode(); } SKData imageData; byte[] imageBytes; bool isCached = _memoryCache.TryGetValue <byte[]>(cacheKey, out imageBytes); if (isCached) { _logger.LogInformation("Serving from cache"); return(SKData.CreateCopy(imageBytes)); } SKCodecOrigin origin; // this represents the EXIF orientation var bitmap = LoadBitmap(File.OpenRead(imagePath), out origin); // always load as 32bit (to overcome issues with indexed color) // if autorotate = true, and origin isn't correct for the rotation, rotate it if (resizeParams.autorotate && origin != SKCodecOrigin.TopLeft) { bitmap = RotateAndFlip(bitmap, origin); } // if either w or h is 0, set it based on ratio of original image if (resizeParams.h == 0) { resizeParams.h = (int)Math.Round(bitmap.Height * (float)resizeParams.w / bitmap.Width); } else if (resizeParams.w == 0) { resizeParams.w = (int)Math.Round(bitmap.Width * (float)resizeParams.h / bitmap.Height); } // if we need to crop, crop the original before resizing if (resizeParams.mode == "crop") { bitmap = Crop(bitmap, resizeParams); } // store padded height and width var paddedHeight = resizeParams.h; var paddedWidth = resizeParams.w; // if we need to pad, or max, set the height or width according to ratio if (resizeParams.mode == "pad" || resizeParams.mode == "max") { var bitmapRatio = (float)bitmap.Width / bitmap.Height; var resizeRatio = (float)resizeParams.w / resizeParams.h; if (bitmapRatio > resizeRatio) // original is more "landscape" { resizeParams.h = (int)Math.Round(bitmap.Height * ((float)resizeParams.w / bitmap.Width)); } else { resizeParams.w = (int)Math.Round(bitmap.Width * ((float)resizeParams.h / bitmap.Height)); } } // resize var resizedImageInfo = new SKImageInfo(resizeParams.w, resizeParams.h, SKImageInfo.PlatformColorType, bitmap.AlphaType); var resizedBitmap = bitmap.Resize(resizedImageInfo, SKBitmapResizeMethod.Lanczos3); // optionally pad if (resizeParams.mode == "pad") { resizedBitmap = Pad(resizedBitmap, paddedWidth, paddedHeight, resizeParams.format != "png"); } // encode var resizedImage = SKImage.FromBitmap(resizedBitmap); var encodeFormat = resizeParams.format == "png" ? SKEncodedImageFormat.Png : SKEncodedImageFormat.Jpeg; imageData = resizedImage.Encode(encodeFormat, resizeParams.quality); // cache the result _memoryCache.Set <byte[]>(cacheKey, imageData.ToArray()); // cleanup resizedImage.Dispose(); bitmap.Dispose(); resizedBitmap.Dispose(); return(imageData); }
private SKData GetImageData(string imagePath, ResizeParams resizeParams, DateTime lastWriteTimeUtc) { // check cache and return if cached string cacheKey; unchecked { cacheKey = "imgasc_" + imagePath.GetHashCode() + lastWriteTimeUtc.ToBinary() + resizeParams.ToString().GetHashCode(); } SKData imageData; byte[] cacheData = _asyncCacheService.GetByKeyAsync <byte[]>(cacheKey).Result; if (cacheData != null) { return(SKData.CreateCopy(cacheData)); } // this represents the EXIF orientation SKBitmap bitmap = LoadBitmap(File.OpenRead(imagePath), out SKEncodedOrigin origin); // always load as 32bit (to overcome issues with indexed color) // if autorotate = true, and origin isn't correct for the rotation, rotate it if (resizeParams.autorotate && origin != SKEncodedOrigin.TopLeft) { bitmap = RotateAndFlip(bitmap, origin); } // if either w or h is 0, set it based on ratio of original image if (resizeParams.h == 0) { resizeParams.h = (int)Math.Round(bitmap.Height * (float)resizeParams.w / bitmap.Width); } else if (resizeParams.w == 0) { resizeParams.w = (int)Math.Round(bitmap.Width * (float)resizeParams.h / bitmap.Height); } // if we need to crop, crop the original before resizing if (resizeParams.mode == "crop") { bitmap = Crop(bitmap, resizeParams); } // store padded height and width int paddedHeight = resizeParams.h; int paddedWidth = resizeParams.w; // if we need to pad, or max, set the height or width according to ratio if (resizeParams.mode == "pad" || resizeParams.mode == "max") { float bitmapRatio = (float)bitmap.Width / bitmap.Height; float resizeRatio = (float)resizeParams.w / resizeParams.h; if (bitmapRatio > resizeRatio) // original is more "landscape" { resizeParams.h = (int)Math.Round(bitmap.Height * ((float)resizeParams.w / bitmap.Width)); } else { resizeParams.w = (int)Math.Round(bitmap.Width * ((float)resizeParams.h / bitmap.Height)); } } // resize SKImageInfo resizedImageInfo = new SKImageInfo(resizeParams.w, resizeParams.h, SKImageInfo.PlatformColorType, bitmap.AlphaType); SKBitmap resizedBitmap = bitmap.Resize(resizedImageInfo, SKFilterQuality.None); // optionally pad if (resizeParams.mode == "pad") { resizedBitmap = Pad(resizedBitmap, paddedWidth, paddedHeight, resizeParams.format != "png"); } // encode SKImage resizedImage = SKImage.FromBitmap(resizedBitmap); SKEncodedImageFormat encodeFormat = resizeParams.format == "png" ? SKEncodedImageFormat.Png : SKEncodedImageFormat.Jpeg; imageData = resizedImage.Encode(encodeFormat, resizeParams.quality); // cache the result _asyncCacheService.SetValueAsync(cacheKey, imageData.ToArray()); // cleanup resizedImage.Dispose(); bitmap.Dispose(); resizedBitmap.Dispose(); return(imageData); }
public static SKData ToSKData(this NSData nsData) { return(SKData.CreateCopy(nsData.Bytes, nsData.Length)); }
public static BitmapInfo?LoadBitmap(object?bitmapStream) { // todo: Our BitmapRegistry stores not only bitmaps. Perhaps we should store a class in it // which has all information. So we should have a SymbolImageRegistry in which we store a // SymbolImage. Which holds the type, data and other parameters. if (bitmapStream is SKImage skBitmap) { return(new BitmapInfo { Bitmap = skBitmap, }); } if (bitmapStream is SKPicture skPicture) { return(new BitmapInfo { Picture = skPicture }); } if (bitmapStream is string str) { if (str.ToLower().Contains("<svg")) { return(new BitmapInfo { Svg = str.LoadSvg() }); } } if (bitmapStream is byte[] data) { if (data.IsXml()) { using var tempStream = new MemoryStream(data); if (tempStream.IsSvg()) { return(new BitmapInfo { Svg = tempStream.LoadSvg() }); } } using var skData = SKData.CreateCopy(data); var image = SKImage.FromEncodedData(skData); return(new BitmapInfo { Bitmap = image }); } if (bitmapStream is Stream stream) { if (stream.IsSvg()) { return(new BitmapInfo { Svg = stream.LoadSvg() }); } using var skData = SKData.CreateCopy(stream.ToBytes()); var image = SKImage.FromEncodedData(skData); return(new BitmapInfo { Bitmap = image }); } if (bitmapStream is Sprite sprite) { return(new BitmapInfo { Sprite = sprite }); } return(null); }
private static async Task 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; 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); }