当前位置: 首页 > news >正文

基于dcmtk的dicom工具 第十一章 加载dicom文件多帧图数据

文章目录

  • 前言
  • 一、加载多帧图的方法
    • 1. DicomImage 构造函数
    • 2. DcmParser Open函数
    • 3. DcmParser CreateDIB函数
    • 4. 为Displayer类添加PrevFrame,NextFrame两个函数
  • 二、按钮滚动帧
  • 三、鼠标滚轮滚动帧


前言

继前一章,本章实现多帧图显示,增加“上一帧”、“下一帧”两个按钮,和鼠标滚动消息滚动不同帧。
效果如下:
在这里插入图片描述


一、加载多帧图的方法

1. DicomImage 构造函数

下面是dcmtk DicomImage类的一个构造函数,创建dcmtk DicomImage对象时,单帧图只需要填写前两个参数即可,多帧图flags参数填 CIF_UsePartialAccessToPixelData,再配合 fstart, fcount参数即可加载第fstart帧到 fstart+fcount帧的图像数据

 /** constructor, use a given DcmObject*** @param  object  pointer to DICOM data structures (fileformat, dataset or item).*                  (do not delete while referenced, i.e. while this image object or any*                   descendant exists; not deleted within dcmimage unless configuration flag*                   CIF_TakeOverExternalDataset is set - in this case do not delete it at all)*  @param  xfer    transfer syntax of the 'object'.*                  (could also be EXS_Unknown in case of fileformat or dataset)*  @param  flags   configuration flags (CIF_xxx, see diutils.h)*  @param  fstart  first frame to be processed (optional, 0 = 1st frame), all subsequent use*                  of parameters labeled 'frame' in this class refers to this start frame.*  @param  fcount  number of frames (optional, 0 = all frames)*/DicomImage(DcmObject *object,const E_TransferSyntax xfer,const unsigned long flags = 0,const unsigned long fstart = 0,const unsigned long fcount = 0);

2. DcmParser Open函数

DcmParser类中的Open, CreateDIB两个函数中处理多帧图的代码
Open函数中的代码,默认多帧图fcount=5,即只加载最多5帧数据到内存,可根据电脑内存修改:

