@Override public CloseableImage decode( EncodedImage encodedImage, int length, QualityInfo qualityInfo, ImageDecodeOptions options) { ImageFormat imageFormat = encodedImage.getImageFormat(); if (imageFormat == DefaultImageFormats.JPEG) { return decodeJpeg(encodedImage, length, qualityInfo, options); } else if (imageFormat == DefaultImageFormats.GIF) { return decodeGif(encodedImage, length, qualityInfo, options); } else if (imageFormat == DefaultImageFormats.WEBP_ANIMATED) { return decodeAnimatedWebp(encodedImage, length, qualityInfo, options); } else if (imageFormat == ImageFormat.UNKNOWN) { throw new DecodeException("unknown image format", encodedImage); } return decodeStaticImage(encodedImage, options); }
/** * Decodes image. * * @param encodedImage input image (encoded bytes plus meta data) * @param length if image type supports decoding incomplete image then determines where the image * data should be cut for decoding. * @param qualityInfo quality information for the image * @param options options that cange decode behavior */ @Override public CloseableImage decode( final EncodedImage encodedImage, final int length, final QualityInfo qualityInfo, final ImageDecodeOptions options) { if (options.customImageDecoder != null) { return options.customImageDecoder.decode(encodedImage, length, qualityInfo, options); } ImageFormat imageFormat = encodedImage.getImageFormat(); if (imageFormat == null || imageFormat == ImageFormat.UNKNOWN) { imageFormat = ImageFormatChecker.getImageFormat_WrapIOException( encodedImage.getInputStream()); encodedImage.setImageFormat(imageFormat); } if (mCustomDecoders != null) { ImageDecoder decoder = mCustomDecoders.get(imageFormat); if (decoder != null) { return decoder.decode(encodedImage, length, qualityInfo, options); } } return mDefaultDecoder.decode(encodedImage, length, qualityInfo, options); }
/** * Decodes gif into CloseableImage. * * @param encodedImage input image (encoded bytes plus meta data) * @return a CloseableImage */ public CloseableImage decodeGif( final EncodedImage encodedImage, final int length, final QualityInfo qualityInfo, final ImageDecodeOptions options) { InputStream is = encodedImage.getInputStream(); if (is == null) { return null; } try { if (!options.forceStaticImage && mAnimatedGifDecoder != null) { return mAnimatedGifDecoder.decode(encodedImage, length, qualityInfo, options); } return decodeStaticImage(encodedImage, options); } finally { Closeables.closeQuietly(is); } }
/** * Decodes a partial jpeg. * * @param encodedImage input image (encoded bytes plus meta data) * @param length amount of currently available data in bytes * @param qualityInfo quality info for the image * @return a CloseableStaticBitmap */ public CloseableStaticBitmap decodeJpeg( final EncodedImage encodedImage, int length, QualityInfo qualityInfo, ImageDecodeOptions options) { CloseableReference<Bitmap> bitmapReference = mPlatformDecoder.decodeJPEGFromEncodedImage( encodedImage, options.bitmapConfig, null, length); try { return new CloseableStaticBitmap( bitmapReference, qualityInfo, encodedImage.getRotationAngle(), encodedImage.getExifOrientation()); } finally { bitmapReference.close(); } }
@Override public CloseableImage decode( EncodedImage encodedImage, int length, QualityInfo qualityInfo, ImageDecodeOptions options) { InputStream encodedInputStream = null; try { encodedInputStream = encodedImage.getInputStream(); return new CloseableKeyframesImage( KFImageDeserializer.deserialize(encodedInputStream)); } catch (IOException e) { e.printStackTrace(); return null; } finally { Closeables.closeQuietly(encodedInputStream); } }
private void logScan(QualityInfo qualityInfo, boolean isFinalImage) { mDebugOutput.append( String.format( Locale.getDefault(), "%s: %s, goodEnough=%b, fullQuality=%b, quality=%d\n\n", mDateFormat.format(new Date(System.currentTimeMillis())), isFinalImage ? "final" : "intermediate", qualityInfo.isOfGoodEnoughQuality(), qualityInfo.isOfFullQuality(), qualityInfo.getQuality())); // Scroll to the bottom mDebugOutputScrollView.post(new Runnable() { @Override public void run() { mDebugOutputScrollView.scrollTo(0, mDebugOutputScrollView.getBottom()); } }); }
@Override public ImageDecoder getGifDecoder(final Bitmap.Config bitmapConfig) { return new ImageDecoder() { @Override public CloseableImage decode( EncodedImage encodedImage, int length, QualityInfo qualityInfo, ImageDecodeOptions options) { return getAnimatedImageFactory().decodeGif(encodedImage, options, bitmapConfig); } }; }
@Override public ImageDecoder getWebPDecoder(final Bitmap.Config bitmapConfig) { return new ImageDecoder() { @Override public CloseableImage decode( EncodedImage encodedImage, int length, QualityInfo qualityInfo, ImageDecodeOptions options) { return getAnimatedImageFactory().decodeWebP(encodedImage, options, bitmapConfig); } }; }
@Override public QualityInfo getQualityInfo(int scanNumber) { return ImmutableQualityInfo.of( scanNumber, /* isOfGoodEnoughQuality */ scanNumber >= mDynamicValueConfig.getGoodEnoughScanNumber(), /* isOfFullQuality */ false); }
@Override public CloseableImage decode( EncodedImage encodedImage, int length, QualityInfo qualityInfo, ImageDecodeOptions options) { try { SVG svg = SVG.getFromInputStream(encodedImage.getInputStream()); return new CloseableSvgImage(svg); } catch (SVGParseException e) { e.printStackTrace(); } return null; }
@Override public CloseableImage decode( EncodedImage encodedImage, int length, QualityInfo qualityInfo, ImageDecodeOptions options) { try { // Read the file as a string String text = new String(ByteStreams.toByteArray(encodedImage.getInputStream())); // Check if the string matches "<color>#" if (!text.startsWith(COLOR_TAG + "#")) { return null; } // Parse the int value between # and < int startIndex = COLOR_TAG.length() + 1; int endIndex = text.lastIndexOf('<'); int color = Integer.parseInt(text.substring(startIndex, endIndex), 16); // Add the alpha component so that we actually see the color color = ColorUtils.setAlphaComponent(color, 255); // Return the CloseableImage return new CloseableColorImage(color); } catch (IOException e) { e.printStackTrace(); } // Return nothing if an error occurred return null; }
/** * Decodes gif into CloseableImage. * * @param encodedImage input image (encoded bytes plus meta data) * @return a CloseableImage */ public CloseableImage decodeGif( final EncodedImage encodedImage, final int length, final QualityInfo qualityInfo, final ImageDecodeOptions options) { if (!options.forceStaticImage && mAnimatedGifDecoder != null) { return mAnimatedGifDecoder.decode(encodedImage, length, qualityInfo, options); } return decodeStaticImage(encodedImage, options); }
CloseableImage decode( EncodedImage encodedImage, int length, QualityInfo qualityInfo, ImageDecodeOptions options);
@Override protected QualityInfo getQualityInfo() { return ImmutableQualityInfo.of(0, false, false); }
@Override protected QualityInfo getQualityInfo() { return mProgressiveJpegConfig.getQualityInfo(mProgressiveJpegParser.getBestScanNumber()); }
protected Consumer<CloseableReference<CloseableImage>> wrapConsumer( final Consumer<CloseableReference<CloseableImage>> consumer, final CacheKey cacheKey) { return new DelegatingConsumer< CloseableReference<CloseableImage>, CloseableReference<CloseableImage>>(consumer) { @Override public void onNewResultImpl( CloseableReference<CloseableImage> newResult, @Status int status) { final boolean isLast = isLast(status); // ignore invalid intermediate results and forward the null result if last if (newResult == null) { if (isLast) { getConsumer().onNewResult(null, status); } return; } // stateful and partial results cannot be cached and are just forwarded if (newResult.get().isStateful() || statusHasFlag(status, IS_PARTIAL_RESULT)) { getConsumer().onNewResult(newResult, status); 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 = mMemoryCache.get(cacheKey); if (currentCachedResult != null) { try { QualityInfo newInfo = newResult.get().getQualityInfo(); QualityInfo cachedInfo = currentCachedResult.get().getQualityInfo(); if (cachedInfo.isOfFullQuality() || cachedInfo.getQuality() >= newInfo.getQuality()) { getConsumer().onNewResult(currentCachedResult, status); return; } } finally { CloseableReference.closeSafely(currentCachedResult); } } } // cache and forward the new result CloseableReference<CloseableImage> newCachedResult = mMemoryCache.cache(cacheKey, newResult); try { if (isLast) { getConsumer().onProgressUpdate(1f); } getConsumer().onNewResult( (newCachedResult != null) ? newCachedResult : newResult, status); } finally { CloseableReference.closeSafely(newCachedResult); } } }; }
@Override public QualityInfo getQualityInfo() { return null; }
/** * Decode a webp animated image into a CloseableImage. * * <p> The image is decoded into a 'pinned' purgeable bitmap. * * @param encodedImage input image (encoded bytes plus meta data) * @param options * @return a {@link CloseableImage} */ public CloseableImage decodeAnimatedWebp( final EncodedImage encodedImage, final int length, final QualityInfo qualityInfo, final ImageDecodeOptions options) { return mAnimatedWebPDecoder.decode(encodedImage, length, qualityInfo, options); }