private Task <EncodedImage> GetAsync(ICacheKey key, AtomicBoolean isCancelled)
        {
            try
            {
                if (isCancelled.Value)
                {
                    throw new OperationCanceledException();
                }

                EncodedImage result = _stagingArea.Get(key);
                if (result != null)
                {
                    Debug.WriteLine($"Found image for { key.ToString() } in staging area");
                    _imageCacheStatsTracker.OnStagingAreaHit();
                }
                else
                {
                    Debug.WriteLine($"Did not find image for { key.ToString() } in staging area");
                    _imageCacheStatsTracker.OnStagingAreaMiss();
                    try
                    {
                        IPooledByteBuffer buffer = ReadFromDiskCache(key);
                        if (buffer == null)
                        {
                            return(Task.FromResult(default(EncodedImage)));
                        }

                        CloseableReference <IPooledByteBuffer> reference =
                            CloseableReference <IPooledByteBuffer> .of(buffer);

                        try
                        {
                            result = new EncodedImage(reference);
                        }
                        finally
                        {
                            CloseableReference <IPooledByteBuffer> .CloseSafely(reference);
                        }
                    }
                    catch (Exception)
                    {
                        return(Task.FromResult(default(EncodedImage)));
                    }
                }

                return(Task.FromResult(result));
            }
            catch (Exception)
            {
                // Log failure
                // TODO: 3697790
                Debug.WriteLine($"Failed to schedule disk-cache read for { key.ToString() }");
                throw;
            }
        }
예제 #2
0
        public void Initialize()
        {
            // Initializes the IFileCache
            _fileCacheFactory = new DiskStorageCacheFactory(new DynamicDefaultDiskStorageFactory());
            _fileCache        = _fileCacheFactory.Get(DiskCacheConfig.NewBuilder().Build());

            // Initializes the IPooledByteBufferFactory and PooledByteStreams
            _poolFactory       = new PoolFactory(PoolConfig.NewBuilder().Build());
            _byteBufferFactory = _poolFactory.PooledByteBufferFactory;
            _pooledByteStreams = _poolFactory.PooledByteStreams;

            // Initializes the IPooledByteBuffer from an image
            var file = StorageFile.GetFileFromApplicationUriAsync(
                new Uri("ms-appx:///Assets/SplashScreen.scale-200.png")).GetAwaiter().GetResult();

            using (var stream = file.OpenReadAsync().GetAwaiter().GetResult())
            {
                _pooledByteBuffer = _byteBufferFactory.NewByteBuffer(
                    ByteStreams.ToByteArray(stream.AsStream()));
            }

            _closeableReference = CloseableReference <IPooledByteBuffer> .of(_pooledByteBuffer);

            _encodedImage           = new EncodedImage(_closeableReference);
            _stagingArea            = StagingArea.Instance;
            _imageCacheStatsTracker = NoOpImageCacheStatsTracker.Instance;

            // Initializes the cache keys
            IList <ICacheKey> keys = new List <ICacheKey>();

            keys.Add(new SimpleCacheKey("http://test.uri"));
            keys.Add(new SimpleCacheKey("http://tyrone.uri"));
            keys.Add(new SimpleCacheKey("http://ian.uri"));
            _cacheKey = new MultiCacheKey(keys);

            // Initializes the executors
            _isCancelled           = new AtomicBoolean(false);
            _readPriorityExecutor  = Executors.NewFixedThreadPool(1);
            _writePriorityExecutor = Executors.NewFixedThreadPool(1);

            // Initializes the disk cache
            _bufferedDiskCache = new BufferedDiskCache(
                _fileCache,
                _byteBufferFactory,
                _pooledByteStreams,
                _readPriorityExecutor,
                _writePriorityExecutor,
                _imageCacheStatsTracker);
        }
