在查找 Dicom 中的 Overlay 相关的 Tag 使用方法时,基本上网上能找到的都是 Overlay Tag 的说明。使用 DCMTK 对 Overlay 读写的实例代码很少。


  1. 收集的几个三方库关于 overlay 的使用
  • leadtools 关于 overlay 使用
    https://www.leadtools.com/help/sdk/v21/dicom/api/class-example.html#!

  • pydicom关于 overlay 使用
    https://pydicom.github.io/pydicom/dev/old/working_with_overlays.html

  • ciods关于 overlay 使用
    https://dicom.innolitics.com/ciods/ct-image/overlay-plane/60xx0050

  • clearcanvas 关于 overlay 使用
    https://documentation.clearcanvas.ca/Documentation/DevelopersGuide/1_5_SP1/index.html?add_a_dicom_bitmap_overlay_plane.htm


  1. 示例源代码
    后来,发现最好的示例代码,就是 DCMTK 的 源代码,而源代码中最好的示例,就是下面的一个类:DVPSOverlay。为了避免再次找源代码,就直接把源代码摘抄如下:
/***  Copyright (C) 1998-2018, OFFIS e.V.*  All rights reserved.  See COPYRIGHT file for details.**  This software and supporting documentation were developed by**    OFFIS e.V.*    R&D Division Health*    Escherweg 2*    D-26121 Oldenburg, Germany***  Module: dcmpstat**  Author: Marco Eichelberg**  Purpose:*    classes: DVPSOverlay**/#include "dcmtk/config/osconfig.h"    /* make sure OS specific configuration is included first */
#include "dcmtk/dcmpstat/dvpsov.h"
#include "dcmtk/ofstd/ofstring.h"
#include "dcmtk/dcmpstat/dvpsdef.h"     /* for constants and macros *//* --------------- class DVPSOverlay --------------- */DVPSOverlay::DVPSOverlay()
: overlayGroup(0)
, overlayRows(DCM_OverlayRows)
, overlayColumns(DCM_OverlayColumns)
, overlayType(DCM_OverlayType)
, overlayOrigin(DCM_OverlayOrigin)
, overlayBitsAllocated(DCM_OverlayBitsAllocated)
, overlayBitPosition(DCM_OverlayBitPosition)
, overlayData(DCM_OverlayData)
, overlayDescription(DCM_OverlayDescription)
, overlayLabel(DCM_OverlayLabel)
{
}DVPSOverlay::DVPSOverlay(const DVPSOverlay& copy)
: overlayGroup(copy.overlayGroup)
, overlayRows(copy.overlayRows)
, overlayColumns(copy.overlayColumns)
, overlayType(copy.overlayType)
, overlayOrigin(copy.overlayOrigin)
, overlayBitsAllocated(copy.overlayBitsAllocated)
, overlayBitPosition(copy.overlayBitPosition)
, overlayData(copy.overlayData)
, overlayDescription(copy.overlayDescription)
, overlayLabel(copy.overlayLabel)
{
}DVPSOverlay::~DVPSOverlay()
{
}OFCondition DVPSOverlay::read(DcmItem &dset, Uint8 ovGroup, Uint8 asGroup)
{OFCondition result = EC_Normal;DcmStack stack;if (asGroup==0xFF) asGroup=ovGroup;overlayGroup = asGroup;Uint16 gtag = 0x6000 + ovGroup;overlayRows.setGTag(gtag);overlayColumns.setGTag(gtag);overlayType.setGTag(gtag);overlayOrigin.setGTag(gtag);overlayBitsAllocated.setGTag(gtag);overlayBitPosition.setGTag(gtag);overlayData.setGTag(gtag);overlayDescription.setGTag(gtag);overlayLabel.setGTag(gtag);READ_FROM_DATASET(DcmUnsignedShort, EVR_US, overlayRows)READ_FROM_DATASET(DcmUnsignedShort, EVR_US, overlayColumns)READ_FROM_DATASET(DcmCodeString, EVR_CS, overlayType)READ_FROM_DATASET(DcmSignedShort, EVR_SS, overlayOrigin)READ_FROM_DATASET(DcmUnsignedShort, EVR_US, overlayBitsAllocated)READ_FROM_DATASET(DcmUnsignedShort, EVR_US, overlayBitPosition)READ_FROM_DATASET(DcmOverlayData, EVR_OverlayData, overlayData)READ_FROM_DATASET(DcmLongString, EVR_LO, overlayDescription)READ_FROM_DATASET(DcmLongString, EVR_LO, overlayLabel)/* Now perform basic sanity checks and adjust use flags */if (overlayRows.getLength() == 0){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayRows absent or empty");}else if (overlayRows.getVM() != 1){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayRows VM != 1");}if (overlayColumns.getLength() == 0){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayColumns absent or empty");}else if (overlayColumns.getVM() != 1){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayColumns VM != 1");}if (overlayType.getLength() == 0){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayType absent or empty");}else if (overlayType.getVM() != 1){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayType VM != 1");}if (overlayOrigin.getLength() == 0){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayOrigin absent or empty");}else if (overlayOrigin.getVM() != 2){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayOrigin VM != 2");}if (overlayBitsAllocated.getLength() == 0){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayBitsAllocated absent or empty");}else if (overlayBitsAllocated.getVM() != 1){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayBitsAllocated VM != 1");}if (overlayBitPosition.getLength() == 0){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayBitPosition absent or empty");}else if (overlayBitPosition.getVM() != 1){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayBitPosition VM != 1");}/* in a presentation state object, the overlay data must always be present in this group */if (overlayData.getLength() == 0){result=EC_IllegalCall;DCMPSTAT_WARN("presentation state contains an overlay with overlayData absent or empty");}return result;
}OFCondition DVPSOverlay::write(DcmItem &dset)
{OFCondition result = EC_Normal;DcmElement *delem=NULL;Uint16 repeatingGroup = 0x6000 + overlayGroup;ADD_REPEATING_ELEMENT_TO_DATASET(DcmUnsignedShort, overlayRows, repeatingGroup)ADD_REPEATING_ELEMENT_TO_DATASET(DcmUnsignedShort, overlayColumns, repeatingGroup)ADD_REPEATING_ELEMENT_TO_DATASET(DcmCodeString, overlayType, repeatingGroup)ADD_REPEATING_ELEMENT_TO_DATASET(DcmSignedShort, overlayOrigin, repeatingGroup)ADD_REPEATING_ELEMENT_TO_DATASET(DcmUnsignedShort, overlayBitsAllocated, repeatingGroup)ADD_REPEATING_ELEMENT_TO_DATASET(DcmUnsignedShort, overlayBitPosition, repeatingGroup)if (overlayData.getLength() >0){ADD_REPEATING_ELEMENT_TO_DATASET(DcmOverlayData, overlayData, repeatingGroup)}if (overlayDescription.getLength() >0){ADD_REPEATING_ELEMENT_TO_DATASET(DcmLongString, overlayDescription, repeatingGroup)}if (overlayLabel.getLength() >0){ADD_REPEATING_ELEMENT_TO_DATASET(DcmLongString, overlayLabel, repeatingGroup)}return result;
}OFBool DVPSOverlay::isSuitableAsShutter(unsigned long x, unsigned long y)
{// check that overlay is Graphic, not ROI.if (isROI()) return OFFalse;// check if overlay origin is 1\1Sint16 originX=0;Sint16 originY=0;OFCondition result = overlayOrigin.getSint16(originX,0);if (result==EC_Normal) result = overlayOrigin.getSint16(originY,1);if ((result != EC_Normal)||(originX != 1)||(originY != 1)) return OFFalse;// check if overlay size matches given image sizeUint16 rows=0;Uint16 columns=0;result = overlayRows.getUint16(rows,0);if (result==EC_Normal) result = overlayColumns.getUint16(columns,0);if (result==EC_Normal) return ((columns==x)&&(rows==y));return OFFalse;
}const char *DVPSOverlay::getOverlayLabel()
{char *c = NULL;if (EC_Normal == overlayLabel.getString(c)) return c; else return NULL;
}const char *DVPSOverlay::getOverlayDescription()
{char *c = NULL;if (EC_Normal == overlayDescription.getString(c)) return c; else return NULL;
}OFBool DVPSOverlay::isROI()
{OFString aString;if (EC_Normal == overlayType.getOFString(aString,0)){return (aString == "ROI");}return OFFalse;
}OFCondition DVPSOverlay::getValues(Sint16& originX,Sint16& originY,Uint16& sizeX,Uint16& sizeY)
{OFCondition result = overlayOrigin.getSint16(originX,1);if (result.good()) result = overlayOrigin.getSint16(originY,0);if (result.good()) result = overlayColumns.getUint16(sizeX,0);if (result.good()) result = overlayRows.getUint16(sizeY,0);return result;
}

