public virtual async Task <DataResolverResult> Resolve(string identifier, TaskParameter parameters, CancellationToken token) { var fileName = Path.GetFileNameWithoutExtension(identifier); DataResolverResult result = null; result = await ResolveFromBundlesAsync(fileName, identifier, parameters, token).ConfigureAwait(false); if (result != null) { return(result); } token.ThrowIfCancellationRequested(); result = await ResolveFromNamedResourceAsync(fileName, identifier, parameters, token).ConfigureAwait(false); if (result != null) { return(result); } token.ThrowIfCancellationRequested(); result = await ResolveFromAssetCatalogAsync(fileName, identifier, parameters, token).ConfigureAwait(false); if (result != null) { return(result); } throw new FileNotFoundException(identifier); }
public async Task <DataResolverResult> Resolve(string identifier, TaskParameter parameters, CancellationToken token) { var resolved = await _resolver.Resolve(identifier, parameters, token); if (resolved.Stream == null && resolved.Decoded == null) { throw new ArgumentNullException($"{nameof(resolved.Stream)} and {nameof(resolved.Decoded)}"); } if (resolved.Stream != null && !resolved.Stream.CanSeek) { using (resolved.Stream) { var memoryStream = new MemoryStream(); await resolved.Stream.CopyToAsync(memoryStream); memoryStream.Position = 0; resolved = new DataResolverResult(memoryStream, resolved.LoadingResult, resolved.ImageInformation); } } if (resolved.Stream != null) { if (resolved.Stream.Length == 0) { throw new InvalidDataException("Zero length stream"); } if (resolved.Stream.Length < 32) { throw new InvalidDataException("Invalid stream"); } if (resolved.ImageInformation.Type == ImageInformation.ImageType.Unknown) { //READ HEADER const int headerLength = 4; byte[] header = new byte[headerLength]; int offset = 0; while (offset < headerLength) { int read = await resolved.Stream.ReadAsync(header, offset, headerLength - offset); offset += read; } resolved.Stream.Position = 0; resolved.ImageInformation.SetType(FileHeader.GetImageType(header)); } if (resolved.ImageInformation.Type == ImageInformation.ImageType.JPEG) { var exif = ExifHelper.Read(resolved.Stream); resolved.Stream.Position = 0; resolved.ImageInformation.SetExif(exif); } } return(resolved); }
private async Task <DataResolverResult> ResolveFromNamedResourceAsync(string fileName, string identifier, TaskParameter parameters, CancellationToken token) { PImage image = null; try { #if __IOS__ || __TVOS__ await ImageService.Instance.Config.MainThreadDispatcher.PostAsync(() => image = PImage.FromBundle(identifier)).ConfigureAwait(false); #elif __MACOS__ await ImageService.Instance.Config.MainThreadDispatcher.PostAsync(() => image = PImage.ImageNamed(identifier)).ConfigureAwait(false); #endif } catch { } if (image == null && fileName != identifier) { try { #if __IOS__ || __TVOS__ await ImageService.Instance.Config.MainThreadDispatcher.PostAsync(() => image = PImage.FromBundle(fileName)).ConfigureAwait(false); #elif __MACOS__ await ImageService.Instance.Config.MainThreadDispatcher.PostAsync(() => image = PImage.ImageNamed(fileName)).ConfigureAwait(false); #endif } catch { } } if (image != null) { token.ThrowIfCancellationRequested(); var imageInformation = new ImageInformation(); imageInformation.SetPath(identifier); imageInformation.SetFilePath(null); var container = new DecodedImage <object>() { Image = image }; var result = new DataResolverResult(container, LoadingResult.CompiledResource, imageInformation); return(result); } return(null); }
private Task <DataResolverResult> ResolveFromBundlesAsync(string fileName, string identifier, TaskParameter parameters, CancellationToken token) { NSBundle bundle = null; var ext = Path.GetExtension(identifier)?.TrimStart(new char[] { '.' }); var tmpPath = Path.GetDirectoryName(identifier)?.Trim('/'); var filenamePath = string.IsNullOrWhiteSpace(tmpPath) ? null : tmpPath + "/"; var hasExtension = !string.IsNullOrWhiteSpace(ext); var fileTypes = hasExtension ? new[] { ext } : _fileTypes; foreach (var fileType in fileTypes) { string file = null; string lastPath = null; token.ThrowIfCancellationRequested(); var scale = (int)ScaleHelper.Scale; if (scale > 1) { while (scale > 1) { token.ThrowIfCancellationRequested(); var tmpFile = string.Format("{0}@{1}x", fileName, scale); bundle = NSBundle._AllBundles.FirstOrDefault(bu => { lastPath = string.IsNullOrWhiteSpace(filenamePath) ? bu.PathForResource(tmpFile, fileType) : bu.PathForResource(tmpFile, fileType, filenamePath); return(!string.IsNullOrWhiteSpace(lastPath)); }); if (bundle != null) { file = tmpFile; break; } scale--; } } token.ThrowIfCancellationRequested(); if (file == null) { bundle = NSBundle._AllBundles.FirstOrDefault(bu => { lastPath = string.IsNullOrWhiteSpace(filenamePath) ? bu.PathForResource(fileName, fileType) : bu.PathForResource(fileName, fileType, filenamePath); return(!string.IsNullOrWhiteSpace(lastPath)); }); } token.ThrowIfCancellationRequested(); if (bundle != null) { var stream = FileStore.GetInputStream(lastPath, true); var imageInformation = new ImageInformation(); imageInformation.SetPath(identifier); imageInformation.SetFilePath(lastPath); var result = new DataResolverResult(stream, LoadingResult.CompiledResource, imageInformation); return(Task.FromResult(result)); } } return(Task.FromResult <DataResolverResult>(null)); }
private async Task <DataResolverResult> Decode(SKPicture picture, SKBitmap bitmap, DataResolverResult resolvedData) { await StaticLocks.DecodingLock.WaitAsync().ConfigureAwait(false); try { #if __IOS__ var info = bitmap.Info; using (var provider = new CGDataProvider(bitmap.GetPixels(out var size), size.ToInt32())) using (var 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; using (var provider = new CGDataProvider(bitmap.GetPixels(out var size), size.ToInt32())) using (var 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__ //var pixels = bitmap.Pixels; //for (int i = 0; i < pixels.Length; i++) //{ // int bytePos = i * 4; // var color = pixels[i]; // pixelData[bytePos] = color.Blue; // pixelData[bytePos + 1] = color.Green; // pixelData[bytePos + 2] = color.Red; // pixelData[bytePos + 3] = color.Alpha; //} byte[] pixelData = new byte[bitmap.Width * bitmap.Height * 4]; System.Runtime.InteropServices.Marshal.Copy(bitmap.GetPixels(), pixelData, 0, bitmap.Width * bitmap.Height * 4); IDecodedImage <object> container = new DecodedImage <object>() { Image = new BitmapHolder(pixelData, bitmap.Width, bitmap.Height), }; return(new DataResolverResult(container, resolvedData.LoadingResult, resolvedData.ImageInformation)); #else 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)); } } #endif } finally { StaticLocks.DecodingLock.Release(); } }