measure_3d_view_controller.dart 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:ui' as ui;
  4. import 'package:fis_common/event/event_type.dart';
  5. import 'package:fis_jsonrpc/services/index.dart';
  6. import 'package:fis_measure/interfaces/process/workspace/measure_3d_view_controller.dart';
  7. import 'package:fis_measure/utils/js_utils.dart'
  8. if (dart.library.io) 'package:fis_measure/utils/js_utils4native.dart'
  9. if (dart.library.html) 'package:fis_measure/utils/js_utils.dart';
  10. import 'package:flutter/material.dart';
  11. import 'package:vid/us/vid_us_image.dart';
  12. class Measure3DViewController implements IMeasure3DViewController {
  13. Measure3DViewController();
  14. /// [Carotid] ✅Measure3DView 控制器
  15. CarotidResultDTO _carotidResult = CarotidResultDTO();
  16. String _recordId = "";
  17. List<Ultra3DResourceInfo> _ultra3DResourceInfoList = [];
  18. bool _exist3DData = false;
  19. bool _enable2DMeasure = false;
  20. bool isShell = ifCurEnvIsShell;
  21. bool needAutoDetection = false;
  22. /// 模型切面标准宽度
  23. Size stdSize = const Size(599, 400);
  24. VidUsImage? _image4Measure;
  25. MeasureMode _curMeasureMode = MeasureMode.vidMode;
  26. ///3D模式下进入颈动脉2D模式
  27. void changeModeTo2DMeasure() {
  28. curMeasureMode = MeasureMode.carotid2DMode;
  29. // initParams();
  30. updatePlayerMode.emit(this, MeasureMode.carotid2DMode);
  31. }
  32. ///vid 2D模式下进入3D测量模式
  33. void changeModeTo3DMode() {
  34. curMeasureMode = MeasureMode.carotid3DMode;
  35. // initParams();
  36. updatePlayerMode.emit(this, MeasureMode.carotid3DMode);
  37. }
  38. ///颈动脉 2D模式下回到3D测量模式
  39. void backTo3DMode() {
  40. curMeasureMode = MeasureMode.carotid3DMode;
  41. updatePlayerMode.emit(this, MeasureMode.carotid3DMode);
  42. }
  43. /// 颈动脉2D、3D模式回到vid 2D测量模式
  44. void backToVidMode() {
  45. // initParams();
  46. resetTone();
  47. curMeasureMode = MeasureMode.vidMode;
  48. updatePlayerMode.emit(this, MeasureMode.vidMode);
  49. }
  50. ///[Carotid] ✅通知 shell 下载全部模型文件,_ultra3DResourceInfoList 中的第一个元素为当前操作的元素
  51. void notifyShellLoadAllModel() {
  52. if (_ultra3DResourceInfoList.isNotEmpty) {
  53. final Ultr3DParameter ultra3DParameter =
  54. Ultr3DParameter(_recordId, _ultra3DResourceInfoList);
  55. callShellMethod("setUltr3DData", [ultra3DParameter.toJson()]);
  56. }
  57. }
  58. /// [Carotid] ✅通知 shell 切换到当前所选模型,本质调用了同一个接口
  59. void notifyShellSetCurModel() {
  60. final Ultr3DParameter ultra3DParameter =
  61. Ultr3DParameter(_recordId, [Ultra3DResourceInfo(_carotidResult)]);
  62. callShellMethod("setUltr3DData", [ultra3DParameter.toJson()]);
  63. }
  64. /// [Carotid] ✅shell 通知 webview 切换到当前所选模型
  65. void handleMdlFileLoaded(String loadedMdlFile) {
  66. if (loadedMdlFile == carotidResult.mdlFile) {
  67. onShellLoadedMdlFile.emit(this, null);
  68. }
  69. }
  70. /// [Carotid] ✅shell 通知 flutter 修改测量中的颈动脉2D图像
  71. void handleUpdateCarotid2DImage(String base64Image) {
  72. if (curMeasureMode == MeasureMode.carotid2DMode) {
  73. onUpdateCarotid2DImage.emit(this, base64Image);
  74. }
  75. }
  76. var onUpdateCarotid2DImage = FEventHandler<String>();
  77. /// 用户主动触发更换颈动脉图像
  78. var onChangeCarotid2DImage = FEventHandler<String>();
  79. void handleChangeCarotid2DImage(String recordId) {
  80. initParams();
  81. onChangeCarotid2DImage.emit(this, recordId);
  82. }
  83. /// [Carotid] ✅模型切换时初始化一些参数
  84. void initParams() {
  85. enable2DMeasure = false;
  86. }
  87. @override
  88. CarotidResultDTO get carotidResult => _carotidResult;
  89. @override
  90. var updatePlayerMode = FEventHandler<MeasureMode>();
  91. @override
  92. var onShellLoadedMdlFile = FEventHandler<void>();
  93. var adjustPlaneImage = FEventHandler<ImageAdjustPara>();
  94. @override
  95. set carotidResult(CarotidResultDTO value) {
  96. if (value != _carotidResult) {
  97. _carotidResult = value;
  98. }
  99. }
  100. @override
  101. bool get exist3DData => _exist3DData;
  102. @override
  103. set exist3DData(bool value) {
  104. if (value != _exist3DData) {
  105. _exist3DData = value;
  106. }
  107. }
  108. @override
  109. bool get enable2DMeasure => _enable2DMeasure;
  110. @override
  111. set enable2DMeasure(bool value) {
  112. if (value != _enable2DMeasure) {
  113. _enable2DMeasure = value;
  114. }
  115. }
  116. @override
  117. VidUsImage? get image4Measure => _image4Measure;
  118. @override
  119. set image4Measure(VidUsImage? value) {
  120. if (value != _image4Measure) {
  121. _image4Measure = value;
  122. }
  123. }
  124. @override
  125. String get recordId => _recordId;
  126. @override
  127. set recordId(String value) {
  128. if (value != _recordId) {
  129. _recordId = value;
  130. }
  131. }
  132. @override
  133. List<Ultra3DResourceInfo> get ultra3DResourceInfoList =>
  134. _ultra3DResourceInfoList;
  135. @override
  136. set ultra3DResourceInfoList(List<Ultra3DResourceInfo> value) {
  137. if (value != _ultra3DResourceInfoList) {
  138. _ultra3DResourceInfoList = value;
  139. }
  140. }
  141. @override
  142. MeasureMode get curMeasureMode => _curMeasureMode;
  143. @override
  144. set curMeasureMode(MeasureMode value) {
  145. if (value != _curMeasureMode) {
  146. _curMeasureMode = value;
  147. }
  148. }
  149. /// 当前3D模型切面的亮度、对比度、锐度 :初始值、最大值、最小值、标准值
  150. /// 控件传入的值范围都是 -100 ~ 100 需要手动转换
  151. int _sharpness = 0; //0,200,-200,0
  152. int _brightness = 0; //0,255,-255,0
  153. int _contrast = 100; //100,400,0,100
  154. int get sharpness => _sharpness;
  155. set sharpness(int value) {
  156. _sharpness = value * 2;
  157. }
  158. int get brightness => _brightness;
  159. set brightness(int value) {
  160. _brightness = (value * 2.55).toInt();
  161. }
  162. int get contrast => _contrast;
  163. set contrast(int value) {
  164. if (value <= 0) {
  165. _contrast = value + 100;
  166. } else {
  167. _contrast = value * 3 + 100;
  168. }
  169. }
  170. var onResetTone = FEventHandler<void>();
  171. /// 重置图像增益
  172. void resetTone() {
  173. sharpness = 0;
  174. brightness = 0;
  175. contrast = 0;
  176. notifyShellSetTone();
  177. onResetTone.emit(this, null);
  178. }
  179. ImageAdjustPara curImageAdjustPara =
  180. ImageAdjustPara(brightness: 0, contrast: 100, sharpness: 0);
  181. /// [Carotid] ✅通知 shell 设置图像增益,并且直接调整 webview 中的图像增益, 如果在2D测量模式下,则刷新图像
  182. void notifyShellSetTone() {
  183. //如果参数没变,不刷新
  184. if (sharpness == curImageAdjustPara.sharpness &&
  185. brightness == curImageAdjustPara.brightness &&
  186. contrast == curImageAdjustPara.contrast) {
  187. return;
  188. }
  189. final ImageAdjustPara params = ImageAdjustPara(
  190. brightness: brightness, contrast: contrast, sharpness: sharpness);
  191. curImageAdjustPara = params;
  192. adjustPlaneImage.emit(this, params);
  193. if (curMeasureMode == MeasureMode.carotid2DMode) {
  194. callShellMethod("getCurrentPlaneWithGivenPara", [params.toJson()]);
  195. }
  196. }
  197. }
  198. /// Shell 内的增益调整参数模型
  199. class ImageAdjustPara {
  200. int brightness;
  201. int contrast;
  202. int sharpness;
  203. ImageAdjustPara(
  204. {required this.brightness,
  205. required this.contrast,
  206. required this.sharpness});
  207. String toJson() {
  208. return json.encode({
  209. "Brightness": brightness,
  210. "Contrast": contrast,
  211. "Sharpness": sharpness,
  212. });
  213. }
  214. }
  215. ///获取图片尺寸
  216. Future<Size> loadImageSize(String url) async {
  217. ui.Image image = await getImage(url);
  218. final width = image.width;
  219. final height = image.height;
  220. image.dispose();
  221. return Size(width.toDouble(), height.toDouble());
  222. }
  223. Future<ui.Image> getImage(String path) async {
  224. var completer = Completer<ImageInfo>();
  225. var img = NetworkImage(path);
  226. img
  227. .resolve(const ImageConfiguration())
  228. .addListener(ImageStreamListener((info, _) {
  229. completer.complete(info);
  230. }));
  231. ImageInfo imageInfo = await completer.future;
  232. return imageInfo.image;
  233. }