/* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.imagepipeline.producers; import java.io.InputStream; import java.util.concurrent.Executor; import com.facebook.common.references.CloseableReference; import com.facebook.common.util.TriState; import com.facebook.imageformat.ImageFormat; import com.facebook.imageformat.ImageFormatChecker; import com.facebook.imagepipeline.memory.PooledByteBuffer; import com.facebook.imagepipeline.memory.PooledByteBufferFactory; import com.facebook.imagepipeline.memory.PooledByteBufferOutputStream; import com.facebook.imagepipeline.nativecode.WebpTranscoder; import com.facebook.imagepipeline.request.ImageRequest; /** * Transcodes webps to jpegs. * * <p> If processed image is one of VP8, VP8X or VP8L non-animated webps then * it is transcoded to jpeg if Android's decoder does not support this format. * If image is of any other type, no transformation is applied. */ public class WebpTranscodeProducer extends ImageTransformProducer<CloseableReference<PooledByteBuffer>, Void> { private static final String PRODUCER_NAME = "WebpTranscodeProducer"; private static final int DEFAULT_JPEG_QUALITY = 80; public WebpTranscodeProducer( Executor executor, PooledByteBufferFactory pooledByteBufferFactory, Producer<CloseableReference<PooledByteBuffer>> nextProducer) { super(executor, pooledByteBufferFactory, nextProducer); } @Override protected TriState shouldTransform( final CloseableReference<PooledByteBuffer> imageRef, final ImageRequest imageRequest, boolean isLast) { InputStream imageInputStream = imageRef.get().getStream(); ImageFormat imageFormat = ImageFormatChecker.getImageFormat_WrapIOException(imageInputStream); switch (imageFormat) { case WEBP_SIMPLE: case WEBP_LOSSLESS: case WEBP_EXTENDED: case WEBP_EXTENDED_WITH_ALPHA: return TriState.valueOf(!WebpTranscoder.isWebpNativelySupported(imageFormat)); case UNKNOWN: return isLast ? TriState.NO : TriState.UNSET; default: return TriState.NO; } } @Override protected void transform( final CloseableReference<PooledByteBuffer> imageRef, final PooledByteBufferOutputStream outputStream, ImageRequest imageRequest, Void unused) throws Exception { InputStream imageInputStream = imageRef.get().getStream(); ImageFormat imageFormat = ImageFormatChecker.getImageFormat_WrapIOException(imageInputStream); switch (imageFormat) { case WEBP_SIMPLE: case WEBP_EXTENDED: WebpTranscoder.transcodeWebpToJpeg(imageInputStream, outputStream, DEFAULT_JPEG_QUALITY); break; case WEBP_LOSSLESS: case WEBP_EXTENDED_WITH_ALPHA: WebpTranscoder.transcodeWebpToPng(imageInputStream, outputStream); break; default: throw new IllegalArgumentException("Wrong image format"); } } @Override protected CloseableReference<PooledByteBuffer> getImageCopy( CloseableReference<PooledByteBuffer> originalResult) { return originalResult.clone(); } @Override protected Void getExtraInformation( CloseableReference<PooledByteBuffer> originalResult) { return null; } @Override protected CloseableReference<PooledByteBuffer> createReturnValue( PooledByteBuffer transformedBytes, Void unused) { return CloseableReference.of(transformedBytes); } @Override protected void closeReturnValue(CloseableReference<PooledByteBuffer> returnValue) { CloseableReference.closeSafely(returnValue); } @Override protected String getProducerName() { return PRODUCER_NAME; } @Override protected boolean shouldAllowCancellation() { return false; } }