如何从字节创建 DICOM 图像 (DCMTK)
How create a DICOM image from byte (DCMTK)
我想在可以创建 DICOM 图像的现有项目中使用 DCMTK 3.6.1 库。我想使用这个库,因为我想压缩 DICOM 图像。在一个新的解决方案中(Visual Studio 2013/C++)按照DCMTK官方文档中的示例,我有这段代码,可以正常工作。
using namespace std;
int main()
{
DJEncoderRegistration::registerCodecs();
DcmFileFormat fileformat;
/**** MONO FILE ******/
if (fileformat.loadFile("Files/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 EXS_JPEGProcess14SV1
dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms);
// check if everything went well
if (dataset->canWriteXfer(EXS_JPEGProcess14SV1))
{
// force the meta-header UIDs to be re-generated when storing the file
// since the UIDs in the data set may have changed
delete metaInfo->remove(DCM_MediaStorageSOPClassUID);
delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID);
metaInfo->putAndInsertString(DCM_ImplementationVersionName, "New Implementation Version Name");
//delete metaInfo->remove(DCM_ImplementationVersionName);
//dataset->remove(DCM_ImplementationVersionName);
// store in lossless JPEG format
fileformat.saveFile("Files/carrellata_esami_compresso.dcm", EXS_JPEGProcess14SV1);
}
}
DJEncoderRegistration::cleanup();
return 0;
}
现在我想在
的现有 C++ 应用程序中使用相同的代码
if (infoDicom.arrayImgDicom.GetSize() != 0) //Things of existing previous code
{
//I have added here the registration
DJEncoderRegistration::registerCodecs(); // register JPEG codecs
DcmFileFormat fileformat;
DcmDataset *dataset = fileformat.getDataset();
DJ_RPLossless params;
dataset->putAndInsertUint16(DCM_Rows, infoDicom.rows);
dataset->putAndInsertUint16(DCM_Columns, infoDicom.columns,);
dataset->putAndInsertUint16(DCM_BitsStored, infoDicom.m_bitstor);
dataset->putAndInsertUint16(DCM_HighBit, infoDicom.highbit);
dataset->putAndInsertUint16(DCM_PixelRepresentation, infoDicom.pixelrapresentation);
dataset->putAndInsertUint16(DCM_RescaleIntercept, infoDicom.rescaleintercept);
dataset->putAndInsertString(DCM_PhotometricInterpretation,"MONOCHROME2");
dataset->putAndInsertString(DCM_PixelSpacing, "0.086\0.086");
dataset->putAndInsertString(DCM_ImagerPixelSpacing, "0.096\0.096");
BYTE* pData = new BYTE[sizeBuffer];
LPBYTE pSorg;
for (int nf=0; nf<iNumberFrames; nf++)
{
//this contains all the PixelData and I put it into the dataset
pSorg = (BYTE*)infoDicom.arrayImgDicom.GetAt(nf);
dataset->putAndInsertUint8Array(DCM_PixelData, pSorg, sizeBuffer);
dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms);
//and I put it in my data set
//but this IF return false so che canWriteXfer fails...
if (dataset->canWriteXfer(EXS_JPEGProcess14SV1))
{
dataset->remove(DCM_MediaStorageSOPClassUID);
dataset->remove(DCM_MediaStorageSOPInstanceUID);
}
//the saveFile fails too, and the error is "Pixel
//rappresentation non found" but I have set the Pixel rep with
//dataset->putAndInsertUint16(DCM_PixelRepresentation, infoDicom.pixelrapresentation);
OFCondition status = fileformat.saveFile("test1.dcm", EXS_JPEGProcess14SV1);
DJEncoderRegistration::cleanup();
if (status.bad())
{
int error = 0; //only for test
}
thefile.Write(pSorg, sizeBuffer); //previous code
}
实际上我用一帧图像做了测试,所以for循环只做了一次。我不明白为什么如果我选择 dataset->chooseRepresentation(EXS_LittleEndianImplicit, ¶ms);
或 dataset->chooseRepresentation(EXS_LittleEndianEXplicit, ¶ms);
效果很好,但当我选择 dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms);
时却不行
如果我在第一个应用程序中使用相同的图像,我可以毫无问题地压缩图像...
编辑: 我认为要解决的主要问题是 return "Tag not found" 的 status = dataset->chooseRepresentation(EXS_JPEGProcess14SV1, &rp_lossless)
。我怎么知道遗漏了哪个标签?
EDIT2:正如 DCMTK 论坛中的建议,我已经添加了关于分配位的标签,现在 works 用于一些图像,但是不适合所有人。对于某些图像,我又遇到了 "Tag not found":我怎么知道哪个标签丢失了?通常最好插入所有标签?
至少你应该在应用数据后调用函数 chooseRepresentation。
**dataset->putAndInsertUint8Array(DCM_PixelData, pSorg, sizeBuffer);**
dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms);
我解决了添加标签 DCM_BitsAllocated 和 DCM_PlanarConfiguration 的问题。这是遗漏的标签。我希望这对某人有用。
我想在可以创建 DICOM 图像的现有项目中使用 DCMTK 3.6.1 库。我想使用这个库,因为我想压缩 DICOM 图像。在一个新的解决方案中(Visual Studio 2013/C++)按照DCMTK官方文档中的示例,我有这段代码,可以正常工作。
using namespace std;
int main()
{
DJEncoderRegistration::registerCodecs();
DcmFileFormat fileformat;
/**** MONO FILE ******/
if (fileformat.loadFile("Files/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 EXS_JPEGProcess14SV1
dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms);
// check if everything went well
if (dataset->canWriteXfer(EXS_JPEGProcess14SV1))
{
// force the meta-header UIDs to be re-generated when storing the file
// since the UIDs in the data set may have changed
delete metaInfo->remove(DCM_MediaStorageSOPClassUID);
delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID);
metaInfo->putAndInsertString(DCM_ImplementationVersionName, "New Implementation Version Name");
//delete metaInfo->remove(DCM_ImplementationVersionName);
//dataset->remove(DCM_ImplementationVersionName);
// store in lossless JPEG format
fileformat.saveFile("Files/carrellata_esami_compresso.dcm", EXS_JPEGProcess14SV1);
}
}
DJEncoderRegistration::cleanup();
return 0;
}
现在我想在
的现有 C++ 应用程序中使用相同的代码if (infoDicom.arrayImgDicom.GetSize() != 0) //Things of existing previous code
{
//I have added here the registration
DJEncoderRegistration::registerCodecs(); // register JPEG codecs
DcmFileFormat fileformat;
DcmDataset *dataset = fileformat.getDataset();
DJ_RPLossless params;
dataset->putAndInsertUint16(DCM_Rows, infoDicom.rows);
dataset->putAndInsertUint16(DCM_Columns, infoDicom.columns,);
dataset->putAndInsertUint16(DCM_BitsStored, infoDicom.m_bitstor);
dataset->putAndInsertUint16(DCM_HighBit, infoDicom.highbit);
dataset->putAndInsertUint16(DCM_PixelRepresentation, infoDicom.pixelrapresentation);
dataset->putAndInsertUint16(DCM_RescaleIntercept, infoDicom.rescaleintercept);
dataset->putAndInsertString(DCM_PhotometricInterpretation,"MONOCHROME2");
dataset->putAndInsertString(DCM_PixelSpacing, "0.086\0.086");
dataset->putAndInsertString(DCM_ImagerPixelSpacing, "0.096\0.096");
BYTE* pData = new BYTE[sizeBuffer];
LPBYTE pSorg;
for (int nf=0; nf<iNumberFrames; nf++)
{
//this contains all the PixelData and I put it into the dataset
pSorg = (BYTE*)infoDicom.arrayImgDicom.GetAt(nf);
dataset->putAndInsertUint8Array(DCM_PixelData, pSorg, sizeBuffer);
dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms);
//and I put it in my data set
//but this IF return false so che canWriteXfer fails...
if (dataset->canWriteXfer(EXS_JPEGProcess14SV1))
{
dataset->remove(DCM_MediaStorageSOPClassUID);
dataset->remove(DCM_MediaStorageSOPInstanceUID);
}
//the saveFile fails too, and the error is "Pixel
//rappresentation non found" but I have set the Pixel rep with
//dataset->putAndInsertUint16(DCM_PixelRepresentation, infoDicom.pixelrapresentation);
OFCondition status = fileformat.saveFile("test1.dcm", EXS_JPEGProcess14SV1);
DJEncoderRegistration::cleanup();
if (status.bad())
{
int error = 0; //only for test
}
thefile.Write(pSorg, sizeBuffer); //previous code
}
实际上我用一帧图像做了测试,所以for循环只做了一次。我不明白为什么如果我选择 dataset->chooseRepresentation(EXS_LittleEndianImplicit, ¶ms);
或 dataset->chooseRepresentation(EXS_LittleEndianEXplicit, ¶ms);
效果很好,但当我选择 dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms);
如果我在第一个应用程序中使用相同的图像,我可以毫无问题地压缩图像...
编辑: 我认为要解决的主要问题是 return "Tag not found" 的 status = dataset->chooseRepresentation(EXS_JPEGProcess14SV1, &rp_lossless)
。我怎么知道遗漏了哪个标签?
EDIT2:正如 DCMTK 论坛中的建议,我已经添加了关于分配位的标签,现在 works 用于一些图像,但是不适合所有人。对于某些图像,我又遇到了 "Tag not found":我怎么知道哪个标签丢失了?通常最好插入所有标签?
至少你应该在应用数据后调用函数 chooseRepresentation。
**dataset->putAndInsertUint8Array(DCM_PixelData, pSorg, sizeBuffer);**
dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms);
我解决了添加标签 DCM_BitsAllocated 和 DCM_PlanarConfiguration 的问题。这是遗漏的标签。我希望这对某人有用。