/// <summary>
 /// Creates a new instance of a CloseableStaticBitmap from an existing
 /// CloseableReference. The CloseableStaticBitmap will hold a reference
 /// to the bitmap until it's closed.
 /// </summary>
 public CloseableStaticBitmap(
     CloseableReference <SoftwareBitmap> bitmapReference,
     IQualityInfo qualityInfo,
     int rotationAngle)
 {
     _bitmapReference = Preconditions.CheckNotNull(bitmapReference.CloneOrNull());
     _bitmap          = _bitmapReference.Get();
     _qualityInfo     = qualityInfo;
     _rotationAngle   = rotationAngle;
 }
            /// <summary>
            /// Performs the decode synchronously.
            /// </summary>
            private async Task DoDecode(EncodedImage encodedImage, bool isLast)
            {
                if (IsFinished() || !EncodedImage.IsValid(encodedImage))
                {
                    return;
                }

                try
                {
                    long queueTime = _jobScheduler.GetQueuedTime();
                    int  length    = isLast ?
                                     encodedImage.Size : GetIntermediateImageEndOffset(encodedImage);

                    if (length == 0)
                    {
                        return;
                    }

                    IQualityInfo quality = isLast ? ImmutableQualityInfo.FULL_QUALITY : GetQualityInfo();

                    _producerListener.OnProducerStart(_producerContext.Id, PRODUCER_NAME);
                    CloseableImage image = null;

                    try
                    {
                        image = await _parent._imageDecoder
                                .DecodeImageAsync(encodedImage, length, quality, _imageDecodeOptions)
                                .ConfigureAwait(false);
                    }
                    catch (Exception e)
                    {
                        _producerListener.OnProducerFinishWithFailure(
                            _producerContext.Id,
                            PRODUCER_NAME,
                            e,
                            GetExtraMap(image, queueTime, quality, isLast));

                        HandleError(e);
                        return;
                    }

                    _producerListener.OnProducerFinishWithSuccess(
                        _producerContext.Id,
                        PRODUCER_NAME,
                        GetExtraMap(image, queueTime, quality, isLast));

                    HandleResult(image, isLast);
                }
                finally
                {
                    EncodedImage.CloseSafely(encodedImage);
                }
            }
        /// <summary>
        /// Creates a new instance of a CloseableStaticBitmap.
        /// </summary>
        public CloseableStaticBitmap(
            SoftwareBitmap bitmap,
            IResourceReleaser <SoftwareBitmap> resourceReleaser,
            IQualityInfo qualityInfo,
            int rotationAngle)
        {
            _bitmap          = Preconditions.CheckNotNull(bitmap);
            _bitmapReference = CloseableReference <SoftwareBitmap> .of(
                _bitmap,
                Preconditions.CheckNotNull(resourceReleaser));

            _qualityInfo   = qualityInfo;
            _rotationAngle = rotationAngle;
        }
            private IDictionary <string, string> GetExtraMap(
                CloseableImage image,
                long queueTime,
                IQualityInfo quality,
                bool isFinal)
            {
                if (!_producerListener.RequiresExtraMap(_producerContext.Id))
                {
                    return(null);
                }

                string queueStr       = queueTime.ToString();
                string qualityStr     = quality.IsOfGoodEnoughQuality.ToString();
                string finalStr       = isFinal.ToString();
                string cacheChoiceStr = _producerContext.ImageRequest.CacheChoice.ToString();

                if (image.GetType() == typeof(CloseableStaticBitmap))
                {
                    SoftwareBitmap bitmap   = ((CloseableStaticBitmap)image).UnderlyingBitmap;
                    string         sizeStr  = bitmap.PixelWidth + "x" + bitmap.PixelHeight;
                    var            extraMap = new Dictionary <string, string>()
                    {
                        { BITMAP_SIZE_KEY, sizeStr },
                        { JobScheduler.QUEUE_TIME_KEY, queueStr },
                        { HAS_GOOD_QUALITY_KEY, qualityStr },
                        { IS_FINAL_KEY, finalStr },
                        { IMAGE_TYPE_KEY, cacheChoiceStr }
                    };

                    return(new ReadOnlyDictionary <string, string>(extraMap));
                }
                else
                {
                    var extraMap = new Dictionary <string, string>()
                    {
                        { JobScheduler.QUEUE_TIME_KEY, queueStr },
                        { HAS_GOOD_QUALITY_KEY, qualityStr },
                        { IS_FINAL_KEY, finalStr },
                        { IMAGE_TYPE_KEY, cacheChoiceStr }
                    };

                    return(new ReadOnlyDictionary <string, string>(extraMap));
                }
            }