BOOL DcmParser::Open(std::string dcmfile)
{if (m_bParserValid)return TRUE;dcmAcceptUnexpectedImplicitEncoding.set(OFFalse);dcmPreferVRFromDataDictionary.set(OFFalse);OFCondition cond;cond = m_dcmFile.loadFile(dcmfile.c_str());...if (m_nFrameCount == 1) {m_pDcmImg = new DicomImage(pDataset, m_newXfer);}else {   // 多帧图,只加载最多5帧数据m_nLoadCount = m_nFrameCount > 5 ? 5 : m_nFrameCount;m_nFrameStart = 0;unsigned long flag = CIF_UsePartialAccessToPixelData;m_pDcmImg = new DicomImage(pDataset, m_orgXfer, flag, m_nFrameStart, m_nLoadCount);}...return m_bParserValid;
}

3. DcmParser CreateDIB函数

对于多帧图,Open函数中默认加载的是前五帧的图像数据,索引[0,4],当CreateDIB函数的frame参数值超过4时,需要加载下一个五帧的图像数据,索引[5,9]
最重要的四行代码:

  1. int fend = m_nFrameStart + m_nLoadCount - 1; 用来判断frame是否超出范围
  2. m_nFrameStart = frame / m_nLoadCount * m_nLoadCount; 计算新的起始帧索引
  3. m_pDcmImg = new DicomImage(pDataset, m_orgXfer, flag, m_nFrameStart, m_nLoadCount); 加载新五帧数据
  4. size = di->createWindowsDIB(pdib, 0, frame-m_nFrameStart, 24, 1); 创建当前frame帧位图数据
BOOL DcmParser::CreateDIB(void*& pdib, int& w, int& h, double wc, double ww, int frame/* = 0*/, bool bneg/* = false*/)
{DcmDataset* pDataset = m_dcmFile.getDataset();int fend = m_nFrameStart + m_nLoadCount - 1;if (!(frame >= m_nFrameStart && frame <= fend)) {m_nFrameStart = frame / m_nLoadCount * m_nLoadCount;delete m_pDcmImg;unsigned long flag = CIF_UsePartialAccessToPixelData;m_pDcmImg = new DicomImage(pDataset, m_orgXfer, flag, m_nFrameStart, m_nLoadCount);}...size = di->createWindowsDIB(pdib, 0, frame-m_nFrameStart, 24, 1);...}

4. 为Displayer类添加PrevFrame,NextFrame两个函数

在绘制参数DrawParam.nFrame中记录当前帧索引,只需要增减nFrame,再调用DcmParser中的CreateDIB重建生成位图数据即可。

void Displayer::PrevFrame()
{int nFrame = m_drawParam.nFrame - 1;if (nFrame < 0) {return;}m_drawParam.nFrame = nFrame;if (m_pDib){delete[] m_pDib;m_pDib = nullptr;}m_pImage->CreateDIB(m_pDib, m_drawParam.width, m_drawParam.height, m_drawParam.winCenter,m_drawParam.winWidth, m_drawParam.nFrame, m_drawParam.bNagtive);FitToView();
}void Displayer::NextFrame()
{int nFrameCount = m_pImage->GetFrameCount();int nFrame = m_drawParam.nFrame + 1;if (nFrame > nFrameCount - 1) {return;}m_drawParam.nFrame = nFrame;if (m_pDib){delete[] m_pDib;m_pDib = nullptr;}m_pImage->CreateDIB(m_pDib, m_drawParam.width, m_drawParam.height, m_drawParam.winCenter,m_drawParam.winWidth, m_drawParam.nFrame, m_drawParam.bNagtive);FitToView();
}

二、按钮滚动帧

  1. 在对话框中添加“上一帧”,“下一帧”两个按钮
  2. 在CDcmImageDlg中为按钮添加响应事件
  3. 图像加载时检查dicom文件是否为多帧图,控制两个按钮是否变灰
void CDcmImageDlg::OnBnClickedButtonPrevFrame()
{m_disp.PrevFrame();
}void CDcmImageDlg::OnBnClickedButtonNextFrame()
{m_disp.NextFrame();
}void CDcmImageDlg::OnSelchangeListDcm()
{// TODO: 在此添加控件通知处理程序代码CString str;int idx = m_list.GetCurSel();m_list.GetText(idx, str);m_disp.LoadFile(str);int nFrames = m_disp.GetFrameCount();if (nFrames > 1) {GetDlgItem(IDC_BUTTON_PREV_FRAME)->EnableWindow(TRUE);GetDlgItem(IDC_BUTTON_NEXT_FRAME)->EnableWindow(TRUE);}else {GetDlgItem(IDC_BUTTON_PREV_FRAME)->EnableWindow(FALSE);GetDlgItem(IDC_BUTTON_NEXT_FRAME)->EnableWindow(FALSE);}}

三、鼠标滚轮滚动帧

Displayer类中添加鼠标滚轮消息WM_MOUSEWHEEL,调用NextFrame,PrevFrame滚动帧

BEGIN_MESSAGE_MAP(Displayer, CWnd)ON_WM_PAINT()ON_WM_SIZE()ON_WM_MOUSEWHEEL()   // 鼠标滚轮
END_MESSAGE_MAP()BOOL Displayer::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{// TODO: 在此添加消息处理程序代码和/或调用默认值if (!m_pImage) return true;int nFrames = m_pImage->GetFrameCount();if (nFrames > 1) {if (zDelta < 0) {NextFrame();}else {PrevFrame();}}return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}
http://www.dtcms.com/a/541702.html

相关文章:

  • 建网站多少钱一平方电工证免考拿证
  • 桌面开发,在线%可视化,招聘系统demo,基于python,matplotlib,request,爬虫,数据库无
  • 护照识别接口-高效智能的OCR身份核验新体验-OCR文字识别API
  • 性能测试 | 性能测试工具JMeter直连数据库和逻辑控制器的使用
  • 建站 报价专业网站开发制作公司
  • 手机版网站如何做直接进网站的浏览器
  • 网站建设总结与心得体会颍州网站建设
  • 引力概念中的混乱点:传统物理学与张祥前统一场论对比
  • 通管局报审通关秘籍:网约车平台网络安全防护与保障能力报告
  • 郑州市建设网站wordpress 加斜杠
  • 正规网站建设公司一般要多少钱建设银行面试经验网站
  • [ssh]系统重装后,如何重新设置window免密登录远程linux服务器
  • 网站模板预览与编辑器旅游网站简介
  • 网站建设ppt百度文库注册公司地址可以用家庭地址
  • 学习一下kernel6.12中sugov_iowait_apply的函数逻辑
  • 北京网站开发报价做搜狗网站优化首页软
  • node.js网站开发十大购物网站排行榜
  • ProcDump 学习笔记(6.14):在调试器中查看转储(WinDbg / Visual Studio 快速上手)
  • 正规网站建设报价网站建设案例精粹 电子书
  • PE之不同区域的结构体定义
  • Ubuntu24.04 赋予 Qt 应用程序 修改系统时间 权限
  • 50+孙悦梓潼舞台状态惊艳全网!自律的女神,连下颌线都是顶配
  • Rust:复合类型内存布局
  • net网站是国际域名吗wordpress发布文章页面错误
  • 英语学习 第一周 重难点
  • 做国际网站的流程unity做网站
  • 模板性公司网站图片网站制作的发展趋势
  • 石英加速度计如何敏锐感知飞机爬升与转弯的细微变化?
  • 【VS2019配置Boost】vs2019无法识别boost库目录
  • 要进一步增强门户网站建设合力有几个网站能在百度做推广