DCMTK 中源代码中使用 Overlay 的例子相关推荐

  1. C语言主程序如何引用外部源代码中的函数

    Introduction 代码要实现比较复杂的功能时,往往会包含非常多的函数. 当我们想再向其中添加其他功能或修改一些功能时,主程序所在的源代码会越来越冗长,查找并准确地修改某功能对应的函数也变得十分 ...

  2. 如何单独编译Android源代码中的模块

    第一次下载好Android源代码工程后,我们通常是在android源代码工程目录下执行make命令,经过漫长的等待之后,就可以得到Android系统镜像system.img了.以后如果我们修改了And ...

  3. 什么工具可以分析php源代码,PHP_一个可以找出源代码中所有中文的工具,一个可以找出源代码中所有中 - phpStudy...

    一个可以找出源代码中所有中文的工具 一个可以找出源代码中所有中文的工具 填写需要查找的路径$sf即可. 功能 1 找出所有中文 2 忽略注释语句中的中文 3 可添加需要忽略的文件和文件夹 4 生成日志 ...

  4. Java8中Lambda表达式的10个例子

    Java8中Lambda表达式的10个例子  例1 用Lambda表达式实现Runnable接口 Java代码   //Before Java 8: new Thread(new Runnable() ...

  5. 【转】如何单独编译Android源代码中的模块--不错

    原文网址:http://blog.csdn.net//article/details/6566662/ 第一次下载好Android源代码工程后,我们通常是在Android源代码工程目录下执行make命 ...

  6. openLayers3 中实现多个Overlay

    openLayers3 中实现多个Overlay 此篇的目的是为了记录下用Overlay的一些操作. 其实实现多个就是创建多个div,然后给每个div绑定Overlay. 1 //页面加载完函数 -- ...

  7. “源代码中禁止显示”概述

    检查代码之后,您可能确定代码是正确的.也可能是以下情况,即某些冲突的优先级较低,因此不会在当前的开发周期中修复.无论出于何种原因,以下操作通常是有用的,即指出相应警告不适用,以使小组成员了解代码已经过 ...

  8. pytorch tensor查找0_在PyTorch中Tensor的查找和筛选例子

    本文源码基于版本1.0,交互界面基于0.4.1 import torch 按照指定轴上的坐标进行过滤 index_select() 沿着某tensor的一个轴dim筛选若干个坐标 >>&g ...

  9. python爬虫基础教程115_Python解析网页源代码中的115网盘链接实例

    本文实例讲述了python解析网页源代码中的115网盘链接的方法.分享给大家供大家参考.具体方法分析如下: 其中的1.txt,是网页http://bbs.pediy.com/showthread.ph ...

