/*
* 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.animated.factory;
import android.graphics.Bitmap;
import com.facebook.common.internal.Preconditions;
import com.facebook.common.references.CloseableReference;
import com.facebook.common.references.ResourceReleaser;
import com.facebook.imagepipeline.animated.base.AnimatedDrawableBackend;
import com.facebook.imagepipeline.animated.base.AnimatedImage;
import com.facebook.imagepipeline.animated.base.AnimatedImageResult;
import com.facebook.imagepipeline.animated.impl.AnimatedDrawableBackendProvider;
import com.facebook.imagepipeline.animated.impl.AnimatedImageCompositor;
import com.facebook.imagepipeline.common.ImageDecodeOptions;
import com.facebook.imagepipeline.gif.GifImage;
import com.facebook.imagepipeline.image.CloseableAnimatedImage;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.memory.PooledByteBuffer;
import com.facebook.imagepipeline.webp.WebPImage;
/**
* Decoder for animated images.
*/
public class AnimatedImageFactory {
private final AnimatedDrawableBackendProvider mAnimatedDrawableBackendProvider;
public AnimatedImageFactory(
AnimatedDrawableBackendProvider animatedDrawableBackendProvider) {
mAnimatedDrawableBackendProvider = animatedDrawableBackendProvider;
}
/**
* Decodes a GIF into a CloseableImage.
*
* @param pooledByteBufferRef native byte array holding the encoded bytes
* @param options the options for the decode
* @return a {@link CloseableImage} for the GIF image
*/
public CloseableImage decodeGif(
final CloseableReference<PooledByteBuffer> pooledByteBufferRef,
final ImageDecodeOptions options) {
Preconditions.checkState(!options.forceOldAnimationCode);
final PooledByteBuffer input = pooledByteBufferRef.get();
GifImage gifImage = GifImage.create(input.getNativePtr(), input.size());
return getCloseableImage(options, gifImage);
}
/**
* Decode a WebP into a CloseableImage.
*
* @param pooledByteBufferRef native byte array holding the encoded bytes
* @param options the options for the decode
* @return a {@link CloseableImage} for the WebP image
*/
public CloseableImage decodeWebP(
final CloseableReference<PooledByteBuffer> pooledByteBufferRef,
final ImageDecodeOptions options) {
Preconditions.checkArgument(!options.forceOldAnimationCode);
final PooledByteBuffer input = pooledByteBufferRef.get();
WebPImage webPImage = WebPImage.create(input.getNativePtr(), input.size());
return getCloseableImage(options, webPImage);
}
private CloseableImage getCloseableImage(ImageDecodeOptions options, AnimatedImage image) {
int frameForPreview = options.useLastFrameForPreview ? image.getFrameCount() - 1 : 0;
CloseableReference<Bitmap> previewBitmap = null;
if (options.decodePreviewFrame) {
previewBitmap = createPreviewBitmap(image, frameForPreview);
}
try {
AnimatedImageResult animatedImageResult = AnimatedImageResult.newBuilder(image)
.setPreviewBitmap(previewBitmap)
.setFrameForPreview(frameForPreview)
.build();
return new CloseableAnimatedImage(animatedImageResult);
} finally {
CloseableReference.closeSafely(previewBitmap);
}
}
private CloseableReference<Bitmap> createPreviewBitmap(
AnimatedImage image,
int frameForPreview) {
Bitmap previewBitmap;
previewBitmap = Bitmap.createBitmap(
image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
AnimatedImageResult tempResult = AnimatedImageResult.forAnimatedImage(image);
AnimatedDrawableBackend drawableBackend =
mAnimatedDrawableBackendProvider.get(tempResult, null);
AnimatedImageCompositor animatedImageCompositor = new AnimatedImageCompositor(
drawableBackend,
new AnimatedImageCompositor.Callback() {
@Override
public void onIntermediateResult(int frameNumber, Bitmap bitmap) {
// Don't care.
}
@Override
public CloseableReference<Bitmap> getCachedBitmap(int frameNumber) {
return null;
}
});
animatedImageCompositor.renderFrame(frameForPreview, previewBitmap);
return CloseableReference.of(
previewBitmap,
new ResourceReleaser<Bitmap>() {
@Override
public void release(Bitmap value) {
value.recycle();
}
});
}
}