| 
									
										
										
										
											2022-09-10 19:50:48 -07:00
										 |  |  | import 'dart:typed_data'; | 
					
						
							|  |  |  | import 'dart:ui' as ui; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-09 23:00:34 +09:00
										 |  |  | import 'package:flutter/widgets.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  | import 'package:flutter_hbb/common.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-10 19:50:48 -07:00
										 |  |  | Future<ui.Image> decodeImageFromPixels( | 
					
						
							|  |  |  |   Uint8List pixels, | 
					
						
							|  |  |  |   int width, | 
					
						
							|  |  |  |   int height, | 
					
						
							|  |  |  |   ui.PixelFormat format, { | 
					
						
							|  |  |  |   int? rowBytes, | 
					
						
							|  |  |  |   int? targetWidth, | 
					
						
							|  |  |  |   int? targetHeight, | 
					
						
							| 
									
										
										
										
											2023-02-15 16:44:40 +08:00
										 |  |  |   VoidCallback? onPixelsCopied, | 
					
						
							| 
									
										
										
										
											2022-09-10 19:50:48 -07:00
										 |  |  |   bool allowUpscaling = true, | 
					
						
							|  |  |  | }) async { | 
					
						
							|  |  |  |   if (targetWidth != null) { | 
					
						
							|  |  |  |     assert(allowUpscaling || targetWidth <= width); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (targetHeight != null) { | 
					
						
							|  |  |  |     assert(allowUpscaling || targetHeight <= height); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   final ui.ImmutableBuffer buffer = | 
					
						
							|  |  |  |       await ui.ImmutableBuffer.fromUint8List(pixels); | 
					
						
							| 
									
										
										
										
											2023-02-15 16:44:40 +08:00
										 |  |  |   onPixelsCopied?.call(); | 
					
						
							| 
									
										
										
										
											2022-09-10 19:50:48 -07:00
										 |  |  |   final ui.ImageDescriptor descriptor = ui.ImageDescriptor.raw( | 
					
						
							|  |  |  |     buffer, | 
					
						
							|  |  |  |     width: width, | 
					
						
							|  |  |  |     height: height, | 
					
						
							|  |  |  |     rowBytes: rowBytes, | 
					
						
							|  |  |  |     pixelFormat: format, | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  |   if (!allowUpscaling) { | 
					
						
							| 
									
										
										
										
											2022-09-11 19:52:38 -07:00
										 |  |  |     if (targetWidth != null && targetWidth > descriptor.width) { | 
					
						
							| 
									
										
										
										
											2022-09-10 19:50:48 -07:00
										 |  |  |       targetWidth = descriptor.width; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-11 19:52:38 -07:00
										 |  |  |     if (targetHeight != null && targetHeight > descriptor.height) { | 
					
						
							| 
									
										
										
										
											2022-09-10 19:50:48 -07:00
										 |  |  |       targetHeight = descriptor.height; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   final ui.Codec codec = await descriptor.instantiateCodec( | 
					
						
							|  |  |  |     targetWidth: targetWidth, | 
					
						
							|  |  |  |     targetHeight: targetHeight, | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   final ui.FrameInfo frameInfo = await codec.getNextFrame(); | 
					
						
							|  |  |  |   codec.dispose(); | 
					
						
							|  |  |  |   buffer.dispose(); | 
					
						
							|  |  |  |   descriptor.dispose(); | 
					
						
							|  |  |  |   return frameInfo.image; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-02-09 23:00:34 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-03-28 11:38:11 +08:00
										 |  |  |     // 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; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-02-09 23:00:34 +09:00
										 |  |  |     canvas.drawImage( | 
					
						
							|  |  |  |         image!, Offset(x.toInt().toDouble(), y.toInt().toDouble()), paint); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   bool shouldRepaint(CustomPainter oldDelegate) { | 
					
						
							|  |  |  |     return oldDelegate != this; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |