传输语法表示了某个dicom
在传输过程中的一些状态封装,有三种形式
- 值表示法(VR):显式VR、 隐式VR
- 字节顺序: Little Endian、 Big Endian
- 压缩格式: JPEG/RLE/有损/无损等好几种
如果是压缩文件,则需要先进行解压操作
压缩文件
DJEncoderRegistration::registerCodecs(); // register JPEG codecs
DcmFileFormat fileformat;
if (fileformat.loadFile("test.dcm").good())
{
DcmDataset *dataset = fileformat.getDataset();
DcmItem *metaInfo = fileformat.getMetaInfo();
DJ_RPLossless params; // codec parameters, we use the defaults
// this causes the lossless JPEG version of the dataset to be created
if (dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms).good() &&
dataset->canWriteXfer(EXS_JPEGProcess14SV1))
{
// store in lossless JPEG format
fileformat.saveFile("test_jpeg.dcm", EXS_JPEGProcess14SV1);
}
}
DJEncoderRegistration::cleanup(); // deregister JPEG codecs
压缩的时候示例采用的是默认参数,这个有多个
默认
DJ_RPLossless params;
常用的
D2RepresentationParameter(
double compressionRatio = 1,
Uint32 compressedSize = 0,
OFBool losslessProcess = OFTrue,
const OFString &imageComment = "")
这个类有三个参数
- compressionRatio 压缩比,必须小于1.0,无损压缩时忽略该参数
- compressedSize 压缩帧大小,以字节为单位,默认为0,非零值将被覆盖,无损压缩时忽略该参数
- losslessProcess 如果在有损传输语法中也应该使用无损处理,则为真
- imageComment 要写入jp2k头的注释
压缩某个dicom
文件可能会出现这样的错误
Pixel representation cannot be changed
查看源码后得知错误原因可能有
......
if (resultStack.top()->ident() == EVR_PixelData)
{
DcmPixelData *pixelData = OFstatic_cast(DcmPixelData *, resultStack.top());
if (!pixelData->canChooseRepresentation(repType, repParam))
l_error = EC_CannotChangeRepresentation;
pixelStack.push(resultStack);
}
else
l_error = EC_CannotChangeRepresentation;
......
错误类型正是这个
makeOFConditionConst(EC_CannotChangeRepresentation, OFM_dcmdata, 14, OF_error, "Pixel representation cannot be changed" );
- 可能数据已经是压缩后的,再次压缩会返回失败;
- 编码器没有找到,可能是没有注册;
解压文件
DJDecoderRegistration::registerCodecs(); // register JPEG codecs
DcmFileFormat fileformat;
if (fileformat.loadFile("test_jpeg.dcm").good())
{
DcmDataset *dataset = fileformat.getDataset();
// decompress data set if compressed
if (dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL).good() &&
dataset->canWriteXfer(EXS_LittleEndianExplicit))
{
fileformat.saveFile("test_decompressed.dcm", EXS_LittleEndianExplicit);
}
}
DJDecoderRegistration::cleanup(); // deregister JPEG codecs
源码部分代码示例
dcmtk
内部初始化时,枚举了所有的压缩类型对应的属性,下面这个是基本数据结构,每个压缩类型对应一个结构体对象
typedef struct
{
const char *xferID;
const char *xferName;
E_TransferSyntax xfer;
E_ByteOrder byteOrder;
E_VRType vrType;
E_JPEGEncapsulated encapsulated;
Uint32 JPEGProcess8;
Uint32 JPEGProcess12;
OFBool lossy;
OFBool retired;
E_StreamCompression streamCompression;
} S_XferNames;
压缩效果
- 采用默认压缩参数,使用
EXS_JPEGProcess2_4
有损压缩
DJ_RPLossless params; // codec parameters, we use the defaults
E_TransferSyntax xfer = EXS_JPEGProcess2_4;
OFCondition ofResult = dataset->chooseRepresentation(xfer, ¶ms);
if (ofResult.good() && dataset->canWriteXfer(xfer))
{
// store in lossless JPEG format
OFCondition ofResult = fileformat.saveFile("G:/dicomFile/8_test_jpeg.dcm", xfer);
}
可以很明显看到图像被压缩的太狠,查看文件大小仅有大概 5KB
,原始文件大小288KB
这种方式几乎不会用,因为图像被压缩的太狠,很多关键信息都丢失了
- 采用自定义压缩参数 使用
EXS_JPEGProcess2_4
有损压缩
int nQuality = 50;
// this causes the lossless JPEG version of the dataset to be created
D2RepresentationParameter rpp( nQuality*0.01, OFstatic_cast(Uint32, 1), OFFalse, "");
OFCondition ofResult = dataset->chooseRepresentation(xfer, &rpp);
这种情况下,压缩后文件大小为 33KB
左右,显示效果比上一个好点
常见图像压缩方式
一般默认可以采用 EXS_JPEGProcess2_4
进行压缩,如果图像包含Overlay
层,则要使用 `
EXS_JPEG2000协议,对于常见的
CT,
MR,
NM,
PET等,如果图像宽高小于 1024 情况下可以采用
EXS_JPEGProcess14SV1`协议
作者:鹅卵石
时间: 2021年8月22日
版本:V 0.0.1
邮箱:kevinlq@163.com
版权:本博客若无特别声明,均属于作者原创文章,欢迎大家转载分享。但是,
希望您注明来源,并留下原文地址,这是对作者最大的尊重,也是对知识的尊重。
如果您对本文有任何问题,可以在下方留言,或者Email我.
捐赠
如果觉得分享的内容不错,可以请作者喝杯咖啡.