Skip to content

Commit

Permalink
Fixed animated image rendering for dynamic frame dimensions
Browse files Browse the repository at this point in the history
Summary:
This fixes animated image rendering for frames with varying dimensions.
Our temp bitmap will increase in size during the first animated image loop and we will then draw the correct bounds of the set bitmap.

Fixes #2015

Reviewed By: erikandre

Differential Revision: D6726703

fbshipit-source-id: 57602c925bb59481885be3a7ef44e9c85dc76035
  • Loading branch information
oprisnik authored and facebook-github-bot committed Jan 16, 2018
1 parent 9077110 commit 086fd1d
Showing 1 changed file with 14 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.facebook.imagepipeline.animated.base.AnimatedImageFrame;
import com.facebook.imagepipeline.animated.base.AnimatedImageResult;
import com.facebook.imagepipeline.animated.util.AnimatedDrawableUtil;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;

/**
Expand All @@ -41,7 +42,7 @@ public class AnimatedDrawableBackendImpl implements AnimatedDrawableBackend {
private final Rect mRenderDstRect = new Rect();

@GuardedBy("this")
private Bitmap mTempBitmap;
private @Nullable Bitmap mTempBitmap;

public AnimatedDrawableBackendImpl(
AnimatedDrawableUtil animatedDrawableUtil,
Expand Down Expand Up @@ -185,12 +186,12 @@ public void renderFrame(int frameNumber, Canvas canvas) {
}
}

private void prepareTempBitmapForThisSize(int width, int height) {
private synchronized void prepareTempBitmapForThisSize(int width, int height) {
// Different gif frames can be different size,
// So we need to ensure we can fit next frame to temporary bitmap
if (mTempBitmap != null
&& (mTempBitmap.getWidth() < width || mTempBitmap.getHeight() < height)) {
dropCaches();
clearTempBitmap();
}
if (mTempBitmap == null) {
mTempBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Expand All @@ -208,12 +209,14 @@ private void renderImageSupportsScaling(Canvas canvas, AnimatedImageFrame frame)
int yOffset = (int) (frame.getYOffset() * yScale);

synchronized (this) {
prepareTempBitmapForThisSize(mRenderedBounds.width(), mRenderedBounds.height());
int renderedWidth = mRenderedBounds.width();
int renderedHeight = mRenderedBounds.height();
// Update the temp bitmap to be >= rendered dimensions
prepareTempBitmapForThisSize(renderedWidth, renderedHeight);
frame.renderFrame(frameWidth, frameHeight, mTempBitmap);

// Temporary bitmap can be bigger than frame, so we should draw only rendered area of bitmap
mRenderSrcRect.set(0, 0, mRenderedBounds.width(), mRenderedBounds.height());
mRenderDstRect.set(xOffset, yOffset, mRenderedBounds.width(), mRenderedBounds.height());
mRenderSrcRect.set(0, 0, renderedWidth, renderedHeight);
mRenderDstRect.set(xOffset, yOffset, xOffset + renderedWidth, yOffset + renderedHeight);

canvas.drawBitmap(mTempBitmap, mRenderSrcRect, mRenderDstRect, null);
}
Expand Down Expand Up @@ -244,6 +247,10 @@ private void renderImageDoesNotSupportScaling(Canvas canvas, AnimatedImageFrame

@Override
public synchronized void dropCaches() {
clearTempBitmap();
}

private synchronized void clearTempBitmap() {
if (mTempBitmap != null) {
mTempBitmap.recycle();
mTempBitmap = null;
Expand Down

0 comments on commit 086fd1d

Please sign in to comment.