carotid_player.dart 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import 'dart:async';
  2. import 'dart:typed_data';
  3. import 'package:fis_measure/interfaces/process/items/terms.dart';
  4. import 'package:fis_measure/interfaces/process/items/types.dart';
  5. import 'package:fis_measure/interfaces/process/workspace/application.dart';
  6. import 'package:fis_measure/interfaces/process/workspace/measure_3d_view_controller.dart';
  7. import 'package:fis_measure/process/workspace/measure_3d_view_controller.dart';
  8. import 'package:fis_measure/view/player/controller.dart';
  9. import 'package:fis_measure/view/vid_painter/carotid_vid_painter.dart';
  10. import 'package:flutter/material.dart' hide Image, decodeImageFromList;
  11. import 'package:get/get.dart';
  12. import 'package:vid/us/vid_us_image.dart';
  13. import 'package:vid/us/vid_us_unit.dart';
  14. import 'dart:ui';
  15. import '../../interfaces/process/items/item_metas.dart';
  16. class CarotidPlayer extends StatefulWidget {
  17. const CarotidPlayer(
  18. this.measure3DViewController, {
  19. Key? key,
  20. }) : super(key: key);
  21. final Measure3DViewController measure3DViewController;
  22. @override
  23. State<StatefulWidget> createState() => _CarotidPlayerState();
  24. }
  25. class _CarotidPlayerState extends State<CarotidPlayer> {
  26. Image? image;
  27. int frameIndex = 0;
  28. final application = Get.find<IApplication>();
  29. List<double> curColorFilterMatrix = <double>[
  30. 1, 0, 0, 0, 0, // red
  31. 0, 1, 0, 0, 0, // green
  32. 0, 0, 1, 0, 0, // blue
  33. 0, 0, 0, 1, 0, // alpha
  34. ];
  35. @override
  36. void initState() {
  37. final stdSize = widget.measure3DViewController.stdSize;
  38. application.loadFrame(VidUsImage(1, stdSize.width.toInt(),
  39. stdSize.height.toInt(), Uint8List.fromList([0])));
  40. application.carotid2DSize = Size(
  41. widget.measure3DViewController.image4Measure!.width.toDouble(),
  42. widget.measure3DViewController.image4Measure!.height.toDouble());
  43. if (application.carotid2DSize.width > stdSize.width ||
  44. application.carotid2DSize.height > stdSize.height) {
  45. application.isAdaptiveCarotid2D = true;
  46. } else {
  47. application.isAdaptiveCarotid2D = false;
  48. }
  49. widget.measure3DViewController.onUpdateCarotid2DImage
  50. .addListener(_loadCarotidImageBytes);
  51. widget.measure3DViewController.updatePlayerMode.addListener(_onModeChanged);
  52. loadFrame(widget.measure3DViewController.image4Measure!);
  53. super.initState();
  54. }
  55. @override
  56. void dispose() {
  57. application.isAdaptiveCarotid2D = false;
  58. widget.measure3DViewController.onUpdateCarotid2DImage
  59. .removeListener(_loadCarotidImageBytes);
  60. widget.measure3DViewController.updatePlayerMode
  61. .removeListener(_onModeChanged);
  62. image?.dispose();
  63. super.dispose();
  64. }
  65. /// 模式改变触发更新
  66. void _onModeChanged(Object s, MeasureMode mode) {
  67. switch (mode) {
  68. case MeasureMode.vidMode:
  69. break;
  70. case MeasureMode.carotid2DMode:
  71. final itemMeta = ItemMeta(
  72. MeasureTerms.IntimaDetection,
  73. description: MeasureTerms.IntimaDetection,
  74. measureType: MeasureTerms.IntimaDetection,
  75. outputs: [
  76. ItemOutputMeta(MeasureTerms.IntimaDetection, "", VidUsUnit.cm2),
  77. ],
  78. );
  79. application.clearRecords();
  80. application.switchItem(itemMeta);
  81. loadFrame(widget.measure3DViewController.image4Measure!);
  82. break;
  83. case MeasureMode.carotid3DMode:
  84. break;
  85. }
  86. }
  87. @override
  88. void didUpdateWidget(covariant CarotidPlayer oldWidget) {
  89. if (oldWidget.measure3DViewController != widget.measure3DViewController) {
  90. throw UnsupportedError("[VidTestPlayer] unsupport replace controller.");
  91. }
  92. super.didUpdateWidget(oldWidget);
  93. }
  94. void loadFrame(VidUsImage e) async {
  95. frameIndex = e.index;
  96. final oldImage = image;
  97. image = await _loadImage(e.imageData);
  98. oldImage?.dispose();
  99. setState(() {});
  100. }
  101. void _loadCarotidImageBytes(Object sender, String base64Url) async {
  102. print("更新颈动脉2D");
  103. final oldImage = image;
  104. image = await getImage(base64Url);
  105. oldImage?.dispose();
  106. setState(() {});
  107. }
  108. ///从base64Url获取图片
  109. Future<Image> getImage(String path) async {
  110. var completer = Completer<ImageInfo>();
  111. var img = NetworkImage(path);
  112. img
  113. .resolve(const ImageConfiguration())
  114. .addListener(ImageStreamListener((info, _) {
  115. completer.complete(info);
  116. }));
  117. ImageInfo imageInfo = await completer.future;
  118. return imageInfo.image;
  119. }
  120. Future<Image> _loadImage(Uint8List bytes) async {
  121. final Completer<Image> completer = Completer<Image>();
  122. decodeVidFromList(bytes, (Image image) => completer.complete(image));
  123. return completer.future;
  124. }
  125. void decodeVidFromList(Uint8List bytes, ImageDecoderCallback callback) async {
  126. ImmutableBuffer.fromUint8List(bytes).then((ImmutableBuffer buffer) async {
  127. final ImageDescriptor descriptor = await ImageDescriptor.encoded(buffer);
  128. descriptor.instantiateCodec().then((Codec codec) {
  129. final Future<FrameInfo> frameInfo = codec.getNextFrame();
  130. codec.dispose();
  131. return frameInfo;
  132. }).then((FrameInfo frameInfo) {
  133. buffer.dispose();
  134. descriptor.dispose();
  135. return callback(frameInfo.image);
  136. });
  137. });
  138. }
  139. @override
  140. Widget build(BuildContext context) {
  141. return buildBox(context, buildFrameView(context));
  142. }
  143. Widget buildBox(BuildContext context, Widget child) {
  144. return Container(
  145. alignment: Alignment.center,
  146. child: child,
  147. );
  148. }
  149. Widget buildFrameView(BuildContext context) {
  150. if (image != null) {
  151. final size = MediaQuery.of(context).size;
  152. return RepaintBoundary(
  153. child: CustomPaint(
  154. painter: CarotidVidPainter(
  155. image: image!, stdSize: widget.measure3DViewController.stdSize),
  156. isComplex: false, //是否为复杂图像(true会缓存)
  157. size: size,
  158. ),
  159. );
  160. } else {
  161. return Container();
  162. }
  163. }
  164. }