本篇文章介绍如何基于dcmtk实现Radiant软件图像overlay操作。并实现添加自定义overlay层,如何显示"HELLO"。
dicom协议的overlay原理部分见文章1.9 DICOM带有overlay覆盖层图像显示(一层覆盖层)
Radiant有如下overlay操作:
隐藏和显示overlay数据
样例图像
一. 实现Radiant相同功能
上图所示的DICOM图像有两层overlay,PixelData全为0。图像中显示的全是overlay数据。
- 显示overlay数据
dcmtk默认显示图像原有的overlay数据,将overlay数据叠加到pixeldata数据上。
1.1 应用层代码实现
int size = dicomImg->getOutputDataSize(8);
unsigned char *pixelDataGrey = new unsigned char[size];
dicomImg->getOutputData(pixelDataGrey, size, 8);
如果手动设置了隐藏overlay层,可以手动设置显示overlay层。
可以单独显示某一层overlay,也可以显示全部overlay层
//判断第一层是否可见
int isVisible = dicomImg->isOverlayVisible(0);
if(isVisible == 0)
{
//显示第一层overlay
dicomImg->showOverlay(0);
//显示所有层overlay
dicomImg->showAllOverlays();
}
int size = dicomImg->getOutputDataSize(8);
unsigned char *pixelDataGrey = new unsigned char[size];
dicomImg->getOutputData(pixelDataGrey, size, 8);
显示效果
bit值为1则有意义像素(默认白色,可自定义颜色),bit为0表示没有意义像素(黑色)。
1.2 底层源码解析
(1)获取图像自带的overlay数据
在DicomImage构造函数内部执行DiMonoImage::Init方法,获得图像自带的overlay数据,并设置默认显示数据
void DiMonoImage::Init(DiMonoModality *modality,
const OFBool reuse)
{
if (modality != NULL)
{
/* only create new overlay object if none exists */
if (Overlays[0] == NULL)
{
Overlays[0] = new DiOverlay(Document, BitsAllocated, BitsStored, HighBit);
if ((Overlays[0] != NULL) && !(Document->getFlags() & CIF_UsePresentationState))
Overlays[0]->showAllPlanes(); // default: show all overlays with stored modes
(2)将overlay数据叠加到pixeldata数据
在DicomImage的getOutputData方法内调用DiMonoOutputPixelTemplate方法,进行Voi lut的窗宽窗位调整后,进行overlay数据叠加
{
if (width < 1) // no valid window according to supplement 33
nowindow(pixel, frame * FrameSize, plut, disp, OFstatic_cast(T3, low), OFstatic_cast(T3, high));
else if (vfunc == EFV_Sigmoid)
sigmoid(pixel, frame * FrameSize, plut, disp, center, width, OFstatic_cast(T3, low), OFstatic_cast(T3, high));
else // linear
window(pixel, frame * FrameSize, plut, disp, center, width, OFstatic_cast(T3, low), OFstatic_cast(T3, high));
}
overlay(overlays, disp, columns, rows, frame); // add (visible) overlay planes to output bitmap
- 隐藏overlay数据
可以单独隐藏某一层overlay,也可以隐藏全部overlay层
2.1 应用层代码实现
//隐藏第一层overlay
//dicomImg->hideOverlay(0);
//隐藏第二层overlay
//dicomImg->hideOverlay(1);
//隐藏所有overlay层
dicomImg->hideAllOverlays();
int size = dicomImg->getOutputDataSize(8);
unsigned char *pixelDataGrey = new unsigned char[size];
dicomImg->getOutputData(pixelDataGrey, size, 8);
显示效果
至此dcmtk实现Radiant相关的overlay操作。
二. 进行dcmtk一些其他操作:
- 获取overlay模块相关元素
dicom协议规定的overlay元素
dcmtk获取overlay相关元素的接口如下:
//获取overlay数量,最多16层
int count = dicomImg->getOverlayCount();
//获取某一层overlay组号
int groupNum = dicomImg->getOverlayGroupNumber(1);
//获取某一层overlay描述
const char *description = dicomImg->getOverlayDescription(1);
//获取某一层overlay标签
const char *lable = dicomImg->getOverlayLabel(1);
//获取overlay模式
EM_Overlay mode = dicomImg->getOverlayMode(10);
unsigned int left_pos;
unsigned int top_pos;
unsigned int width;
unsigned int height;
EM_Overlay mode1;
//获取overlay数据,同时获取overlay origin和rows,cloumn,mode
Uint8 * overlayData = (Uint8*)dicomImg->getOverlayData(1, left_pos, top_pos, width, height, mode1);
overlay模式如下,G表示EMO_Graphic=EMO_Replace,overlay数据替换对应坐标点的pixeldata数据。R表示ROI感兴趣区域。
enum EM_Ove