예제 #3
0
        public void TestFetchEncodedImageSuccess()
        {
            var completion     = new ManualResetEvent(false);
            var dataSource     = _imagePipeline.FetchEncodedImage(ImageRequest.FromUri(IMAGE_URL), null);
            var dataSubscriber = new BaseDataSubscriberImpl <CloseableReference <IPooledByteBuffer> >(
                async response =>
            {
                CloseableReference <IPooledByteBuffer> reference = response.GetResult();
                if (reference != null)
                {
                    IPooledByteBuffer inputStream = reference.Get();

                    try
                    {
                        Assert.IsTrue(inputStream.Size != 0);
                        Assert.IsTrue(await _imagePipeline.IsInDiskCacheAsync(IMAGE_URL).ConfigureAwait(false));
                    }
                    catch (Exception)
                    {
                        Assert.Fail();
                    }
                    finally
                    {
                        CloseableReference <IPooledByteBuffer> .CloseSafely(reference);
                        completion.Set();
                    }
                }
                else
                {
                    Assert.Fail();
                    completion.Set();
                }
            },
                response =>
            {
                Assert.Fail();
                completion.Set();
            });

            dataSource.Subscribe(dataSubscriber, CallerThreadExecutor.Instance);
            completion.WaitOne();
        }
        private async Task <EncodedImage> BuildEncodedImage(
            IPooledByteBuffer imageBytes,
            IRandomAccessStream imageStream)
        {
            using (var stream = imageStream.AsStream())
            {
                Tuple <int, int> dimensions = await BitmapUtil
                                              .DecodeDimensionsAsync(stream)
                                              .ConfigureAwait(false);

                int rotationAngle = GetRotationAngle(stream);
                int width         = dimensions != default(Tuple <int, int>) ?
                                    dimensions.Item1 :
                                    EncodedImage.UNKNOWN_WIDTH;

                int height = dimensions != default(Tuple <int, int>) ?
                             dimensions.Item2 :
                             EncodedImage.UNKNOWN_HEIGHT;

                EncodedImage encodedImage;
                CloseableReference <IPooledByteBuffer> closeableByteBuffer =
                    CloseableReference <IPooledByteBuffer> .of(imageBytes);

                try
                {
                    encodedImage = new EncodedImage(closeableByteBuffer);
                }
                finally
                {
                    CloseableReference <IPooledByteBuffer> .CloseSafely(
                        closeableByteBuffer);
                }

                encodedImage.Format        = ImageFormat.JPEG;
                encodedImage.RotationAngle = rotationAngle;
                encodedImage.Width         = width;
                encodedImage.Height        = height;

                return(encodedImage);
            }
        }
