public void TestCloneOrNull()
        {
            EncodedImage encodedImage = new EncodedImage(_byteBufferRef);

            encodedImage.Format        = ImageFormat.JPEG;
            encodedImage.RotationAngle = 0;
            encodedImage.Width         = 1;
            encodedImage.Height        = 2;
            encodedImage.SampleSize    = 4;
            EncodedImage encodedImage2 = EncodedImage.CloneOrNull(encodedImage);

            Assert.AreEqual(3, _byteBufferRef.GetUnderlyingReferenceTestOnly().GetRefCountTestOnly());
            Assert.AreSame(
                encodedImage.GetByteBufferRef().GetUnderlyingReferenceTestOnly(),
                encodedImage2.GetByteBufferRef().GetUnderlyingReferenceTestOnly());
            Assert.AreEqual(encodedImage.Format, encodedImage2.Format);
            Assert.AreEqual(encodedImage.RotationAngle, encodedImage2.RotationAngle);
            Assert.AreEqual(encodedImage.Height, encodedImage2.Height);
            Assert.AreEqual(encodedImage.Width, encodedImage2.Width);
            Assert.AreEqual(encodedImage.SampleSize, encodedImage2.SampleSize);

            encodedImage               = new EncodedImage(_inputStreamSupplier, 100);
            encodedImage.Format        = ImageFormat.JPEG;
            encodedImage.RotationAngle = 0;
            encodedImage.Width         = 1;
            encodedImage.Height        = 2;
            encodedImage2              = EncodedImage.CloneOrNull(encodedImage);
            Assert.AreSame(encodedImage.GetInputStream(), encodedImage2.GetInputStream());
            Assert.AreEqual(encodedImage2.Size, encodedImage.Size);
        }
        /// <summary>
        /// Writes to disk cache.
        /// </summary>
        private void WriteToDiskCache(ICacheKey key, EncodedImage encodedImage)
        {
            Debug.WriteLine($"About to write to disk-cache for key { key.ToString() }");

            try
            {
                _fileCache.Insert(key, new WriterCallbackImpl(os =>
                {
                    _pooledByteStreams.Copy(encodedImage.GetInputStream(), os);
                }));

                Debug.WriteLine($"Successful disk-cache write for key { key.ToString() }");
            }
            catch (IOException)
            {
                // Log failure
                // TODO: 3697790
                Debug.WriteLine($"Failed to write to disk-cache for key { key.ToString() }");
            }
        }
예제 #3
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));
            }
        }
예제 #4
0
        /// <summary>
        /// If this is the first time calling this method, the buffer will
        /// be checked to make sure it starts with SOI marker (0xffd8).
        /// If the image has been identified as a non-JPEG, data will be
        /// ignored and false will be returned immediately on all
        /// subsequent calls.
        ///
        /// This object maintains state of the position of the last read
        /// byte. On repeated calls to this method, it will continue from
        /// where it left off.
        /// </summary>
        /// <param name="encodedImage">
        /// Next set of bytes received by the caller.
        /// </param>
        /// <returns>true if a new full scan has been found.</returns>
        public bool ParseMoreData(EncodedImage encodedImage)
        {
            if (_parserState == NOT_A_JPEG)
            {
                return(false);
            }

            int dataBufferSize = encodedImage.Size;

            // Is there any new data to parse?
            // _bytesParsed might be greater than size of dataBuffer - that
            // happens when we skip more data than is available to read
            // inside DoParseMoreData method.
            if (dataBufferSize <= _bytesParsed)
            {
                return(false);
            }

            Stream bufferedDataStream = new PooledByteArrayBufferedInputStream(
                encodedImage.GetInputStream(),
                _byteArrayPool.Get(BUFFER_SIZE),
                _byteArrayPool);

            try
            {
                StreamUtil.Skip(bufferedDataStream, _bytesParsed);
                return(DoParseMoreData(encodedImage, bufferedDataStream));
            }
            catch (IOException)
            {
                // Does not happen - streams returned by IPooledByteBuffers
                // do not throw IOExceptions.
                throw;
            }
            finally
            {
                Closeables.CloseQuietly(bufferedDataStream);
            }
        }
