content: import 'dart:typed_data';
  import 'dart:ui' as ui;
  
  import 'package:flutter/widgets.dart';
  
  import 'package:flutter_hbb/common.dart';
  
  Future<ui.Image?> decodeImageFromPixels(
    Uint8List pixels,
    int width,
    int height,
    ui.PixelFormat format, {
    int? rowBytes,
    int? targetWidth,
    int? targetHeight,
    bool allowUpscaling = true,
  }) async {
    if (targetWidth != null) {
      assert(allowUpscaling || targetWidth <= width);
      if (!(allowUpscaling || targetWidth <= width)) {
        print("not allow upscaling but targetWidth > width");
        return null;
      }
    }
    if (targetHeight != null) {
      assert(allowUpscaling || targetHeight <= height);
      if (!(allowUpscaling || targetHeight <= height)) {
        print("not allow upscaling but targetHeight > height");
        return null;
      }
    }
  
    final ui.ImmutableBuffer buffer;
    try {
      buffer = await ui.ImmutableBuffer.fromUint8List(pixels);
    } catch (e) {
      return null;
    }
  
    final ui.ImageDescriptor descriptor;
    try {
      descriptor = ui.ImageDescriptor.raw(
        buffer,
        width: width,
        height: height,
        rowBytes: rowBytes,
        pixelFormat: format,
      );
      if (!allowUpscaling) {
        if (targetWidth != null && targetWidth > descriptor.width) {
          targetWidth = descriptor.width;
        }
        if (targetHeight != null && targetHeight > descriptor.height) {
          targetHeight = descriptor.height;
        }
      }
    } catch (e) {
      print("ImageDescriptor.raw failed: $e");
      buffer.dispose();
      return null;
    }
  
    final ui.Codec codec;
    try {
      codec = await descriptor.instantiateCodec(
        targetWidth: targetWidth,
        targetHeight: targetHeight,
      );
    } catch (e) {
      print("instantiateCodec failed: $e");
      buffer.dispose();
      descriptor.dispose();
      return null;
    }
  
    final ui.FrameInfo frameInfo;
    try {
      frameInfo = await codec.getNextFrame();
    } catch (e) {
      print("getNextFrame failed: $e");
      codec.dispose();
      buffer.dispose();
      descriptor.dispose();
      return null;
    }
  
    codec.dispose();
    buffer.dispose();
    descriptor.dispose();
    return frameInfo.image;
  }
  
  class ImagePainter extends CustomPainter {
    ImagePainter({
      required this.image,
      required this.x,
      required this.y,
      required this.scale,
    });
  
    ui.Image? image;
    double x;
    double y;
    double scale;
  
    @override
    void paint(Canvas canvas, Size size) {
      if (image == null) return;
      if (x.isNaN || y.isNaN) return;
      canvas.scale(scale, scale);
      // https://github.com/flutter/flutter/issues/76187#issuecomment-784628161
      // https://api.flutter-io.cn/flutter/dart-ui/FilterQuality.html
      var paint = Paint();
      if ((scale - 1.0).abs() > 0.001) {
        paint.filterQuality = FilterQuality.medium;
        if (scale > 10.00000) {
          paint.filterQuality = FilterQuality.high;
        }
      }
      // It's strange that if (scale < 0.5 && paint.filterQuality == FilterQuality.medium)
      // The canvas.drawImage will not work on web
      if (isWeb) {
        paint.filterQuality = FilterQuality.high;
      }
      canvas.drawImage(
          image!, Offset(x.toInt().toDouble(), y.toInt().toDouble()), paint);
    }
  
    @override
    bool shouldRepaint(CustomPainter oldDelegate) {
      return oldDelegate != this;
    }
  }
  