예제 #5
0
        /// <summary>
        /// Returns true if the image is a JPEG and its data is already complete
        /// at the specified length, false otherwise.
        /// </summary>
        public bool IsCompleteAt(int length)
        {
            if (Format != ImageFormat.JPEG)
            {
                return(true);
            }

            // If the image is backed by FileStream return true since they will
            // always be complete.
            if (_inputStreamSupplier != null)
            {
                return(true);
            }

            // The image should be backed by a ByteBuffer
            Preconditions.CheckNotNull(_pooledByteBufferRef);
            IPooledByteBuffer buf = _pooledByteBufferRef.Get();

            return((buf.Read(length - 2) == JfifUtil.MARKER_FIRST_BYTE) &&
                   (buf.Read(length - 1) == JfifUtil.MARKER_EOI));
        }
        /// <summary>
        /// Fetches the encoded BitmapImage.
        /// </summary>
        /// <param name="uri">The image uri.</param>
        /// <param name="token">The cancellation token.</param>
        /// <param name="dispatcher">
        /// The current view's dispatcher, used to create BitmapImage.
        /// </param>
        /// <returns>The encoded BitmapImage.</returns>
        /// <exception cref="IOException">
        /// If the image uri can't be found.
        /// </exception>
        public Task <BitmapImage> FetchEncodedBitmapImageAsync(
            Uri uri,
            CancellationToken token   = default(CancellationToken),
            CoreDispatcher dispatcher = null)
        {
            var taskCompletionSource = new TaskCompletionSource <BitmapImage>();
            var dataSource           = FetchEncodedImage(ImageRequest.FromUri(uri), null);
            var dataSubscriber       = new BaseDataSubscriberImpl <CloseableReference <IPooledByteBuffer> >(
                async response =>
            {
                CloseableReference <IPooledByteBuffer> reference = response.GetResult();
                if (reference != null)
                {
                    //----------------------------------------------------------------------
                    // Phong Cao: InMemoryRandomAccessStream can't write anything < 16KB.
                    // http://stackoverflow.com/questions/25928408/inmemoryrandomaccessstream-incorrect-behavior
                    //----------------------------------------------------------------------
                    IPooledByteBuffer inputStream = reference.Get();
                    int supportedSize             = Math.Max(16 * ByteConstants.KB, inputStream.Size);

                    // Allocate temp buffer for stream convert
                    byte[] bytesArray = default(byte[]);
                    CloseableReference <byte[]> bytesArrayRef = default(CloseableReference <byte[]>);

                    try
                    {
                        bytesArrayRef = _flexByteArrayPool.Get(supportedSize);
                        bytesArray    = bytesArrayRef.Get();
                    }
                    catch (Exception)
                    {
                        // Allocates the byte array since the pool couldn't provide one
                        bytesArray = new byte[supportedSize];
                    }

                    try
                    {
                        inputStream.Read(0, bytesArray, 0, inputStream.Size);
                        await DispatcherHelpers.CallOnDispatcherAsync(async() =>
                        {
                            using (var outStream = new InMemoryRandomAccessStream())
                                using (var writeStream = outStream.AsStreamForWrite())
                                {
                                    await writeStream.WriteAsync(bytesArray, 0, supportedSize);
                                    outStream.Seek(0);
                                    BitmapImage bitmapImage = new BitmapImage();
                                    await bitmapImage.SetSourceAsync(outStream).AsTask().ConfigureAwait(false);
                                    taskCompletionSource.SetResult(bitmapImage);
                                }
                        },
                                                                      dispatcher).ConfigureAwait(false);
                    }
                    catch (Exception e)
                    {
                        taskCompletionSource.SetException(e);
                    }
                    finally
                    {
                        CloseableReference <IPooledByteBuffer> .CloseSafely(reference);
                        CloseableReference <byte[]> .CloseSafely(bytesArrayRef);
                    }
                }
                else
                {
                    taskCompletionSource.SetResult(null);
                }
            },
                response =>
            {
                taskCompletionSource.SetException(response.GetFailureCause());
            });

            dataSource.Subscribe(dataSubscriber, _handleResultExecutor);
            token.Register(() =>
            {
                dataSource.Close();
                taskCompletionSource.TrySetCanceled();
            });

            return(taskCompletionSource.Task);
        }
        /// <summary>
        /// Start producing results for given context.
        /// Provided consumer is notified whenever progress is made
        /// (new value is ready or error occurs).
        /// </summary>
        public void ProduceResults(
            IConsumer <EncodedImage> consumer,
            IProducerContext producerContext)
        {
            IProducerListener listener     = producerContext.Listener;
            string            requestId    = producerContext.Id;
            ImageRequest      imageRequest = producerContext.ImageRequest;

            StatefulProducerRunnable <EncodedImage> cancellableProducerRunnable =
                new StatefulProducerRunnableImpl <EncodedImage>(
                    consumer,
                    listener,
                    PRODUCER_NAME,
                    requestId,
                    null,
                    null,
                    null,
                    (result) =>
            {
                IDictionary <string, string> extraMap = new Dictionary <string, string>()
                {
                    { CREATED_THUMBNAIL, (result != null).ToString() }
                };

                return(new ReadOnlyDictionary <string, string>(extraMap));
            },
                    null,
                    null,
                    (result) =>
            {
                EncodedImage.CloseSafely(result);
            },
                    async() =>
            {
                Uri sourceUri    = imageRequest.SourceUri;
                StorageFile file = await StorageFile
                                   .GetFileFromApplicationUriAsync(sourceUri)
                                   .AsTask()
                                   .ConfigureAwait(false);

                using (var fileStream = await file.OpenReadAsync().AsTask().ConfigureAwait(false))
                {
                    byte[] bytes = await BitmapUtil
                                   .GetThumbnailAsync(fileStream)
                                   .ConfigureAwait(false);

                    if (bytes != null)
                    {
                        IPooledByteBuffer pooledByteBuffer =
                            _pooledByteBufferFactory.NewByteBuffer(bytes);

                        return(await BuildEncodedImage(pooledByteBuffer, fileStream)
                               .ConfigureAwait(false));
                    }
                    else
                    {
                        return(null);
                    }
                }
            });

            producerContext.AddCallbacks(
                new BaseProducerContextCallbacks(
                    () =>
            {
                cancellableProducerRunnable.Cancel();
            },
                    () => { },
                    () => { },
                    () => { }));

            _executor.Execute(cancellableProducerRunnable.Runnable);
        }
 /// <summary>
 /// Creates a new inputstream instance over the specific buffer.
 /// </summary>
 /// <param name="pooledByteBuffer">
 /// The buffer to read from.
 /// </param>
 public PooledByteBufferInputStream(IPooledByteBuffer pooledByteBuffer)
 {
     Preconditions.CheckArgument(!pooledByteBuffer.IsClosed);
     _pooledByteBuffer = Preconditions.CheckNotNull(pooledByteBuffer);
     _currentOffset    = 0;
 }