예제 #1
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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));
        }
예제 #5
0
        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();
            }
        }