anchor.diff:    }
   }
   
  -/// A [ui.Codec] backed by an `SkImage` from Skia.
  -class SkImageCodec implements ui.Codec {
  -  final SkImage skImage;
  +/// A [Codec] that wraps an `SkAnimatedImage`.
  +class SkAnimatedImageCodec implements ui.Codec {
  +  SkAnimatedImage animatedImage;
   
  -  SkImageCodec(this.skImage);
  +  SkAnimatedImageCodec(this.animatedImage);
   
     @override
     void dispose() {
  -    // TODO: implement dispose
  +    animatedImage.dispose();
  +    animatedImage = null;
     }
   
     @override
  -  int get frameCount => 1;
  +  int get frameCount => animatedImage.frameCount;
  +
  +  @override
  +  int get repetitionCount => animatedImage.repetitionCount;
   
     @override
     Future<ui.FrameInfo> getNextFrame() {
  -    return Future<ui.FrameInfo>.value(SingleFrameInfo(skImage));
  +    final Duration duration = animatedImage.decodeNextFrame();
  +    final SkImage image = animatedImage.currentFrameAsImage;
  +    return Future<ui.FrameInfo>.value(AnimatedImageFrameInfo(duration, image));
     }
  +}
  +
  +/// Data for a single frame of an animated image.
  +class AnimatedImageFrameInfo implements ui.FrameInfo {
  +  final Duration _duration;
  +  final SkImage _image;
  +
  +  AnimatedImageFrameInfo(this._duration, this._image);
   
     @override
  -  int get repetitionCount => 0;
  +  Duration get duration => _duration;
  +
  +  @override
  +  ui.Image get image => _image;
   }
  
positive.code: 
    @override
    void dispose() {
      skImage = null;
    }
  
  
negative.code: /// Instantiates a [ui.Codec] backed by an `SkImage` from Skia.
  void skiaInstantiateImageCodec(Uint8List list, Callback<ui.Codec> callback,
      [int width, int height, int format, int rowBytes]) {
    final js.JsObject skAnimatedImage =
        canvasKit.callMethod('MakeAnimatedImageFromEncoded', <Uint8List>[list]);
    final SkAnimatedImage animatedImage = SkAnimatedImage(skAnimatedImage);
    final SkAnimatedImageCodec codec = SkAnimatedImageCodec(animatedImage);
    callback(codec);
  }
  
  /// A wrapper for `SkAnimatedImage`.
  class SkAnimatedImage implements ui.Image {
    final js.JsObject _skAnimatedImage;
  
    SkAnimatedImage(this._skAnimatedImage);
  
    @override
    void dispose() {
      _skAnimatedImage.callMethod('delete');
    }
  
    int get frameCount => _skAnimatedImage.callMethod('getFrameCount');
  
    /// Decodes the next frame and returns the frame duration.
    Duration decodeNextFrame() {
      final int durationMillis = _skAnimatedImage.callMethod('decodeNextFrame');
      return Duration(milliseconds: durationMillis);
    }
  
    int get repetitionCount => _skAnimatedImage.callMethod('getRepetitionCount');
  
    SkImage get currentFrameAsImage {
      final js.JsObject _currentFrame =
          _skAnimatedImage.callMethod('getCurrentFrame');
      return SkImage(_currentFrame);
    }
  
    @override
    int get width => _skAnimatedImage.callMethod('width');
  
    @override
    int get height => _skAnimatedImage.callMethod('height');
  
    @override
    Future<ByteData> toByteData(
        {ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba}) {
      throw 'unimplemented';
    }
  }
  
  /// A [ui.Image] backed by an `SkImage` from Skia.
  