最新文章

  1. 腾讯!阿里!大二男生斩获4家头部科技公司实习offer!完整经验总结!
  2. 观峰雨个人空间 2010 STOCK ADVICE !
  3. Python自动化开发 - RESTful API
  4. qt实现窗口拖动的两种思路
  5. TCP/IP学习笔记-Qt中的ReuseAddressHint以及SO_REUSEADDR,以为组播常用场景分析
  6. 使用php-fpm状态页观察当前的php-fpm状态
  7. rect函数_Python基础入门(9):从函数到高级魔法方法--阿里云天池
  8. EasyUi-1 拖放
  9. 蓝桥杯2014c++真题:切面条
  10. Java中OutOfMemoryError(内存溢出)的情况及解决办法
  11. *(绝对可以安装成功的HUAWEI eNSP模拟器)计算机网络实验(华为eNSP模拟器)——第一章 华为eNSP安装教程
  12. 信息流广告的发展前景!
  13. ROSLAUNCH 的.launch/XML 语法
  14. 没学历可以学IT吗?
  15. Flutter的原理及美团的实践(下,100%好评
  16. python研究背景和意义_一研究背景和意义
  17. 基于多种分隔符进行字符串的分割
  18. 推荐一款截屏翻译工具|截屏提取文字|划词翻译
  19. 动手写一个HTML5的无限循环滚动焦点图
  20. 安卓手机硬件信息修改 Device ID Changer 2020

热门文章

  1. 什么是虚继承?虚基类?
  2. 维基解密披露CIA Grasshopper远程木马套件 Windows预安装环境、Carberp财务恶意软件的计算机驻留方法都用上了...
  3. Python处理HDF5文件:h5py库
  4. 请介绍一下ivac 2L
  5. Unity Substance材质
  6. Symfony5 系列教程1-安装并认识symfony
  7. Linux内核Ramdisk(initrd)机制【转】
  8. 虚拟化中的链接克隆技术
  9. nginx降权及匹配php
  10. 关于考研的几个潜规则