123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- #include "Export.h"
- #include "VolumeDataPreProcessor.h"
- /// <summary>
- /// 获取错误详情
- /// </summary>
- /// <param name="errorCode"></param>
- /// <param name="errorMsg"></param>
- /// <param name="errorMaxLen"></param>
- /// <returns></returns>
- extern "C" __declspec(dllexport) void GetErrorCodeAndMsg(ErrorCode & errorCode, char* errorMsg, const int errorMaxLen)
- {
- ErrorMsg::GetErrorMsg(errorCode, errorMsg, errorMaxLen);
- }
- /// <summary>
- /// 图像数据解码
- /// </summary>
- /// <param name="srcImgData"></param>
- /// <param name="dstImgData"></param>
- /// <param name="dstDataSize"></param>
- /// <param name="imReadMode"></param>
- /// <returns></returns>
- extern "C" __declspec(dllexport) bool ImDataDecode(const uint8_t * srcImgData, const int srcDataSize,
- uint8_t * dstImgData, const int dstDataSize, ImreadModes imReadMode)
- {
- // 如果失败,已经在函数内部写了ErrorMsg了,不用再重复赋值
- return _encodeDecode.Decode(srcImgData, srcDataSize, dstImgData, dstDataSize, imReadMode);
- }
- /// <summary>
- /// 图像数据编码
- /// </summary>
- /// <param name="srcImgInfo"></param>
- /// <param name="extension"></param>
- /// <param name="imwriteParams"></param>
- /// <param name="paramCount"></param>
- /// <param name="dstImgData"></param>
- /// <param name="dstDataSize"></param>
- /// <returns></returns>
- extern "C" __declspec(dllexport) bool ImDataEncode(ImageInfo srcImgInfo, ImwriteExtension extension,
- ImwriteParam * imwriteParams, int paramCount, uint8_t * dstImgData, int& dstDataSize)
- {
- // 如果失败,已经在函数内部写了ErrorMsg了,不用再重复赋值
- return _encodeDecode.Encode(srcImgInfo, extension, imwriteParams, paramCount, dstImgData, dstDataSize);
- }
- /// <summary>
- /// 将直线扫查的数据转成均一立方体
- /// </summary>
- /// <param name="volumeInfo"></param>
- /// <param name="dstVolumeData"></param>
- /// <returns></returns>
- extern "C" __declspec(dllexport) bool StraightScanDataToUniformCube(VolumeDataPreProcessorInfo volumeInfo,
- uint8_t * dstVolumeData)
- {
- try
- {
- // 创建容器
- VolumeDataPreProcessor preprocessor = VolumeDataPreProcessor(2, volumeInfo);
- // 根据目标图像数量逐帧插值
- // 考虑到是直线扫查得到的数据,因此在求每一个插值帧的每个像素点灰度时,
- // 相当于xy完全落在网格点处,只有z可能会落在前后帧之间,因此只需要在z方向取前后帧的xy位置处的灰度,
- // 直接进行线性插值即可获得所需灰度
- int imgCount = volumeInfo.origImgCount;
- int dstImgCount = volumeInfo.desiredImgCount;
- if(dstImgCount <=1)
- {
- char strMsgBuff[32];
- std::snprintf(strMsgBuff, 32, "unexpected desiredImgCount value ( %i ) ", dstImgCount);
- ErrorMsg::SetErrorMsg(StraightScanDataUniformError, { strMsgBuff });
- return false;
- }
- float ratio = (imgCount -1) * 1.0f / (dstImgCount -1);
- int bytePerPixel = ImageHelper::GetBytesPerPixel(volumeInfo.colorType);
- int dstBytePerImg = volumeInfo.desiredImgWidth * volumeInfo.desiredImgHeight * bytePerPixel;
- uint8_t* pDstData;
- for (int ni = 0; ni < dstImgCount; ni++)
- {
- float position = ratio * ni;
- int posFront = floor(position);
- float posRatio = position - posFront;
- // 很靠近前一个点或后一个点,就直接只参考前一个点或后一个点的灰度即可
- // 因为就算后一个点的灰度是255,乘以比值0.001后,对当前位置处也只有0.255的贡献,可以忽略不计
- if (posRatio < 0.001)
- {
- posRatio = 0;
- }
- if (posRatio > 0.99)
- {
- posRatio = 1;
- }
- int posBack = posFront + 1;
- // 不要超过范围
- posFront = std::min(imgCount-1,std::max(0, posFront));
- posBack = std::min(imgCount - 1, std::max(0, posBack));
- cv::Mat dstImg;
- // 只取前一帧图,直接复制即可
- if (posRatio == 0)
- {
- dstImg = preprocessor.GetImage(posFront);
- }
- // 只取后一帧图,直接复制即可
- else if (posRatio == 1)
- {
- dstImg = preprocessor.GetImage(posBack);
- }
- // 需要取前后各一帧,逐像素进行插值
- else
- {
- auto frontImg = preprocessor.GetImage(posFront);
- auto backImg = preprocessor.GetImage(posBack);
- dstImg = UniformHelper::LinearInterpolation(frontImg, backImg, posRatio);
- }
- // 将dstImg中的数据复制到所需位置
- pDstData = dstVolumeData + ni * dstBytePerImg;
- std::memcpy(pDstData, dstImg.data, dstBytePerImg);
- }
- return true;
- }
- catch (const std::exception& ex)
- {
- ErrorMsg::SetErrorMsg(StraightScanDataUniformError,{ ex.what() });
- return false;
- }
- }
- /// <summary>
- /// 获取立方体的六个表面
- /// </summary>
- /// <param name="volumeDataInfo"></param>
- /// <param name="surfaceNum"></param>
- /// <param name="surfaceInfos"></param>
- /// <returns></returns>
- extern "C" __declspec(dllexport) bool GetSurfacePicsFromUniformCube(UniformVolumeDataInfo volumeDataInfo,
- int surfaceNum, SurfacePicInfo * surfaceInfos)
- {
- try
- {
- int x = volumeDataInfo.x;
- int y = volumeDataInfo.y;
- int z = volumeDataInfo.z;
- float spacing = volumeDataInfo.spacing;
- // 创建SliceHelper
- SliceHelper _sliceHelper;
- // 把体数据加载到SliceHelper里
- _sliceHelper.LoadVolumeData(volumeDataInfo);
- // 逐个表面获取
- for(int ni=0; ni< surfaceNum;ni++)
- {
- auto surfaceInfo = surfaceInfos[ni];
- auto surfaceType = surfaceInfo.surfaceType;
- auto imgInfo = surfaceInfo.imgInfo;
- AxisName axisName = X;
- int intersectionVal = 0;
- switch(surfaceType)
- {
- case Right:
- axisName = X;
- intersectionVal = x-1;
- break;
- case Left:
- axisName = X;
- intersectionVal = 0;
- break;
- case Behind:
- axisName = Z;
- intersectionVal = z-1;
- break;
- case Front:
- axisName = Z;
- intersectionVal = 0;
- break;
- case Top:
- axisName = Y;
- intersectionVal = 0;
- break;
- case Bottom:
- axisName = Y;
- intersectionVal = y-1;
- break;
- }
- _sliceHelper.GetVerticalToAxisSlicePlaneImage(axisName, intersectionVal,imgInfo);
- // 赋值回去
- surfaceInfos[ni].imgInfo.width = imgInfo.width;
- surfaceInfos[ni].imgInfo.height = imgInfo.height;
- surfaceInfos[ni].imgInfo.colorType = imgInfo.colorType;
- int imgByteCounts = imgInfo.width * imgInfo.height * ImageHelper::GetBytesPerPixel(imgInfo.colorType);
- }
- return true;
- }
- catch(const std::exception & ex)
- {
- ErrorMsg::SetErrorMsg(GetSurfaceError, { ex.what() });
- return false;
- }
- }
- /// <summary>
- /// 基于ITK的x方向融合
- /// </summary>
- /// <param name="volumeDataInfos"></param>
- /// <param name="volumeDataCount"></param>
- /// <param name="fusedDataInfo"></param>
- extern "C" __declspec(dllexport) bool ITKBasedFusionAlongX(UniformVolumeDataInfo * volumeDataInfos, int volumeDataCount,
- UniformVolumeDataInfo & fusedDataInfo)
- {
- if (volumeDataCount < 2)
- {
- char strMsgBuff[32];
- std::snprintf(strMsgBuff, 32, "unexpected volumeDataCount ( %i ).", volumeDataCount);
- ErrorMsg::SetErrorMsg(FusionError, { strMsgBuff });
- return false;
- }
- // 直接按照给入的顺序,第一个作为基础体数据,其他顺序与其融合
- FusionHelper fusionHelper = FusionHelper();
- const int baseVolumeIndex = 0;
- if (!fusionHelper.LoadBaseVolumeData(volumeDataInfos[baseVolumeIndex]))
- {
- // 已经在函数内部写了ErrorMsg了
- return false;
- }
- for (int ni = 1; ni < volumeDataCount; ni++)
- {
- if(!fusionHelper.FuseWithAnotherVolumeData(volumeDataInfos[ni]))
- {
- // 已经在函数内部写了ErrorMsg了,不用再重复赋值
- return false;
- }
- }
- // 取出融合后的结果
- if(!fusionHelper.GetFusedVolumeData(fusedDataInfo))
- {
- // 已经在函数内部写了ErrorMsg了,不用再重复赋值
- return false;
- }
- return true;
- }
- /// <summary>
- /// 图像数据编码并保存至本地
- /// </summary>
- /// <param name="srcImgInfo"></param>
- /// <param name="extension"></param>
- /// <param name="imwriteParams"></param>
- /// <param name="paramCount"></param>
- /// <param name="savePath"></param>
- /// <returns></returns>
- extern "C" __declspec(dllexport) bool ImDataSave(ImageInfo srcImgInfo, ImwriteExtension extension,
- ImwriteParam * imwriteParams, int paramCount, const char* savePath)
- {
- // 如果失败,已经在函数内部写了ErrorMsg了,不用再重复赋值
- return _encodeDecode.SaveImage(srcImgInfo, extension, imwriteParams, paramCount, savePath);
- }
|