public ImmutableBitmap(Stream stream, int decodeSize, bool horizontal, BitmapInterpolationMode interpolationMode) { using (var skStream = new SKManagedStream(stream)) using (var codec = SKCodec.Create(skStream)) { var info = codec.Info; // get the scale that is nearest to what we want (eg: jpg returned 512) var supportedScale = codec.GetScaledDimensions(horizontal ? ((float)decodeSize / info.Width) : ((float)decodeSize / info.Height)); // decode the bitmap at the nearest size var nearest = new SKImageInfo(supportedScale.Width, supportedScale.Height); var bmp = SKBitmap.Decode(codec, nearest); // now scale that to the size that we want var realScale = horizontal ? ((double)info.Height / info.Width) : ((double)info.Width / info.Height); SKImageInfo desired; if (horizontal) { desired = new SKImageInfo(decodeSize, (int)(realScale * decodeSize)); } else { desired = new SKImageInfo((int)(realScale * decodeSize), decodeSize); } if (bmp.Width != desired.Width || bmp.Height != desired.Height) { var scaledBmp = bmp.Resize(desired, interpolationMode.ToSKFilterQuality()); bmp.Dispose(); bmp = scaledBmp; } _image = SKImage.FromBitmap(bmp); bmp.Dispose(); if (_image == null) { throw new ArgumentException("Unable to load bitmap from provided data"); } PixelSize = new PixelSize(_image.Width, _image.Height); // TODO: Skia doesn't have an API for DPI. Dpi = new Vector(96, 96); } }
public ImageSize GetImageSize(string path) { using (var s = new SKFileStream(path)) using (var codec = SKCodec.Create(s)) { var info = codec.Info; return(new ImageSize { Width = info.Width, Height = info.Height }); } }
public void GetSingleGifFrame() { var stream = new SKFileStream(Path.Combine(PathToImages, "animated-heart.gif")); using (var codec = SKCodec.Create(stream)) { var frameInfos = codec.FrameInfo; for (var i = 0; i < frameInfos.Length; i++) { Assert.True(codec.GetFrameInfo(i, out var info)); Assert.Equal(frameInfos[i], info); } } }
protected override async Task OnInit() { var stream = new SKManagedStream(SampleMedia.Images.AnimatedHeartGif, true); codec = SKCodec.Create(stream); frames = codec.FrameInfo; info = codec.Info; info = new SKImageInfo(info.Width, info.Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul); bitmap = new SKBitmap(info); await base.OnInit(); }
public static bool FramesFromImage(string path, out List <Frame> ret) { ret = null; if (!File.Exists(path)) { return(false); } using (SKCodec codec = SKCodec.Create(path)){ if (codec == null) { return(false); } SKImageInfo info = codec.Info; ret = new List <Frame>(); for (int i = 0; i < codec.FrameCount; i++) { SKBitmap frame = new SKBitmap(info); if (codec.GetPixels(info, frame.GetPixels(), new SKCodecOptions(i)) == SKCodecResult.Success) { frame = frame.Resize(targetInfo, SKFilterQuality.High); ret.Add(new Frame(new Time(false, free: codec.FrameInfo[i].Duration))); for (int x = 0; x <= 9; x++) { for (int y = 0; y <= 9; y++) { SKColor color = frame.GetPixel(x, 9 - y); ret[i].Screen[y * 10 + x] = new Color( (byte)(color.Red >> 2), (byte)(color.Green >> 2), (byte)(color.Blue >> 2) ); } } } else { return(false); } } return(true); } }
/// <summary> /// Decode an image. /// </summary> /// <param name="path">The filepath of the image to decode.</param> /// <param name="forceCleanBitmap">Whether to force clean the bitmap.</param> /// <param name="orientation">The orientation of the image.</param> /// <param name="origin">The detected origin of the image.</param> /// <returns>The resulting bitmap of the image.</returns> internal SKBitmap?Decode(string path, bool forceCleanBitmap, ImageOrientation?orientation, out SKEncodedOrigin origin) { if (!File.Exists(path)) { throw new FileNotFoundException("File not found", path); } var requiresTransparencyHack = _transparentImageTypes.Contains(Path.GetExtension(path)); if (requiresTransparencyHack || forceCleanBitmap) { using (var codec = SKCodec.Create(NormalizePath(path))) { if (codec == null) { origin = GetSKEncodedOrigin(orientation); return(null); } // create the bitmap var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack); // decode _ = codec.GetPixels(bitmap.Info, bitmap.GetPixels()); origin = codec.EncodedOrigin; return(bitmap); } } var resultBitmap = SKBitmap.Decode(NormalizePath(path)); if (resultBitmap == null) { return(Decode(path, true, orientation, out origin)); } // If we have to resize these they often end up distorted if (resultBitmap.ColorType == SKColorType.Gray8) { using (resultBitmap) { return(Decode(path, true, orientation, out origin)); } } origin = SKEncodedOrigin.TopLeft; return(resultBitmap); }
public void GetGifFrames() { const int FrameCount = 16; var stream = new SKFileStream(Path.Combine(PathToImages, "animated-heart.gif")); using (var codec = SKCodec.Create(stream)) { Assert.Equal(-1, codec.RepetitionCount); var frameInfos = codec.FrameInfo; Assert.Equal(FrameCount, frameInfos.Length); Assert.Equal(-1, frameInfos [0].RequiredFrame); var cachedFrames = new SKBitmap [FrameCount]; var info = new SKImageInfo(codec.Info.Width, codec.Info.Height); var decode = new Action <SKBitmap, int, int> ((bm, cachedIndex, index) => { var decodeInfo = info; if (index > 0) { decodeInfo = info.WithAlphaType(frameInfos [index].AlphaType); } bm.TryAllocPixels(decodeInfo); if (cachedIndex != -1) { Assert.True(cachedFrames [cachedIndex].CopyTo(bm)); } var opts = new SKCodecOptions(index, cachedIndex); var result = codec.GetPixels(decodeInfo, bm.GetPixels(), opts); if (cachedIndex != -1 && frameInfos [cachedIndex].DisposalMethod == SKCodecAnimationDisposalMethod.RestorePrevious) { Assert.Equal(SKCodecResult.InvalidParameters, result); } Assert.Equal(SKCodecResult.Success, result); }); for (var i = 0; i < FrameCount; i++) { var cachedFrame = cachedFrames [i] = new SKBitmap(); decode(cachedFrame, -1, i); var uncachedFrame = new SKBitmap(); decode(uncachedFrame, frameInfos [i].RequiredFrame, i); Assert.Equal(cachedFrame.Bytes, uncachedFrame.Bytes); } } }
public void Index8ImageHasColorTable() { var path = Path.Combine(PathToImages, "index8.png"); var codec = SKCodec.Create(new SKFileStream(path)); // It appears I can't use Unpremul as the alpha type, as the color table is not premultiplied then // https://groups.google.com/forum/#!topic/skia-discuss/mNUxQon5OMY var info = new SKImageInfo(codec.Info.Width, codec.Info.Height, SKColorType.Index8, SKAlphaType.Premul); var bitmap = SKBitmap.Decode(codec, info); var colorTable = bitmap.ColorTable; Assert.IsNotNull(colorTable); Assert.AreEqual((SKPMColor)0x000000, colorTable[0]); Assert.AreEqual((SKColor)0x000000, colorTable.GetUnPreMultipliedColor(0)); if (IsWindows || IsLinux) { Assert.AreEqual((SKPMColor)0xFFA4C639, colorTable[255]); } else { Assert.AreEqual((SKPMColor)0xFF39C6A4, colorTable[255]); } Assert.AreEqual((SKColor)0xFFA4C639, colorTable.GetUnPreMultipliedColor(255)); if (IsWindows || IsLinux) { Assert.AreEqual((SKPMColor)0x7E51621C, colorTable[140]); } else { Assert.AreEqual((SKPMColor)0x7E1C6251, colorTable[140]); } Assert.AreEqual((SKColor)0x7EA4C639, colorTable.GetUnPreMultipliedColor(140)); if (IsWindows || IsLinux) { Assert.AreEqual((SKPMColor)0x7E51621C, bitmap.GetIndex8Color(182, 348)); } else { Assert.AreEqual((SKPMColor)0x7E1C6251, bitmap.GetIndex8Color(182, 348)); } Assert.AreEqual((SKColor)0x7EA4C639, bitmap.GetPixel(182, 348)); }
public ImageDimensions GetImageSize(string path) { if (!File.Exists(path)) { throw new FileNotFoundException("File not found", path); } using (var s = new SKFileStream(path)) using (var codec = SKCodec.Create(s)) { var info = codec.Info; return(new ImageDimensions(info.Width, info.Height)); } }
public unsafe void InvalidStreamIsDisposedImmediately() { var stream = CreateTestSKStream(); var handle = stream.Handle; Assert.True(stream.OwnsHandle); Assert.False(stream.IgnorePublicDispose); Assert.True(SKObject.GetInstance <SKStream>(handle, out _)); Assert.Null(SKCodec.Create(stream)); Assert.False(stream.OwnsHandle); Assert.True(stream.IgnorePublicDispose); Assert.False(SKObject.GetInstance <SKStream>(handle, out _)); }
public void BitmapDecodesCorrectly() { byte[] codecPixels; byte[] bitmapPixels; using (var codec = SKCodec.Create(new SKFileStream(Path.Combine(PathToImages, "baboon.png")))) { codecPixels = codec.Pixels; } using (var bitmap = SKBitmap.Decode(Path.Combine(PathToImages, "baboon.png"))) { bitmapPixels = bitmap.Bytes; } Assert.Equal(codecPixels, bitmapPixels); }
public void CanCreateStreamCodecWithResult() { var stream = new SKFileStream(Path.Combine(PathToImages, "color-wheel.png")); Assert.True(stream.IsValid); using var codec = SKCodec.Create(stream, out var result); Assert.Equal(SKCodecResult.Success, result); Assert.Equal(SKEncodedImageFormat.Png, codec.EncodedFormat); Assert.Equal(128, codec.Info.Width); Assert.Equal(128, codec.Info.Height); Assert.Equal(SKAlphaType.Unpremul, codec.Info.AlphaType); Assert.Equal(SKImageInfo.PlatformColorType, codec.Info.ColorType); }
public static BitmapDrawable From(SKData data) { if (data == null) { throw new ArgumentNullException(nameof(data)); } using (var codec = SKCodec.Create(data)) { if (codec == null) { return(null); } return(From(codec)); } }
public static BitmapDrawable From(System.IO.Stream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } using (var codec = SKCodec.Create(stream)) { if (codec == null) { return(null); } return(From(codec)); } }
/// <summary> /// Constructor for a feature extractor using Google Cloud Platform SDK, optimized for analysing a single image. /// </summary> /// <param name="imageStream"></param> /// <param name="credentialsPath"></param> public GcpFeatureExtractor(Stream imageStream, string credentialsPath) { SetRotation(SKCodec.Create(imageStream).EncodedOrigin); var size = System.Drawing.Image.FromStream(imageStream).Size; Width = size.Width; Height = size.Height; var visionImage = Image.FromStream(imageStream); _client = new ImageAnnotatorClientBuilder() { CredentialsPath = credentialsPath }.Build(); _image = Image.FromStream(imageStream); }
private SKBitmap LoadBitmap(Stream sourceStream) { using (var codec = SKCodec.Create(sourceStream)) { var bitmap = SKBitmap.Decode(codec); Log.Debug($"Orientation: {codec.EncodedOrigin}"); SKBitmap rotated; switch (codec.EncodedOrigin) { case SKEncodedOrigin.BottomRight: using (var surface = new SKCanvas(bitmap)) { surface.RotateDegrees(180, bitmap.Width / 2f, bitmap.Height / 2f); surface.DrawBitmap(bitmap.Copy(), 0, 0); } return(bitmap); case SKEncodedOrigin.RightTop: rotated = new SKBitmap(bitmap.Height, bitmap.Width); using (var surface = new SKCanvas(rotated)) { surface.Translate(rotated.Width, 0); surface.RotateDegrees(90); surface.DrawBitmap(bitmap, 0, 0); } return(rotated); case SKEncodedOrigin.LeftBottom: rotated = new SKBitmap(bitmap.Height, bitmap.Width); using (var surface = new SKCanvas(rotated)) { surface.Translate(0, rotated.Height); surface.RotateDegrees(270); surface.DrawBitmap(bitmap, 0, 0); } return(rotated); default: return(bitmap); } } }
public static BitmapDrawable From(SKCodec codec) { if (codec == null) { throw new ArgumentNullException(nameof(codec)); } var info = codec.Info; if (info.AlphaType == SKAlphaType.Unpremul) { info.AlphaType = SKAlphaType.Premul; } // for backwards compatibility, remove the colorspace info.ColorSpace = null; return(From(codec, info)); }
/// <inheritdoc /> /// <exception cref="ArgumentNullException">The path is null.</exception> /// <exception cref="FileNotFoundException">The path is not valid.</exception> /// <exception cref="SkiaCodecException">The file at the specified path could not be used to generate a codec.</exception> public ImageDimensions GetImageSize(string path) { if (!File.Exists(path)) { throw new FileNotFoundException("File not found", path); } using (var codec = SKCodec.Create(path, out SKCodecResult result)) { EnsureSuccess(result); var info = codec.Info; return(new ImageDimensions(info.Width, info.Height)); } }
public AnimatedGifPage() { InitializeComponent(); string resourceID = "SkiaSharpFormsDemos.Media.Newtons_cradle_animation_book_2.gif"; Assembly assembly = GetType().GetTypeInfo().Assembly; using (Stream stream = assembly.GetManifestResourceStream(resourceID)) using (SKManagedStream skStream = new SKManagedStream(stream)) using (SKCodec codec = SKCodec.Create(skStream)) { // Get frame count and allocate bitmaps int frameCount = codec.FrameCount; bitmaps = new SKBitmap[frameCount]; durations = new int[frameCount]; accumulatedDurations = new int[frameCount]; // Note: There's also a RepetitionCount property of SKCodec not used here // Loop through the frames for (int frame = 0; frame < frameCount; frame++) { // From the FrameInfo collection, get the duration of each frame durations[frame] = codec.FrameInfo[frame].Duration; // Create a full-color bitmap for each frame SKImageInfo imageInfo = new SKImageInfo(codec.Info.Width, codec.Info.Height); bitmaps[frame] = new SKBitmap(imageInfo); // Get the address of the pixels in that bitmap IntPtr pointer = bitmaps[frame].GetPixels(); // Create an SKCodecOptions value to specify the frame SKCodecOptions codecOptions = new SKCodecOptions(frame, false); // Copy pixels from the frame into the bitmap codec.GetPixels(imageInfo, pointer, codecOptions); } // Sum up the total duration for (int frame = 0; frame < durations.Length; frame++) { totalDuration += durations[frame]; } // Calculate the accumulated durations for (int frame = 0; frame < durations.Length; frame++) { accumulatedDurations[frame] = durations[frame] + (frame == 0 ? 0 : accumulatedDurations[frame - 1]); } } }
public static BitmapDrawable From(SKCodec codec, SKImageInfo bitmapInfo) { if (codec == null) { throw new ArgumentNullException(nameof(codec)); } var bitmap = new BitmapDrawable(bitmapInfo); var result = codec.GetPixels(bitmapInfo, bitmap.GetPixels(out var length)); if (result != SKCodecResult.Success && result != SKCodecResult.IncompleteInput) { bitmap.Dispose(); bitmap = null; } return(bitmap); }
public unsafe void StreamThatHasLostOwnershipIsDisposed() { var bytes = File.ReadAllBytes(Path.Combine(PathToImages, "color-wheel.png")); var dotnet = new MemoryStream(bytes); var stream = new SKManagedStream(dotnet, true); var handle = stream.Handle; Assert.True(stream.OwnsHandle); Assert.True(SKObject.GetInstance <SKManagedStream>(handle, out _)); var codec = SKCodec.Create(stream); Assert.False(stream.OwnsHandle); codec.Dispose(); Assert.False(SKObject.GetInstance <SKManagedStream>(handle, out _)); }
protected override void OnDrawSample(SKCanvas canvas, int width, int height) { canvas.Clear(SKColors.White); // load the embedded resource stream using (var stream = new SKManagedStream(SampleMedia.Images.ColorWheel)) using (var codec = SKCodec.Create(stream)) using (var paint = new SKPaint()) using (var tf = SKTypeface.FromFamilyName("Arial")) { var info = codec.Info; var encodedInfo = codec.EncodedInfo; paint.IsAntialias = true; paint.TextSize = 14; paint.Typeface = tf; paint.Color = SKColors.Black; // decode the image using (var bitmap = new SKBitmap(info.Width, info.Height, info.ColorType, info.IsOpaque ? SKAlphaType.Opaque : SKAlphaType.Premul)) { IntPtr length; var result = codec.GetPixels(bitmap.Info, bitmap.GetPixels(out length)); if (result == SKCodecResult.Success || result == SKCodecResult.IncompleteInput) { var x = 25; var y = 25; canvas.DrawBitmap(bitmap, x, y); x += bitmap.Info.Width + 25; y += 14; canvas.DrawText(string.Format("Result: {0}", result), x, y, paint); y += 20; canvas.DrawText(string.Format("Size: {0}px x {1}px", bitmap.Width, bitmap.Height), x, y, paint); y += 20; canvas.DrawText(string.Format("Pixels: {0} @ {1}b/px", bitmap.Pixels.Length, bitmap.BytesPerPixel), x, y, paint); y += 20; canvas.DrawText(string.Format("Encoding: {0} ({1}) @ {2}-bit color", encodedInfo.Color, encodedInfo.Alpha, encodedInfo.BitsPerComponent), x, y, paint); } } } }
public void BitmapDecodesCorrectlyWithManagedStream() { byte[] codecPixels; byte[] bitmapPixels; var stream = File.OpenRead(Path.Combine(PathToImages, "baboon.png")); using (var codec = SKCodec.Create(new SKManagedStream(stream))) { codecPixels = codec.Pixels; } using (var bitmap = SKBitmap.Decode(Path.Combine(PathToImages, "baboon.png"))) { bitmapPixels = bitmap.Bytes; } Assert.Equal(codecPixels, bitmapPixels); }
private SKBitmap GetChildViewImage() { var r = DependencyService.Get <IViewImageProvider>(DependencyFetchTarget.GlobalInstance).GetViewImage(ChildView); SKCodec codec = SKCodec.Create(new MemoryStream(r)); return(SKBitmap.Decode(codec)); //string resourceID = "FormsRevealer.Sample.ape.jpg"; //Assembly assembly = GetType().GetTypeInfo().Assembly; //SKBitmap resourceBitmap; //using (Stream stream = assembly.GetManifestResourceStream(resourceID)) //{ // resourceBitmap = SKBitmap.Decode(stream); //} //return resourceBitmap; }
private SKBitmap LoadBitmap(Stream stream, out SKEncodedOrigin origin) { using var managedStream = new SKManagedStream(stream); using var codec = SKCodec.Create(managedStream); origin = codec.EncodedOrigin; var info = codec.Info; var bitmap = new SKBitmap(info.Width, info.Height, SKImageInfo.PlatformColorType, info.IsOpaque ? SKAlphaType.Opaque : SKAlphaType.Premul); var result = codec.GetPixels(bitmap.Info, bitmap.GetPixels(out _)); if (result == SKCodecResult.Success || result == SKCodecResult.IncompleteInput) { return(bitmap); } throw new ArgumentException("Невозможно загрузить изображение из источника."); }
private void LoadPng(Item item) { try { if (!File.Exists(item.ReferencePngPath)) { return; } using var codec = SKCodec.Create(new SKFileStream(item.ReferencePngPath)); #if USE_COLORSPACE var skImageInfo = new SKImageInfo(codec.Info.Width, codec.Info.Height, SKSvg.s_colorType, SKSvg.s_alphaType, SvgPaintingExtensions.Srgb); #else var skImageInfo = new SKImageInfo(codec.Info.Width, codec.Info.Height, SKSvg.s_colorType, SKSvg.s_alphaType); #endif var skReferenceBitmap = new SKBitmap(skImageInfo); codec.GetPixels(skReferenceBitmap.Info, skReferenceBitmap.GetPixels()); if (skReferenceBitmap == null) { return; } item.ReferencePng = skReferenceBitmap; float scaleX = skReferenceBitmap.Width / item.Picture.CullRect.Width; float scaleY = skReferenceBitmap.Height / item.Picture.CullRect.Height; #if USE_COLORSPACE using var svgBitmap = item.Picture.ToBitmap(SKColors.Transparent, scaleX, scaleY, SKSvg.s_colorType, SKSvg.s_alphaType, SvgPaintingExtensions.Srgb); #else using var svgBitmap = item.Picture.ToBitmap(SKColors.Transparent, scaleX, scaleY, SKSvg.s_colorType, SKSvg.s_alphaType); #endif if (svgBitmap.Width == skReferenceBitmap.Width && svgBitmap.Height == skReferenceBitmap.Height) { var pixelDiff = PixelDiff(skReferenceBitmap, svgBitmap); item.PixelDiff = pixelDiff; } } catch (Exception ex) { Debug.WriteLine($"Failed to load reference png: {item.ReferencePngPath}"); Debug.WriteLine(ex.Message); Debug.WriteLine(ex.StackTrace); } }
private static TwitchEmote GetTwitchEmote(string fileName, string url, string name, string imageType, string id, int imageScale) { try { using (WebClient client = new WebClient()) { SKBitmap emoteBitmap = null; byte[] bytes = null; bool fileExists = File.Exists(fileName); if (fileExists) { //File may already be locked, can just download again from URL try { bytes = File.ReadAllBytes(fileName); } catch { } emoteBitmap = SKBitmap.Decode(bytes); } if (!fileExists || emoteBitmap == null) { bytes = client.DownloadData(url); try { //File may already be open, just a cache so can ignore File.WriteAllBytes(fileName, bytes); } catch { } emoteBitmap = SKBitmap.Decode(bytes); } MemoryStream ms = new MemoryStream(bytes); return(new TwitchEmote(new List <SKBitmap>() { emoteBitmap }, SKCodec.Create(ms), name, imageType, id, imageScale, bytes)); } } catch { return(null); } }
public void GetGifFrames() { const int FrameCount = 16; var stream = new SKFileStream(Path.Combine(PathToImages, "animated-heart.gif")); using (var codec = SKCodec.Create(stream)) { Assert.Equal(-1, codec.RepetitionCount); var frameInfos = codec.FrameInfo; Assert.Equal(FrameCount, frameInfos.Length); Assert.Equal(-1, frameInfos [0].RequiredFrame); var cachedFrames = new SKBitmap [FrameCount]; var info = new SKImageInfo(codec.Info.Width, codec.Info.Height); var decode = new Action <SKBitmap, bool, int> ((bm, cached, index) => { if (cached) { var requiredFrame = frameInfos [index].RequiredFrame; if (requiredFrame != -1) { Assert.True(cachedFrames [requiredFrame].CopyTo(bm)); } } var opts = new SKCodecOptions(index, cached); var result = codec.GetPixels(info, bm.GetPixels(), opts); Assert.Equal(SKCodecResult.Success, result); }); for (var i = 0; i < FrameCount; i++) { var cachedFrame = cachedFrames [i] = new SKBitmap(info); decode(cachedFrame, true, i); var uncachedFrame = new SKBitmap(info); decode(uncachedFrame, false, i); Assert.Equal(cachedFrame.Bytes, uncachedFrame.Bytes); } } }
private SKBitmap LoadBitmap(Stream stream, out SKEncodedOrigin origin) { using SKManagedStream s = new SKManagedStream(stream); using SKCodec codec = SKCodec.Create(s); origin = codec.EncodedOrigin; SKImageInfo info = codec.Info; SKBitmap bitmap = new SKBitmap(info.Width, info.Height, SKImageInfo.PlatformColorType, info.IsOpaque ? SKAlphaType.Opaque : SKAlphaType.Premul); SKCodecResult result = codec.GetPixels(bitmap.Info, bitmap.GetPixels(out IntPtr length)); if (result == SKCodecResult.Success || result == SKCodecResult.IncompleteInput) { return(bitmap); } else { throw new ArgumentException("Unable to load bitmap from provided data"); } }
public unsafe void StreamLosesOwnershipToCodecButIsNotForgotten() { var bytes = File.ReadAllBytes(Path.Combine(PathToImages, "color-wheel.png")); var stream = new SKMemoryStream(bytes); var handle = stream.Handle; Assert.True(stream.OwnsHandle); Assert.True(SKObject.GetInstance <SKMemoryStream>(handle, out _)); var codec = SKCodec.Create(stream); Assert.False(stream.OwnsHandle); stream.Dispose(); Assert.True(SKObject.GetInstance <SKMemoryStream>(handle, out _)); Assert.Equal(SKCodecResult.Success, codec.GetPixels(out var pixels)); Assert.NotEmpty(pixels); }