docs: public void renderFrame(int frameNumber, Bitmap bitmap) {
      Canvas canvas = new Canvas(bitmap);
      canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
  
      // If blending is required, prepare the canvas with the nearest cached frame.
      int nextIndex;
      if (!isKeyFrame(frameNumber)) {
        // Blending is required. nextIndex points to the next index to render onto the canvas.
        nextIndex = prepareCanvasWithClosestCachedFrame(frameNumber - 1, canvas);
      } else {
        // Blending isn't required. Start at the frame we're trying to render.
        nextIndex = frameNumber;
      }
  
      // Iterate from nextIndex to the frame number just preceding the one we're trying to render
      // and composite them in order according to the Disposal Method.
      for (int index = nextIndex; index < frameNumber; index++) {
        AnimatedDrawableFrameInfo frameInfo = mAnimatedDrawableBackend.getFrameInfo(index);
        DisposalMethod disposalMethod = frameInfo.disposalMethod;
        if (disposalMethod == DisposalMethod.DISPOSE_TO_PREVIOUS) {
          continue;
        }
        if (frameInfo.blendOperation == BlendOperation.NO_BLEND) {
          disposeToBackground(canvas, frameInfo);
        }
        mAnimatedDrawableBackend.renderFrame(index, canvas);
        mCallback.onIntermediateResult(index, bitmap);
        if (disposalMethod == DisposalMethod.DISPOSE_TO_BACKGROUND) {
          disposeToBackground(canvas, frameInfo);
        }
      }
  
      AnimatedDrawableFrameInfo frameInfo = mAnimatedDrawableBackend.getFrameInfo(frameNumber);
      if (frameInfo.blendOperation == BlendOperation.NO_BLEND) {
        disposeToBackground(canvas, frameInfo);
      }
      // Finally, we render the current frame. We don't dispose it.
      mAnimatedDrawableBackend.renderFrame(frameNumber, canvas);
    }