123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- 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;
- }
- }
|