private void renderScalingFrames(
      Canvas canvas,
      AnimatedImageFrame frame,
      AnimatedDrawableFrameInfo frameInfo,
      @Nullable AnimatedDrawableFrameInfo previousFrameInfo) {
    int assetWidth = mAnimatedImage.getWidth();
    int assetHeight = mAnimatedImage.getHeight();

    // Find the best scale asset size. Maximum scaleSize would be the assetSize.
    float scaledWidth = assetWidth;
    float scaledHeight = assetHeight;

    // Apply the scale to the frame
    float xScale = 1f;
    float yScale = 1f;

    int frameWidth = frame.getWidth();
    int frameHeight = frame.getHeight();
    int xOffset = frame.getXOffset();
    int yOffset = frame.getYOffset();

    // Check if we need to down scale the asset to the canvas size
    if (scaledWidth > canvas.getWidth() || scaledHeight > canvas.getHeight()) {
      // Canvas could have wrong sizes as 314573336x200. Then we limit the frame sizes
      int maxCanvasWidth = Math.min(canvas.getWidth(), assetWidth);
      int maxCanvasHeight = Math.min(canvas.getHeight(), assetHeight);

      float assetRatio = assetWidth / (float) assetHeight;
      if (maxCanvasWidth > maxCanvasHeight) {
        scaledWidth = maxCanvasWidth;
        scaledHeight = maxCanvasWidth / assetRatio;
      } else {
        scaledWidth = maxCanvasHeight * assetRatio;
        scaledHeight = maxCanvasHeight;
      }

      xScale = scaledWidth / (float) assetWidth;
      yScale = scaledHeight / (float) assetHeight;

      frameWidth = (int) Math.ceil(frame.getWidth() * xScale);
      frameHeight = (int) Math.ceil(frame.getHeight() * yScale);
      xOffset = (int) Math.ceil(frame.getXOffset() * xScale);
      yOffset = (int) Math.ceil(frame.getYOffset() * yScale);
    }

    Rect renderSrcRect = new Rect(0, 0, frameWidth, frameHeight);
    Rect renderDstRect = new Rect(xOffset, yOffset, xOffset + frameWidth, yOffset + frameHeight);

    // Clean previous frame surface if that frame was disposable
    if (previousFrameInfo != null) {
      maybeDisposeBackground(canvas, xScale, yScale, previousFrameInfo);
    }

    // If current frame is no_blend, then we have to clean their surface before rendering
    if (frameInfo.blendOperation == BlendOperation.NO_BLEND) {
      canvas.drawRect(renderDstRect, mTransparentPaint);
    }

    synchronized (this) {
      // Impress the frame in the bitmap
      Bitmap frameBitmap = prepareTempBitmapForThisSize(frameWidth, frameHeight);
      frame.renderFrame(frameWidth, frameHeight, frameBitmap);
      canvas.drawBitmap(frameBitmap, renderSrcRect, renderDstRect, null);
    }
  }
An {@link AnimatedDrawableBackend} that renders {@link AnimatedImage}.
animated-base/src/main/java/com/facebook/imagepipeline/animated/impl/AnimatedDrawableBackendImpl.java