dcmtk支持解压jpeg2000dcm文件

一. windows 端编译 dcmtk支持 jpeg2000 编解码dcm文件
dcmjp2k模块非免费:https://dicom.offis.de/en/dcmtk-expansion-modules/dcmjp2k/
为了解决该问题dcmtk支持jpeg2000编解码dcm文件,在GitHub上看到

1.准备工作: 从dcmtk官网中 下载dcmtk源码 和openjpeg源码:
https://dicom.offis.de/download/dcmtk/dcmtk366/support/openjpeg-v2.4.0.tar.gz
https://dicom.offis.de/download/dcmtk/dcmtk366/dcmtk-3.6.6.tar.gz

将源码解压,在windows端编译 openjpeg-v2.4.0 dcmtk-3.6.6 为 Release x64版本的库。使用cmake工具编译。

2.从githup中下载源码:https://github.com/DraconPern/fmjpeg2koj

3.将fmjpeg2koj目录中 include文件拷贝到自己的工程目录下,及8个.cc文件

在这里插入图片描述
4.写测试代码 支持jpeg2000解压,取图片像素数据。
dicom_open.h

#ifndef DICOM_OPEN_H
#define DICOM_OPEN_H

typedef struct _DcmFileMessgae
{
    int isCompressIndex;                //dicom文件是否压缩  0:未压缩  1:压缩
    const char* patientID;              //患者ID
    const char* patientName;            //患者姓名
    const char* patientSex;             //患者性别
    const char* patientAge;             //患者年龄
    const char* patientBirthDate;       //患者生日
    const char* patientAddress;         //患者家庭地址
    const char* modality;               //dcm文件类型 CT MR DX US
    const char* photoIntertion;         //图像模式  MONOCHROME2/MONOCHROME1
    const char* transferSyntax;         //dicom压缩语法

    const char* studyDate;              //检查日期
    const char* studyTime;              //检查时间
    const char* studyID;                //检查ID
    const char* studyInstanceUID;       //检查UID
    const char* studyDescription;       //检查描述

    const char* seriesDate;         //检查日期
    const char* seriesTime;         //检查时间
    const char* seriesInstanceUID;
    const char* seriesDescription;  //检查描述和说明
    const char* sopInstanceUID;
    const char* sopClassUID;
    const char* contentDate;
    const char* seriesNumber;       //序列号


    long int numFrame;              //图片数量
    unsigned short mWidth;          //图片宽度
    unsigned short mHeight;         //图片高度
    unsigned short wCenter;         //窗位
    unsigned short wWidth;          //窗高
    unsigned short bitsCount;       //一个像素取样点存储时使用到的位数 8 12 16
    unsigned short bitsAllcated;    //一个像素取样点存储时分配到的位数
    unsigned short bitsSample;      //1灰度图 3彩色图
    unsigned short pixelReNum;      //有符号存储 或无符号存储
    unsigned short bitsHigh;        //最高位序号,它定义了存储点在分配的内存中的排列方式
    unsigned short instanceNumber;  //

}DcmFileMessage;



/*
 function: 初始化读取dcm文件,获取dcm文件信息,解压dcm文件

 @filepath: dcm文件路径
 @pt: dcm文件信息结构体

 return: 正常返回0
 */
int initDcmFile_t(const char *filepath, DcmFileMessage *pt);


/*
 function: 保存dicom图片数据为bmp图片

 @bmppath: bmp文件路径
 @numIndex: dcm第几张图片序列号

 return: 0=正常返回0
 */
int saveBmpFile_t(const char *bmppath, int numIndex);


/*
 function: 释放dcm文件内存

 */
int freeDcmFile_t();

dicom_open.cpp

#include "dicom_open.h"

#include "dcmtk/dcmimage/diregist.h"
#include "dcmtk/dcmimgle/dcmimage.h"

#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcpixel.h"
#include "dcmtk/ofstd/ofcond.h"
#include "dcmtk/ofstd/ofstring.h"
#include "dcmtk/dcmdata/dcitem.h"
#include "dcmtk/dcmdata/dctagkey.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcmetinf.h"

#include "dcmtk/dcmjpeg/djdecode.h"
#include "dcmtk/dcmdata/dcrledrg.h"
#include "dcmtk/dcmjpls/djdecode.h"
#include "fmjpeg2k/djdecode.h"

#include <iostream>
#include <string>
using namespace std;

