import 'dart:async'; import 'dart:convert'; import 'dart:ui' as ui; import 'package:fis_common/event/event_type.dart'; import 'package:fis_jsonrpc/services/index.dart'; import 'package:fis_measure/interfaces/process/workspace/measure_3d_view_controller.dart'; import 'package:fis_measure/utils/js_utils.dart' if (dart.library.io) 'package:fis_measure/utils/js_utils4native.dart' if (dart.library.html) 'package:fis_measure/utils/js_utils.dart'; import 'package:flutter/material.dart'; import 'package:vid/us/vid_us_image.dart'; class Measure3DViewController implements IMeasure3DViewController { Measure3DViewController(); /// [Carotid] ✅Measure3DView 控制器 CarotidResultDTO _carotidResult = CarotidResultDTO(); String _recordId = ""; List _ultra3DResourceInfoList = []; bool _exist3DData = false; bool _enable2DMeasure = false; bool isShell = ifCurEnvIsShell; bool needAutoDetection = false; /// 模型切面标准宽度 Size stdSize = const Size(599, 400); VidUsImage? _image4Measure; MeasureMode _curMeasureMode = MeasureMode.vidMode; ///3D模式下进入颈动脉2D模式 void changeModeTo2DMeasure() { curMeasureMode = MeasureMode.carotid2DMode; // initParams(); updatePlayerMode.emit(this, MeasureMode.carotid2DMode); } ///vid 2D模式下进入3D测量模式 void changeModeTo3DMode() { curMeasureMode = MeasureMode.carotid3DMode; // initParams(); updatePlayerMode.emit(this, MeasureMode.carotid3DMode); } ///颈动脉 2D模式下回到3D测量模式 void backTo3DMode() { curMeasureMode = MeasureMode.carotid3DMode; updatePlayerMode.emit(this, MeasureMode.carotid3DMode); } /// 颈动脉2D、3D模式回到vid 2D测量模式 void backToVidMode() { // initParams(); resetTone(); curMeasureMode = MeasureMode.vidMode; updatePlayerMode.emit(this, MeasureMode.vidMode); } ///[Carotid] ✅通知 shell 下载全部模型文件,_ultra3DResourceInfoList 中的第一个元素为当前操作的元素 void notifyShellLoadAllModel() { if (_ultra3DResourceInfoList.isNotEmpty) { final Ultr3DParameter ultra3DParameter = Ultr3DParameter(_recordId, _ultra3DResourceInfoList); callShellMethod("setUltr3DData", [ultra3DParameter.toJson()]); } } /// [Carotid] ✅通知 shell 切换到当前所选模型,本质调用了同一个接口 void notifyShellSetCurModel() { final Ultr3DParameter ultra3DParameter = Ultr3DParameter(_recordId, [Ultra3DResourceInfo(_carotidResult)]); callShellMethod("setUltr3DData", [ultra3DParameter.toJson()]); } /// [Carotid] ✅shell 通知 webview 切换到当前所选模型 void handleMdlFileLoaded(String loadedMdlFile) { if (loadedMdlFile == carotidResult.mdlFile) { onShellLoadedMdlFile.emit(this, null); } } /// [Carotid] ✅shell 通知 flutter 修改测量中的颈动脉2D图像 void handleUpdateCarotid2DImage(String base64Image) { if (curMeasureMode == MeasureMode.carotid2DMode) { onUpdateCarotid2DImage.emit(this, base64Image); } } var onUpdateCarotid2DImage = FEventHandler(); /// 用户主动触发更换颈动脉图像 var onChangeCarotid2DImage = FEventHandler(); void handleChangeCarotid2DImage(String recordId) { initParams(); onChangeCarotid2DImage.emit(this, recordId); } /// [Carotid] ✅模型切换时初始化一些参数 void initParams() { enable2DMeasure = false; } @override CarotidResultDTO get carotidResult => _carotidResult; @override var updatePlayerMode = FEventHandler(); @override var onShellLoadedMdlFile = FEventHandler(); var adjustPlaneImage = FEventHandler(); @override set carotidResult(CarotidResultDTO value) { if (value != _carotidResult) { _carotidResult = value; } } @override bool get exist3DData => _exist3DData; @override set exist3DData(bool value) { if (value != _exist3DData) { _exist3DData = value; } } @override bool get enable2DMeasure => _enable2DMeasure; @override set enable2DMeasure(bool value) { if (value != _enable2DMeasure) { _enable2DMeasure = value; } } @override VidUsImage? get image4Measure => _image4Measure; @override set image4Measure(VidUsImage? value) { if (value != _image4Measure) { _image4Measure = value; } } @override String get recordId => _recordId; @override set recordId(String value) { if (value != _recordId) { _recordId = value; } } @override List get ultra3DResourceInfoList => _ultra3DResourceInfoList; @override set ultra3DResourceInfoList(List value) { if (value != _ultra3DResourceInfoList) { _ultra3DResourceInfoList = value; } } @override MeasureMode get curMeasureMode => _curMeasureMode; @override set curMeasureMode(MeasureMode value) { if (value != _curMeasureMode) { _curMeasureMode = value; } } /// 当前3D模型切面的亮度、对比度、锐度 :初始值、最大值、最小值、标准值 /// 控件传入的值范围都是 -100 ~ 100 需要手动转换 int _sharpness = 0; //0,200,-200,0 int _brightness = 0; //0,255,-255,0 int _contrast = 100; //100,400,0,100 int get sharpness => _sharpness; set sharpness(int value) { _sharpness = value * 2; } int get brightness => _brightness; set brightness(int value) { _brightness = (value * 2.55).toInt(); } int get contrast => _contrast; set contrast(int value) { if (value <= 0) { _contrast = value + 100; } else { _contrast = value * 3 + 100; } } var onResetTone = FEventHandler(); /// 重置图像增益 void resetTone() { sharpness = 0; brightness = 0; contrast = 0; notifyShellSetTone(); onResetTone.emit(this, null); } ImageAdjustPara curImageAdjustPara = ImageAdjustPara(brightness: 0, contrast: 100, sharpness: 0); /// [Carotid] ✅通知 shell 设置图像增益,并且直接调整 webview 中的图像增益, 如果在2D测量模式下,则刷新图像 void notifyShellSetTone() { //如果参数没变,不刷新 if (sharpness == curImageAdjustPara.sharpness && brightness == curImageAdjustPara.brightness && contrast == curImageAdjustPara.contrast) { return; } final ImageAdjustPara params = ImageAdjustPara( brightness: brightness, contrast: contrast, sharpness: sharpness); curImageAdjustPara = params; adjustPlaneImage.emit(this, params); if (curMeasureMode == MeasureMode.carotid2DMode) { callShellMethod("getCurrentPlaneWithGivenPara", [params.toJson()]); } } } /// Shell 内的增益调整参数模型 class ImageAdjustPara { int brightness; int contrast; int sharpness; ImageAdjustPara( {required this.brightness, required this.contrast, required this.sharpness}); String toJson() { return json.encode({ "Brightness": brightness, "Contrast": contrast, "Sharpness": sharpness, }); } } ///获取图片尺寸 Future loadImageSize(String url) async { ui.Image image = await getImage(url); final width = image.width; final height = image.height; image.dispose(); return Size(width.toDouble(), height.toDouble()); } Future getImage(String path) async { var completer = Completer(); var img = NetworkImage(path); img .resolve(const ImageConfiguration()) .addListener(ImageStreamListener((info, _) { completer.complete(info); })); ImageInfo imageInfo = await completer.future; return imageInfo.image; }