Exemplo n.º 5
0
        /// <summary>
        /// Decodes image.
        /// </summary>
        /// <param name="encodedImage">
        /// Input image (encoded bytes plus meta data).
        /// </param>
        /// <param name="length">
        /// If image type supports decoding incomplete image then
        /// determines where the image data should be cut for decoding.
        /// </param>
        /// <param name="qualityInfo">
        /// Quality information for the image.
        /// </param>
        /// <param name="options">
        /// Options that cange decode behavior.
        /// </param>
        public Task <CloseableImage> DecodeImageAsync(
            EncodedImage encodedImage,
            int length,
            IQualityInfo qualityInfo,
            ImageDecodeOptions options)
        {
            ImageFormat imageFormat = encodedImage.Format;

            if (imageFormat == ImageFormat.UNINITIALIZED || imageFormat == ImageFormat.UNKNOWN)
            {
                imageFormat = ImageFormatChecker.GetImageFormat_WrapIOException(
                    encodedImage.GetInputStream());

                encodedImage.Format = imageFormat;
            }

            switch (imageFormat)
            {
            case ImageFormat.UNKNOWN:
                throw new ArgumentException("unknown image format");

            case ImageFormat.JPEG:
                return(DecodeJpegAsync(encodedImage, length, qualityInfo)
                       .ContinueWith(
                           task => ((CloseableImage)task.Result),
                           TaskContinuationOptions.ExecuteSynchronously));

            case ImageFormat.GIF:
                return(DecodeGifAsync(encodedImage, options));

            case ImageFormat.WEBP_ANIMATED:
                return(DecodeAnimatedWebpAsync(encodedImage, options));

            default:
                return(DecodeStaticImageAsync(encodedImage)
                       .ContinueWith(
                           task => ((CloseableImage)task.Result),
                           TaskContinuationOptions.ExecuteSynchronously));
            }
        }
Exemplo n.º 6
0
 /// <summary>
 /// Decodes a partial jpeg.
 /// </summary>
 /// <param name="encodedImage">
 /// Input image (encoded bytes plus meta data).
 /// </param>
 /// <param name="length">
 /// Amount of currently available data in bytes.
 /// </param>
 /// <param name="qualityInfo">
 /// Quality info for the image.
 /// </param>
 /// <returns>A CloseableStaticBitmap.</returns>
 public Task <CloseableStaticBitmap> DecodeJpegAsync(
     EncodedImage encodedImage,
     int length,
     IQualityInfo qualityInfo)
 {
     return(_platformDecoder
            .DecodeJPEGFromEncodedImageAsync(encodedImage, _bitmapConfig, length)
            .ContinueWith(
                task =>
     {
         try
         {
             return new CloseableStaticBitmap(
                 task.Result,
                 qualityInfo,
                 encodedImage.RotationAngle);
         }
         finally
         {
             task.Result.Dispose();
         }
     },
                TaskContinuationOptions.ExecuteSynchronously));
 }
            protected override void OnNewResultImpl(
                CloseableReference <CloseableImage> newResult,
                bool isLast)
            {
                // Ignore invalid intermediate results and forward the null result if last
                if (newResult == null)
                {
                    if (isLast)
                    {
                        Consumer.OnNewResult(null, true);
                    }

                    return;
                }

                // Stateful results cannot be cached and are just forwarded
                if (newResult.Get().Stateful)
                {
                    Consumer.OnNewResult(newResult, isLast);
                    return;
                }

                // If the intermediate result is not of a better quality than the cached
                // result, forward the already cached result and don't cache the new result.
                if (!isLast)
                {
                    CloseableReference <CloseableImage> currentCachedResult = _memoryCache.Get(_cacheKey);
                    if (currentCachedResult != null)
                    {
                        try
                        {
                            IQualityInfo newInfo    = newResult.Get().QualityInfo;
                            IQualityInfo cachedInfo = currentCachedResult.Get().QualityInfo;
                            if (cachedInfo.IsOfFullQuality || cachedInfo.Quality >= newInfo.Quality)
                            {
                                Consumer.OnNewResult(currentCachedResult, false);
                                return;
                            }
                        }
                        finally
                        {
                            CloseableReference <CloseableImage> .CloseSafely(currentCachedResult);
                        }
                    }
                }

                // Cache and forward the new result
                CloseableReference <CloseableImage> newCachedResult =
                    _memoryCache.Cache(_cacheKey, newResult);

                try
                {
                    if (isLast)
                    {
                        Consumer.OnProgressUpdate(1f);
                    }

                    Consumer.OnNewResult(
                        (newCachedResult != null) ? newCachedResult : newResult, isLast);
                }
                finally
                {
                    CloseableReference <CloseableImage> .CloseSafely(newCachedResult);
                }
            }