static DcmFileFormat *fileFormat = nullptr;
static DcmDataset    *dataSet    = nullptr;
static E_TransferSyntax xfer;          		//dicom传输语法

/*
 function: 初始化读取dcm文件,获取dcm文件信息,解压dcm文件

 @filepath: dcm文件路径
 @pt: dcm文件信息结构体

 return: 正常返回0
 */
int initDcmFile_t(const char *filepath, DcmFileMessage *pt)
{
	if (fileFormat)
	{
		delete fileFormat;
		fileFormat = nullptr;
	}
	if (fileFormat == nullptr)
	{
		fileFormat = new DcmFileFormat();
	}

	OFCondition condition = fileFormat->loadFile(filepath);
    if(condition.bad())
    {
    	printf("dcm file load failed\n");
        return -1;
    }
	
    dataSet = fileFormat->getDataset();					//dicom数据集
    DcmMetaInfo *metaInfo= fileFormat->getMetaInfo();
    xfer = dataSet->getOriginalXfer();          		//dicom传输语法

    // 获取dicom文件压缩语法
	metaInfo->findAndGetString(DCM_TransferSyntaxUID, pt->transferSyntax);
    if(pt->transferSyntax == nullptr)
    {
        pt->isCompressIndex = 0;
        pt->transferSyntax = "1.2.840.10008.1.2";
    }
    else
    {
        pt->isCompressIndex = 1;
    }

	dataSet->findAndGetString(DCM_PatientID,     pt->patientID);
	dataSet->findAndGetString(DCM_PatientName,   pt->patientName);
	dataSet->findAndGetString(DCM_PatientSex,    pt->patientSex);
	dataSet->findAndGetString(DCM_PatientAge,    pt->patientAge);
	dataSet->findAndGetString(DCM_PatientBirthDate, pt->patientBirthDate);
	dataSet->findAndGetString(DCM_PatientAddress,   pt->patientAddress);

	dataSet->findAndGetString(DCM_StudyDate,		 pt->studyDate);
	dataSet->findAndGetString(DCM_StudyTime,		 pt->studyTime);
	dataSet->findAndGetString(DCM_StudyID,           pt->studyID);
	dataSet->findAndGetString(DCM_StudyInstanceUID,  pt->studyInstanceUID);
	dataSet->findAndGetString(DCM_StudyDescription,  pt->studyDescription);

	dataSet->findAndGetString(DCM_SeriesDate,    pt->seriesDate);
	dataSet->findAndGetString(DCM_SeriesTime,    pt->seriesTime);
	dataSet->findAndGetString(DCM_SeriesInstanceUID, pt->seriesInstanceUID);
	dataSet->findAndGetString(DCM_SeriesDescription, pt->seriesDescription);
	dataSet->findAndGetString(DCM_SOPInstanceUID, pt->sopInstanceUID);
	dataSet->findAndGetString(DCM_SOPClassUID,   pt->sopClassUID);
	dataSet->findAndGetString(DCM_ContentDate,   pt->contentDate);

	dataSet->findAndGetString(DCM_PhotometricInterpretation, pt->photoIntertion);  //获取图像模式
	dataSet->findAndGetString(DCM_Modality,      pt->modality);          //图像类型 CT DX MR

	dataSet->findAndGetLongInt(DCM_NumberOfFrames, pt->numFrame);        //获取图片数量
    if(pt->numFrame == 0)
        pt->numFrame =1;


	dataSet->findAndGetUint16(DCM_BitsStored,   pt->bitsCount);         //图像位数 8 12 16
	dataSet->findAndGetUint16(DCM_BitsAllocated, pt->bitsAllcated);     //图像存储
	dataSet->findAndGetUint16(DCM_SamplesPerPixel, pt->bitsSample);     //图像像素字节
	dataSet->findAndGetUint16(DCM_Columns, pt->mWidth);                 //图像宽度
	dataSet->findAndGetUint16(DCM_Rows, pt->mHeight);                   //图像高度
	dataSet->findAndGetUint16(DCM_WindowCenter, pt->wCenter);           //图像窗位
	dataSet->findAndGetUint16(DCM_WindowWidth, pt->wWidth);             //图像宽位
	dataSet->findAndGetUint16(DCM_PixelRepresentation, pt->pixelReNum); //判断数据是有符号存储,还是无符号存储
	dataSet->findAndGetUint16(DCM_HighBit, pt->bitsHigh);
	dataSet->findAndGetUint16(DCM_InstanceNumber, pt->instanceNumber);
	dataSet->findAndGetString(DCM_SeriesNumber,  pt->seriesNumber);

	if (!pt->patientID)
		pt->patientID = "";

	if (!pt->patientName)
		pt->patientName = "";

	if (!pt->patientSex)
		pt->patientSex = "";

	if (!pt->patientAge)
		pt->patientAge = "";

	if (!pt->patientAddress)
		pt->patientAddress = "";

	if (!pt->patientBirthDate)
		pt->patientBirthDate = "";

	if (!pt->studyDate)
		pt->studyDate = "";

	if (!pt->studyTime)
		pt->studyTime = "";

	if (!pt->studyID)
		pt->studyID = "";

	if (!pt->studyInstanceUID)
		pt->studyInstanceUID = "";

	if (!pt->studyDescription)
		pt->studyDescription = "";

	if (!pt->seriesDate)
		pt->seriesDate = "";

	if (!pt->seriesTime)
		pt->seriesTime = "";

	if (!pt->seriesInstanceUID)
		pt->seriesInstanceUID = "";

	if (!pt->seriesDescription)
		pt->seriesDescription = "";

	if (!pt->sopInstanceUID)
		pt->sopInstanceUID = "";

	if (!pt->sopClassUID)
		pt->sopClassUID = "";

	if (!pt->contentDate)
		pt->contentDate = "";

	if (!pt->photoIntertion)
		pt->photoIntertion = "";

	if (!pt->modality)
		pt->modality = "";

	if (!pt->seriesNumber)
		pt->seriesNumber = "";


	/*    jpeg        */
	string loss_JPEGProcess1 = "1.2.840.10008.1.2.4.50";
	string loss_JPEGProcess2_4 = "1.2.840.10008.1.2.4.51";
	string loss_JPEGProcess6_8 = "1.2.840.10008.1.2.4.53";
	string loss_JPEGProcess10_12 = "1.2.840.10008.1.2.4.55";
	string loss_JPEGProcess14 = "1.2.840.10008.1.2.4.57";
	string loss_JPEGProcess14SV1 = "1.2.840.10008.1.2.4.70";

	/*    RLELoss     */
	string loss_RLELossless = "1.2.840.10008.1.2.5";

	/*    jpegls      */
	string loss_JPEGLSLossless = "1.2.840.10008.1.2.4.80";
	string loss_JPEGLSLossy = "1.2.840.10008.1.2.4.81";

	/*    jpeg2000    */
	string loss_JPEG2000LosslessOnly = "1.2.840.10008.1.2.4.90";
	string loss_JPEG2000 = "1.2.840.10008.1.2.4.91";

	// 开始解压dcm文件
	if (pt->isCompressIndex)
	{
		if (pt->transferSyntax == loss_JPEGProcess1 || pt->transferSyntax == loss_JPEGProcess2_4 || pt->transferSyntax == loss_JPEGProcess6_8 ||
			pt->transferSyntax == loss_JPEGProcess10_12 || pt->transferSyntax == loss_JPEGProcess14 || pt->transferSyntax == loss_JPEGProcess14SV1)
		{
			DJDecoderRegistration::registerCodecs();
			dataSet->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
			DJDecoderRegistration::cleanup();
		}
		else if (pt->transferSyntax == loss_RLELossless)
		{
			DcmRLEDecoderRegistration::registerCodecs();
			dataSet->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
			DcmRLEDecoderRegistration::cleanup();
		}
		else if (pt->transferSyntax == loss_JPEGLSLossless || pt->transferSyntax == loss_JPEGLSLossy)
		{
			DJLSDecoderRegistration::registerCodecs();
			dataSet->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
			DJLSDecoderRegistration::cleanup();
		}
		else if (pt->transferSyntax == loss_JPEG2000 || pt->transferSyntax == loss_JPEG2000LosslessOnly)
		{
			FMJPEG2KDecoderRegistration::registerCodecs();
			dataSet->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
			FMJPEG2KDecoderRegistration::cleanup();
		}
		else
		{
			dataSet->chooseRepresentation(xfer, NULL);
		}
	}
	return 0;
}

