Export.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #include "Export.h"
  2. #include "VolumeDataPreProcessor.h"
  3. /// <summary>
  4. /// 获取错误详情
  5. /// </summary>
  6. /// <param name="errorCode"></param>
  7. /// <param name="errorMsg"></param>
  8. /// <param name="errorMaxLen"></param>
  9. /// <returns></returns>
  10. extern "C" __declspec(dllexport) void GetErrorCodeAndMsg(ErrorCode & errorCode, char* errorMsg, const int errorMaxLen)
  11. {
  12. ErrorMsg::GetErrorMsg(errorCode, errorMsg, errorMaxLen);
  13. }
  14. /// <summary>
  15. /// 图像数据解码
  16. /// </summary>
  17. /// <param name="srcImgData"></param>
  18. /// <param name="dstImgData"></param>
  19. /// <param name="dstDataSize"></param>
  20. /// <param name="imReadMode"></param>
  21. /// <returns></returns>
  22. extern "C" __declspec(dllexport) bool ImDataDecode(const uint8_t * srcImgData, const int srcDataSize,
  23. uint8_t * dstImgData, const int dstDataSize, ImreadModes imReadMode)
  24. {
  25. // 如果失败,已经在函数内部写了ErrorMsg了,不用再重复赋值
  26. return _encodeDecode.Decode(srcImgData, srcDataSize, dstImgData, dstDataSize, imReadMode);
  27. }
  28. /// <summary>
  29. /// 图像数据编码
  30. /// </summary>
  31. /// <param name="srcImgInfo"></param>
  32. /// <param name="extension"></param>
  33. /// <param name="imwriteParams"></param>
  34. /// <param name="paramCount"></param>
  35. /// <param name="dstImgData"></param>
  36. /// <param name="dstDataSize"></param>
  37. /// <returns></returns>
  38. extern "C" __declspec(dllexport) bool ImDataEncode(ImageInfo srcImgInfo, ImwriteExtension extension,
  39. ImwriteParam * imwriteParams, int paramCount, uint8_t * dstImgData, int& dstDataSize)
  40. {
  41. // 如果失败,已经在函数内部写了ErrorMsg了,不用再重复赋值
  42. return _encodeDecode.Encode(srcImgInfo, extension, imwriteParams, paramCount, dstImgData, dstDataSize);
  43. }
  44. /// <summary>
  45. /// 将直线扫查的数据转成均一立方体
  46. /// </summary>
  47. /// <param name="volumeInfo"></param>
  48. /// <param name="dstVolumeData"></param>
  49. /// <returns></returns>
  50. extern "C" __declspec(dllexport) bool StraightScanDataToUniformCube(VolumeDataPreProcessorInfo volumeInfo,
  51. uint8_t * dstVolumeData)
  52. {
  53. try
  54. {
  55. // 创建容器
  56. VolumeDataPreProcessor preprocessor = VolumeDataPreProcessor(2, volumeInfo);
  57. // 根据目标图像数量逐帧插值
  58. // 考虑到是直线扫查得到的数据,因此在求每一个插值帧的每个像素点灰度时,
  59. // 相当于xy完全落在网格点处,只有z可能会落在前后帧之间,因此只需要在z方向取前后帧的xy位置处的灰度,
  60. // 直接进行线性插值即可获得所需灰度
  61. int imgCount = volumeInfo.origImgCount;
  62. int dstImgCount = volumeInfo.desiredImgCount;
  63. if(dstImgCount <=1)
  64. {
  65. char strMsgBuff[32];
  66. std::snprintf(strMsgBuff, 32, "unexpected desiredImgCount value ( %i ) ", dstImgCount);
  67. ErrorMsg::SetErrorMsg(StraightScanDataUniformError, { strMsgBuff });
  68. return false;
  69. }
  70. float ratio = (imgCount -1) * 1.0f / (dstImgCount -1);
  71. int bytePerPixel = ImageHelper::GetBytesPerPixel(volumeInfo.colorType);
  72. int dstBytePerImg = volumeInfo.desiredImgWidth * volumeInfo.desiredImgHeight * bytePerPixel;
  73. uint8_t* pDstData;
  74. for (int ni = 0; ni < dstImgCount; ni++)
  75. {
  76. float position = ratio * ni;
  77. int posFront = floor(position);
  78. float posRatio = position - posFront;
  79. // 很靠近前一个点或后一个点,就直接只参考前一个点或后一个点的灰度即可
  80. // 因为就算后一个点的灰度是255,乘以比值0.001后,对当前位置处也只有0.255的贡献,可以忽略不计
  81. if (posRatio < 0.001)
  82. {
  83. posRatio = 0;
  84. }
  85. if (posRatio > 0.99)
  86. {
  87. posRatio = 1;
  88. }
  89. int posBack = posFront + 1;
  90. // 不要超过范围
  91. posFront = std::min(imgCount-1,std::max(0, posFront));
  92. posBack = std::min(imgCount - 1, std::max(0, posBack));
  93. cv::Mat dstImg;
  94. // 只取前一帧图,直接复制即可
  95. if (posRatio == 0)
  96. {
  97. dstImg = preprocessor.GetImage(posFront);
  98. }
  99. // 只取后一帧图,直接复制即可
  100. else if (posRatio == 1)
  101. {
  102. dstImg = preprocessor.GetImage(posBack);
  103. }
  104. // 需要取前后各一帧,逐像素进行插值
  105. else
  106. {
  107. auto frontImg = preprocessor.GetImage(posFront);
  108. auto backImg = preprocessor.GetImage(posBack);
  109. dstImg = UniformHelper::LinearInterpolation(frontImg, backImg, posRatio);
  110. }
  111. // 将dstImg中的数据复制到所需位置
  112. pDstData = dstVolumeData + ni * dstBytePerImg;
  113. std::memcpy(pDstData, dstImg.data, dstBytePerImg);
  114. }
  115. return true;
  116. }
  117. catch (const std::exception& ex)
  118. {
  119. ErrorMsg::SetErrorMsg(StraightScanDataUniformError,{ ex.what() });
  120. return false;
  121. }
  122. }
  123. /// <summary>
  124. /// 获取立方体的六个表面
  125. /// </summary>
  126. /// <param name="volumeDataInfo"></param>
  127. /// <param name="surfaceNum"></param>
  128. /// <param name="surfaceInfos"></param>
  129. /// <returns></returns>
  130. extern "C" __declspec(dllexport) bool GetSurfacePicsFromUniformCube(UniformVolumeDataInfo volumeDataInfo,
  131. int surfaceNum, SurfacePicInfo * surfaceInfos)
  132. {
  133. try
  134. {
  135. int x = volumeDataInfo.x;
  136. int y = volumeDataInfo.y;
  137. int z = volumeDataInfo.z;
  138. float spacing = volumeDataInfo.spacing;
  139. // 创建SliceHelper
  140. SliceHelper _sliceHelper;
  141. // 把体数据加载到SliceHelper里
  142. _sliceHelper.LoadVolumeData(volumeDataInfo);
  143. // 逐个表面获取
  144. for(int ni=0; ni< surfaceNum;ni++)
  145. {
  146. auto surfaceInfo = surfaceInfos[ni];
  147. auto surfaceType = surfaceInfo.surfaceType;
  148. auto imgInfo = surfaceInfo.imgInfo;
  149. AxisName axisName = X;
  150. int intersectionVal = 0;
  151. switch(surfaceType)
  152. {
  153. case Right:
  154. axisName = X;
  155. intersectionVal = x-1;
  156. break;
  157. case Left:
  158. axisName = X;
  159. intersectionVal = 0;
  160. break;
  161. case Behind:
  162. axisName = Z;
  163. intersectionVal = z-1;
  164. break;
  165. case Front:
  166. axisName = Z;
  167. intersectionVal = 0;
  168. break;
  169. case Top:
  170. axisName = Y;
  171. intersectionVal = 0;
  172. break;
  173. case Bottom:
  174. axisName = Y;
  175. intersectionVal = y-1;
  176. break;
  177. }
  178. _sliceHelper.GetVerticalToAxisSlicePlaneImage(axisName, intersectionVal,imgInfo);
  179. // 赋值回去
  180. surfaceInfos[ni].imgInfo.width = imgInfo.width;
  181. surfaceInfos[ni].imgInfo.height = imgInfo.height;
  182. surfaceInfos[ni].imgInfo.colorType = imgInfo.colorType;
  183. int imgByteCounts = imgInfo.width * imgInfo.height * ImageHelper::GetBytesPerPixel(imgInfo.colorType);
  184. }
  185. return true;
  186. }
  187. catch(const std::exception & ex)
  188. {
  189. ErrorMsg::SetErrorMsg(GetSurfaceError, { ex.what() });
  190. return false;
  191. }
  192. }
  193. /// <summary>
  194. /// 基于ITK的x方向融合
  195. /// </summary>
  196. /// <param name="volumeDataInfos"></param>
  197. /// <param name="volumeDataCount"></param>
  198. /// <param name="fusedDataInfo"></param>
  199. extern "C" __declspec(dllexport) bool ITKBasedFusionAlongX(UniformVolumeDataInfo * volumeDataInfos, int volumeDataCount,
  200. UniformVolumeDataInfo & fusedDataInfo)
  201. {
  202. if (volumeDataCount < 2)
  203. {
  204. char strMsgBuff[32];
  205. std::snprintf(strMsgBuff, 32, "unexpected volumeDataCount ( %i ).", volumeDataCount);
  206. ErrorMsg::SetErrorMsg(FusionError, { strMsgBuff });
  207. return false;
  208. }
  209. // 直接按照给入的顺序,第一个作为基础体数据,其他顺序与其融合
  210. FusionHelper fusionHelper = FusionHelper();
  211. const int baseVolumeIndex = 0;
  212. if (!fusionHelper.LoadBaseVolumeData(volumeDataInfos[baseVolumeIndex]))
  213. {
  214. // 已经在函数内部写了ErrorMsg了
  215. return false;
  216. }
  217. for (int ni = 1; ni < volumeDataCount; ni++)
  218. {
  219. if(!fusionHelper.FuseWithAnotherVolumeData(volumeDataInfos[ni]))
  220. {
  221. // 已经在函数内部写了ErrorMsg了,不用再重复赋值
  222. return false;
  223. }
  224. }
  225. // 取出融合后的结果
  226. if(!fusionHelper.GetFusedVolumeData(fusedDataInfo))
  227. {
  228. // 已经在函数内部写了ErrorMsg了,不用再重复赋值
  229. return false;
  230. }
  231. return true;
  232. }
  233. /// <summary>
  234. /// 图像数据编码并保存至本地
  235. /// </summary>
  236. /// <param name="srcImgInfo"></param>
  237. /// <param name="extension"></param>
  238. /// <param name="imwriteParams"></param>
  239. /// <param name="paramCount"></param>
  240. /// <param name="savePath"></param>
  241. /// <returns></returns>
  242. extern "C" __declspec(dllexport) bool ImDataSave(ImageInfo srcImgInfo, ImwriteExtension extension,
  243. ImwriteParam * imwriteParams, int paramCount, const char* savePath)
  244. {
  245. // 如果失败,已经在函数内部写了ErrorMsg了,不用再重复赋值
  246. return _encodeDecode.SaveImage(srcImgInfo, extension, imwriteParams, paramCount, savePath);
  247. }