예제 #5
0
        /// <summary>
        /// Creates a bitmap from encoded bytes.
        /// Supports JPEG but callers should use DecodeJPEGFromEncodedImage
        /// for partial JPEGs.
        /// </summary>
        /// <param name="encodedImage">
        /// The reference to the encoded image with the reference to the
        /// encoded bytes.
        /// </param>
        /// <param name="bitmapConfig">
        /// The <see cref="BitmapPixelFormat"/> used to create the decoded
        /// SoftwareBitmap.
        /// </param>
        /// <returns>The bitmap.</returns>
        /// <exception cref="OutOfMemoryException">
        /// If the Bitmap cannot be allocated.
        /// </exception>
        public Task <CloseableReference <SoftwareBitmap> > DecodeFromEncodedImageAsync(
            EncodedImage encodedImage, BitmapPixelFormat bitmapConfig)
        {
            Stream inputStream = encodedImage.GetInputStream();

            Preconditions.CheckNotNull(inputStream);
            return(_executor.Execute(async() =>
            {
                BitmapDecoder decoder = await BitmapDecoder.CreateAsync(
                    inputStream.AsRandomAccessStream())
                                        .AsTask()
                                        .ConfigureAwait(false);

                SoftwareBitmap bitmap = await decoder
                                        .GetSoftwareBitmapAsync(bitmapConfig, BitmapAlphaMode.Premultiplied)
                                        .AsTask()
                                        .ConfigureAwait(false);

                return CloseableReference <SoftwareBitmap> .of(bitmap);
            })
                   .Unwrap());
        }
예제 #6
0
        /// <summary>
        /// Creates a bitmap from encoded JPEG bytes.
        /// Supports a partial JPEG image.
        /// </summary>
        /// <param name="encodedImage">
        /// The reference to the encoded image with the reference to the
        /// encoded bytes.
        /// </param>
        /// <param name="bitmapConfig">
        /// The <see cref="BitmapPixelFormat"/> used to create the decoded
        /// SoftwareBitmap.
        /// </param>
        /// <param name="length">
        /// The number of encoded bytes in the buffer.
        /// </param>
        /// <returns>The bitmap.</returns>
        /// <exception cref="OutOfMemoryException">
        /// If the Bitmap cannot be allocated.
        /// </exception>
        public Task <CloseableReference <SoftwareBitmap> > DecodeJPEGFromEncodedImageAsync(
            EncodedImage encodedImage, BitmapPixelFormat bitmapConfig, int length)
        {
            return(_executor.Execute(async() =>
            {
                bool isJpegComplete = encodedImage.IsCompleteAt(length);
                Stream jpegDataStream = encodedImage.GetInputStream();

                // At this point the Stream from the encoded image should not
                // be null since in the pipeline,this comes from a call stack where
                // this was checked before. Also this method needs the Stream to
                // decode the image so this can't be null.
                Preconditions.CheckNotNull(jpegDataStream);
                if (encodedImage.Size > length)
                {
                    jpegDataStream = new LimitedInputStream(jpegDataStream, length);
                }

                if (!isJpegComplete)
                {
                    jpegDataStream = new TailAppendingInputStream(jpegDataStream, EOI_TAIL);
                }

                BitmapDecoder decoder = await BitmapDecoder.CreateAsync(
                    jpegDataStream.AsRandomAccessStream())
                                        .AsTask()
                                        .ConfigureAwait(false);

                SoftwareBitmap bitmap = await decoder
                                        .GetSoftwareBitmapAsync(bitmapConfig, BitmapAlphaMode.Premultiplied)
                                        .AsTask()
                                        .ConfigureAwait(false);

                return CloseableReference <SoftwareBitmap> .of(bitmap);
            })
                   .Unwrap());
        }
예제 #7
0
        /// <summary>
        /// Decodes gif into CloseableImage.
        /// </summary>
        /// <param name="encodedImage">
        /// Input image (encoded bytes plus meta data).
        /// </param>
        /// <param name="options">Decode options.</param>
        /// <returns>A CloseableImage.</returns>
        public Task <CloseableImage> DecodeGifAsync(
            EncodedImage encodedImage,
            ImageDecodeOptions options)
        {
            Stream inputStream = encodedImage.GetInputStream();

            if (inputStream == null)
            {
                return(Task.FromResult(default(CloseableImage)));
            }

            try
            {
                // Phong Cao: always forceStaticImage
                return(DecodeStaticImageAsync(encodedImage)
                       .ContinueWith(
                           task => ((CloseableImage)task.Result),
                           TaskContinuationOptions.ExecuteSynchronously));
            }
            finally
            {
                Closeables.CloseQuietly(inputStream);
            }
        }
        public void TestInputStream()
        {
            EncodedImage encodedImage = new EncodedImage(_inputStreamSupplier);

            Assert.AreSame(encodedImage.GetInputStream(), _inputStreamSupplier.Get());
        }