/*
 function: 保存dicom图片数据为bmp图片

 @bmppath: bmp文件路径
 @numIndex: dcm第几张图片序列号

 return: 0=正常返回0
 */
int saveBmpFile_t(const char *bmppath, int numIndex)
{
	DicomImage *diImage = new DicomImage(dataSet, xfer, CIF_UsePartialAccessToPixelData, numIndex, 1);
	if (!diImage)
	{
		printf("malloc DicomImage failed\n");
		return -1;
	}

	FILE *bmpFile = fopen(bmppath, "wb");
	if(!bmpFile)
	{
		printf("open bmp file failed\n");
		return -2;
	}

	diImage->writeBMP(bmpFile, 24, 0);

	if(diImage)
	{
		delete diImage;
		diImage = nullptr;
	}
	if(bmpFile)
	{
		fclose(bmpFile);
	}
	return 0;
}

/*

 function: 释放dcm文件内存

 */

int freeDcmFile_t()
{
    if(fileFormat)
    {
        delete fileFormat;
        fileFormat = nullptr;
    }
    return 0;
}

main.cpp

#include "dicom_open.h"
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
int main(int argc, char *argv[])
{
	//图片数量
	int num = 0;																	
	char dcm_filepath[128] = "";	
	char bmp_filepath[128] = "";
	char tmp_buff[128]  = "";
	
	memcpy(dcm_filepath, argv[1], strlen(argv[1]));
	DcmFileMessage *pt = (DcmFileMessage*)malloc(sizeof(DcmFileMessage));
	if (!pt)
	{
		printf("malloc DcmFileMessage failed\n");
		return -1;
	}
	//初始化读取dcm文件,获取dcm文件信息,解压dcm文件
	if (initDcmFile_t(dcm_filepath, pt) < 0)
	{
		goto endX;
	}

	printf("patientID=%s\n",   pt->patientID);
	printf("patientName=%s\n", pt->patientName);
	printf("patientSex=%s\n",  pt->patientSex);
	printf("patientAge=%s\n",  pt->patientAge);
	printf("imgWidth=%d\n",    pt->mWidth);
	printf("imgHeight=%d\n",   pt->mHeight);

	num = pt->numFrame;
	sscanf(dcm_filepath, "%[^.]", tmp_buff);
	
	for (int i = 0; i < num; i++)
	{
		// bmp文件名
		memset(bmp_filepath, 0, sizeof(bmp_filepath));
		sprintf(bmp_filepath, "%s_%03d.bmp", tmp_buff, i);
		printf("bmp_filepath=[%s]\n", bmp_filepath);
		// 保存dicom图片数据为bmp图片
		if(saveBmpFile_t(bmp_filepath, i) < 0)
		{
			goto endX;
		}
	}

endX:
	// 释放dcm文件内存
	freeDcmFile_t();
	if (pt)
	{
		free(pt);
		pt = NULL;
	}
	return 0;
}

