/** * @param encodedImage input image (encoded bytes plus meta data) * @return a CloseableStaticBitmap */ public CloseableStaticBitmap decodeStaticImage( final EncodedImage encodedImage, ImageDecodeOptions options) { CloseableReference<Bitmap> bitmapReference = mPlatformDecoder.decodeFromEncodedImage(encodedImage, options.bitmapConfig, null); try { return new CloseableStaticBitmap( bitmapReference, ImmutableQualityInfo.FULL_QUALITY, encodedImage.getRotationAngle(), encodedImage.getExifOrientation()); } finally { bitmapReference.close(); } }
@Test public void testCacheIntermediateImageAsBetterScan() { setupInputProducerStreamingSuccess(); CloseableImage closeableImage = mock(CloseableImage.class); when(closeableImage.getQualityInfo()) .thenReturn(ImmutableQualityInfo.of(INTERMEDIATE_SCAN_1, false, false)); CloseableReference<CloseableImage> closeableImageRef = CloseableReference.of(closeableImage); setupBitmapMemoryCacheGetSuccessOnSecondRead(closeableImageRef); mBitmapMemoryCacheProducer.produceResults(mConsumer, mProducerContext); verify(mMemoryCache).cache(mBitmapMemoryCacheKey, mIntermediateImageReference); verify(mMemoryCache).cache(mBitmapMemoryCacheKey, mFinalImageReference); verify(mConsumer).onNewResult(mIntermediateImageReferenceClone, Consumer.NO_FLAGS); verify(mConsumer).onNewResult(mFinalImageReferenceClone, Consumer.IS_LAST); Assert.assertTrue(!mIntermediateImageReferenceClone.isValid()); Assert.assertTrue(!mFinalImageReferenceClone.isValid()); Assert.assertEquals( 0, closeableImageRef.getUnderlyingReferenceTestOnly().getRefCountTestOnly()); verify(mProducerListener).onProducerStart(mRequestId, PRODUCER_NAME); Map<String, String> extraMap = ImmutableMap.of(BitmapMemoryCacheProducer.EXTRA_CACHED_VALUE_FOUND, "false"); verify(mProducerListener).onProducerFinishWithSuccess(mRequestId, PRODUCER_NAME, extraMap); verify(mProducerListener, never()) .onUltimateProducerReached(anyString(), anyString(), anyBoolean()); }
@Test public void testDontCacheIntermediateImageAsAlreadyHaveSameQuality() { setupInputProducerStreamingSuccess(); CloseableImage closeableImage = mock(CloseableImage.class); when(closeableImage.getQualityInfo()) .thenReturn(ImmutableQualityInfo.of(INTERMEDIATE_SCAN_2, true, false)); CloseableReference<CloseableImage> closeableImageRef = CloseableReference.of(closeableImage); setupBitmapMemoryCacheGetSuccessOnSecondRead(closeableImageRef); mBitmapMemoryCacheProducer.produceResults(mConsumer, mProducerContext); verify(mMemoryCache, never()).cache(mBitmapMemoryCacheKey, mIntermediateImageReference); verify(mMemoryCache).cache(mBitmapMemoryCacheKey, mFinalImageReference); verify(mConsumer).onNewResult(closeableImageRef, Consumer.NO_FLAGS); verify(mConsumer).onNewResult(mFinalImageReferenceClone, Consumer.IS_LAST); Assert.assertTrue(!mFinalImageReferenceClone.isValid()); Assert.assertEquals( 0, closeableImageRef.getUnderlyingReferenceTestOnly().getRefCountTestOnly()); verify(mProducerListener).onProducerStart(mRequestId, PRODUCER_NAME); Map<String, String> extraMap = ImmutableMap.of(BitmapMemoryCacheProducer.EXTRA_CACHED_VALUE_FOUND, "false"); verify(mProducerListener).onProducerFinishWithSuccess(mRequestId, PRODUCER_NAME, extraMap); verify(mProducerListener, never()) .onUltimateProducerReached(anyString(), anyString(), anyBoolean()); }
@Test public void testDontCacheIntermediateImageAsAlreadyHaveFullQuality() { setupBitmapMemoryCacheGetNotFound(); setupInputProducerStreamingSuccess(); CloseableImage closeableImage = mock(CloseableImage.class); when(closeableImage.getQualityInfo()).thenReturn(ImmutableQualityInfo.FULL_QUALITY); CloseableReference<CloseableImage> closeableImageRef = CloseableReference.of(closeableImage); setupBitmapMemoryCacheGetSuccessOnSecondRead(closeableImageRef); mBitmapMemoryCacheProducer.produceResults(mConsumer, mProducerContext); verify(mMemoryCache, never()).cache(mBitmapMemoryCacheKey, mIntermediateImageReference); verify(mMemoryCache).cache(mBitmapMemoryCacheKey, mFinalImageReference); verify(mConsumer).onNewResult(closeableImageRef, Consumer.NO_FLAGS); verify(mConsumer).onNewResult(mFinalImageReferenceClone, Consumer.IS_LAST); Assert.assertTrue(!mFinalImageReferenceClone.isValid()); Assert.assertEquals( 0, closeableImageRef.getUnderlyingReferenceTestOnly().getRefCountTestOnly()); verify(mProducerListener).onProducerStart(mRequestId, PRODUCER_NAME); Map<String, String> extraMap = ImmutableMap.of(BitmapMemoryCacheProducer.EXTRA_CACHED_VALUE_FOUND, "false"); verify(mProducerListener).onProducerFinishWithSuccess(mRequestId, PRODUCER_NAME, extraMap); verify(mProducerListener, never()) .onUltimateProducerReached(anyString(), anyString(), anyBoolean()); }
@Test public void testDecode_Final() throws Exception { setupNetworkUri(); produceResults(); JobScheduler.JobRunnable jobRunnable = getJobRunnable(); jobRunnable.run(mEncodedImage, Consumer.IS_LAST); InOrder inOrder = inOrder(mProducerListener, mImageDecoder); inOrder.verify(mProducerListener).onProducerStart(mRequestId, DecodeProducer.PRODUCER_NAME); inOrder.verify(mImageDecoder).decode( mEncodedImage, IMAGE_SIZE, ImmutableQualityInfo.FULL_QUALITY, IMAGE_DECODE_OPTIONS); inOrder.verify(mProducerListener).onProducerFinishWithSuccess( eq(mRequestId), eq(DecodeProducer.PRODUCER_NAME), any(Map.class)); verify(mProducerListener, never()) .onUltimateProducerReached(anyString(), anyString(), anyBoolean()); }
@Test public void testDecode_Intermediate_pJPEG() throws Exception { setupNetworkUri(); produceResults(); JobScheduler.JobRunnable jobRunnable = getJobRunnable(); when(mProgressiveJpegParser.isJpeg()).thenReturn(true); when(mProgressiveJpegParser.getBestScanEndOffset()).thenReturn(200); when(mProgressiveJpegParser.getBestScanNumber()).thenReturn(PREVIEW_SCAN); jobRunnable.run(mEncodedImage, Consumer.NO_FLAGS); InOrder inOrder = inOrder(mProducerListener, mImageDecoder); inOrder.verify(mProducerListener).onProducerStart(mRequestId, DecodeProducer.PRODUCER_NAME); inOrder.verify(mImageDecoder).decode( mEncodedImage, 200, ImmutableQualityInfo.of(PREVIEW_SCAN, false, false), IMAGE_DECODE_OPTIONS); inOrder.verify(mProducerListener).onProducerFinishWithSuccess( eq(mRequestId), eq(DecodeProducer.PRODUCER_NAME), any(Map.class)); inOrder.verifyNoMoreInteractions(); }
@Before public void setUp() { MockitoAnnotations.initMocks(this); mBitmapMemoryCacheGetProducer = new BitmapMemoryCacheGetProducer(mMemoryCache, mCacheKeyFactory, mInputProducer); mCloseableImage1 = mock(CloseableImage.class); mFinalImageReference = CloseableReference.of(mCloseableImage1); when(mCloseableImage1.getQualityInfo()).thenReturn(ImmutableQualityInfo.FULL_QUALITY); when(mProducerContext.getImageRequest()).thenReturn(mImageRequest); when(mProducerContext.getListener()).thenReturn(mProducerListener); when(mProducerContext.getId()).thenReturn(mRequestId); when(mProducerListener.requiresExtraMap(mRequestId)).thenReturn(true); when(mProducerContext.getLowestPermittedRequestLevel()) .thenReturn(ImageRequest.RequestLevel.FULL_FETCH); when(mProducerContext.getCallerContext()) .thenReturn(PRODUCER_NAME); when(mCacheKeyFactory.getBitmapCacheKey(mImageRequest, PRODUCER_NAME)).thenReturn(mCacheKey); }
@Nullable private static CloseableReference<CloseableImage> createImageReference( CloseableReference<Bitmap> bitmapReference) { // The given CloseableStaticBitmap will be cached and then released by the resource releaser // of the closeable reference CloseableImage closeableImage = new CloseableStaticBitmap(bitmapReference, ImmutableQualityInfo.FULL_QUALITY, 0); return CloseableReference.of(closeableImage); }
private CloseableImage getCloseableImage( ImageDecodeOptions options, AnimatedImage image, Bitmap.Config bitmapConfig) { List<CloseableReference<Bitmap>> decodedFrames = null; CloseableReference<Bitmap> previewBitmap = null; try { final int frameForPreview = options.useLastFrameForPreview ? image.getFrameCount() - 1 : 0; if (options.forceStaticImage) { return new CloseableStaticBitmap( createPreviewBitmap(image, bitmapConfig, frameForPreview), ImmutableQualityInfo.FULL_QUALITY, 0); } if (options.decodeAllFrames) { decodedFrames = decodeAllFrames(image, bitmapConfig); previewBitmap = CloseableReference.cloneOrNull(decodedFrames.get(frameForPreview)); } if (options.decodePreviewFrame && previewBitmap == null) { previewBitmap = createPreviewBitmap(image, bitmapConfig, frameForPreview); } AnimatedImageResult animatedImageResult = AnimatedImageResult.newBuilder(image) .setPreviewBitmap(previewBitmap) .setFrameForPreview(frameForPreview) .setDecodedFrames(decodedFrames) .build(); return new CloseableAnimatedImage(animatedImageResult); } finally { CloseableReference.closeSafely(previewBitmap); CloseableReference.closeSafely(decodedFrames); } }
@Override public QualityInfo getQualityInfo(int scanNumber) { return ImmutableQualityInfo.of( scanNumber, /* isOfGoodEnoughQuality */ scanNumber >= mDynamicValueConfig.getGoodEnoughScanNumber(), /* isOfFullQuality */ false); }
@Before public void setUp() { MockitoAnnotations.initMocks(this); mBitmapMemoryCacheProducer = new BitmapMemoryCacheProducer(mMemoryCache, mCacheKeyFactory, mInputProducer); mBitmapMemoryCacheKey = mock(BitmapMemoryCacheKey.class); mCloseableImage1 = mock(CloseableImage.class); when(mCloseableImage1.getQualityInfo()).thenReturn(ImmutableQualityInfo.FULL_QUALITY); mCloseableImage2 = mock(CloseableImage.class); when(mCloseableImage2.getQualityInfo()) .thenReturn(ImmutableQualityInfo.of(INTERMEDIATE_SCAN_2, true, false)); mFinalImageReference = CloseableReference.of(mCloseableImage1); mIntermediateImageReference = CloseableReference.of(mCloseableImage2); mFinalImageReferenceClone = mFinalImageReference.clone(); mIntermediateImageReferenceClone = mIntermediateImageReference.clone(); when(mMemoryCache.cache(mBitmapMemoryCacheKey, mIntermediateImageReference)) .thenReturn(mIntermediateImageReferenceClone); when(mMemoryCache.cache(mBitmapMemoryCacheKey, mFinalImageReference)) .thenReturn(mFinalImageReferenceClone); when(mProducerContext.getImageRequest()).thenReturn(mImageRequest); when(mProducerContext.getListener()).thenReturn(mProducerListener); when(mProducerContext.getId()).thenReturn(mRequestId); when(mProducerContext.getLowestPermittedRequestLevel()) .thenReturn(ImageRequest.RequestLevel.FULL_FETCH); when(mProducerContext.getCallerContext()).thenReturn(PRODUCER_NAME); when(mProducerListener.requiresExtraMap(mRequestId)).thenReturn(true); when(mCacheKeyFactory.getBitmapCacheKey(mImageRequest, PRODUCER_NAME)) .thenReturn(mBitmapMemoryCacheKey); }
@Test public void testDecode_Failure() throws Exception { setupNetworkUri(); produceResults(); JobScheduler.JobRunnable jobRunnable = getJobRunnable(); Exception exception = new RuntimeException(); when(mImageDecoder.decode( mEncodedImage, IMAGE_SIZE, ImmutableQualityInfo.FULL_QUALITY, IMAGE_DECODE_OPTIONS)) .thenThrow(exception); jobRunnable.run(mEncodedImage, Consumer.IS_LAST); InOrder inOrder = inOrder(mProducerListener, mImageDecoder); inOrder.verify(mProducerListener).onProducerStart(mRequestId, DecodeProducer.PRODUCER_NAME); inOrder.verify(mImageDecoder).decode( mEncodedImage, IMAGE_SIZE, ImmutableQualityInfo.FULL_QUALITY, IMAGE_DECODE_OPTIONS); inOrder.verify(mProducerListener).onProducerFinishWithFailure( eq(mRequestId), eq(DecodeProducer.PRODUCER_NAME), eq(exception), any(Map.class)); verify(mProducerListener, never()) .onUltimateProducerReached(anyString(), anyString(), anyBoolean()); }
@Override protected QualityInfo getQualityInfo() { return ImmutableQualityInfo.of(0, false, false); }