测试应用程序, 编译完终端执行 ./main ./file/DX_dcm1.dcm

结果:如下图 ,左边是jpeg2000编码dcm文件,右边是解码后的bmp文件
在这里插入图片描述

DCMTK是一款用于医学图像和通信的开源软件包。它包含了各种用于处理、转换和通信DICOM格式的工具和库。其中的pdf2dcm工具被用于将PDF(Portable Document Format)文件转换为DICOM(Digital Imaging and Communications in Medicine)格式的图像。下面我将简要介绍pdf2dcm的使用方法。 pdf2dcm工具可以在命令行下执行。首先,您需要确保已经正确安装和配置了DCMTK软件包。然后,您可以使用pdf2dcm命令将PDF文件转换为DICOM图像。可以通过以下命令完成转换: pdf2dcm input.pdf output.dcm 其中,input.pdf是要转换的PDF文件的路径,output.dcm是要保存的DICOM文件的路径。 当转换完成后,output.dcm文件将包含从PDF提取的相关信息,如图像数据、患者信息等。可以使用DICOM文件查看器等工具来验证转换是否成功。 在转换过程中,pdf2dcm会尝试从PDF中提取图像数据。如果PDF文件包含多页,每一页都将转换为DICOM格式的图像。转换结果还会包含PDF中的文本和图形等其他相关信息。 需要注意的是,pdf2dcm转换的DICOM图像不会包含DICOM标准中定义的所有字段和信息。转换时可能会丢失一些PDF中的细节。另外,如果PDF文件中的文本信息不够清晰,转换后的图像质量可能会受到影响。 总之,DCMTK的pdf2dcm工具能够将PDF文件转换为DICOM格式的图像。它是医学图像处理和通信中的一个有用工具,可以帮助实现图像数据的转换和应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值