创建多帧超声DICOM文件



我是DICOM和DCMTK的新手。我有一组BITMAP超声数据,我想保存为无损DICOM文件。

在将数据加载到队列frame_queue中并设置超声多帧图像的所有强制性DICOM必要参数后,我实现了一个循环,将图像添加到DcmDataset中,如下所示:

std::unique_ptr<DcmDataset> dataset;
/*** 
DICOM parameters A setted not added here as many parameters are set
***/

std::shared_ptr<unsigned char[]> frame;
std::shared_ptr<RGBQUAD[]> colorTable;
DJEncoderRegistration::registerCodecs();
DJ_RPLossless params; // codec parameters, we use the defaults
// this causes the lossless JPEG version of the m_dataset to be created

/**/
E_TransferSyntax xfer = DcmXfer(EXS_JPEGProcess14).getXfer();
DcmPixelSequence* sequence = new DcmPixelSequence(DcmTag(DCM_PixelData, EVR_OB));
DcmPixelData* newPixelData = new DcmPixelData(DCM_PixelData);
dataset->insert(sequence, OFTrue);
OFstatic_cast(DcmPixelData*, newPixelData)->putOriginalRepresentation(xfer, NULL, sequence);
while (frame_queue.popFrame(frame, colorTable)) // we extract a new frame from the queue
{
DcmPixelItem* newItem = new DcmPixelItem(DcmTag(DCM_Item, EVR_OB));
if (newItem != NULL)
{
sequence->insert(newItem);
/* put pixel data into the item */
std::shared_ptr<Uint8[]> newDCMFrame;

colorTableToRGB(frame, colorTable, newDCMFrame, m_frameWidth, m_frameHeight);
result = newItem->putUint8Array((Uint8*)newDCMFrame.get(), m_frameHeight * m_frameWidth * 3).good(); // this returns true in my test
frame.reset();
colorTable.reset();
}
}
dataset->chooseRepresentation(EXS_JPEGProcess14, &params); 
dataset->saveFile(path.c_str());

dataset->chooseRepresentation(EXS_JPEGProcess14, &params);的调用引发错误:

DcmDataset: Wrong class for pixel data element, cannot change representation

DICOM文件已保存,但为空。

有人知道是什么导致了这个错误吗?

只是猜测,但您正在以未压缩的表示形式创建数据集。在这种情况下,像素数据不能表示为帧序列。您应该尝试直接在DcmPixelData元素上调用putUint8Array(),而不是向其插入序列

当您调用DcmDataset::chooseRepresentation()时,DCMTK会将这种编码方式更改为您想要直接实现的编码方式。

对于未压缩的像素数据;封装的";用序列编码的像素数据,我怀疑这就是DcmDataset::chooseRepresentation()抱怨";没有找到所期望的";。

所以我终于让它工作了:

std::unique_ptr<DcmDataset> dataset;
/*** 
DICOM parameters A setted not added here as many parameters are set
***/

std::shared_ptr<unsigned char[]> frame;
std::shared_ptr<RGBQUAD[]> colorTable;
DJEncoderRegistration::registerCodecs();
DJ_RPLossless params; // codec parameters, we use the defaults
// this causes the lossless JPEG version of the m_dataset to be created

/**/
E_TransferSyntax xfer = DcmXfer(EXS_JPEGProcess14).getXfer();
DcmPixelData* newPixelData = new DcmPixelData(DCM_PixelData);
dataset->insert(newPixelData , OFTrue);

bool result = true;
static const int imageSize = m_frameWidth * m_frameHeight * 3;
std::shared_ptr<Uint8[]> imagesBufferPtr(new Uint8[imageSize * m_nbFrames], array_deleter<Uint8>());
std::vector<std::vector<Uint8>> dataImages(m_nbFrames, std::vector<Uint8>(imageSize));
int frameId = 0;
while (this->popFrame(frame, colorTable) == cwlibdicom::frameBufferStatus::BUFFER_SUCCESS && result)
{
Uint8 *img = imagesBufferPtr.get();
img = &img[frameId];
colorTableToRGB(frame, colorTable, img, m_frameWidth, m_frameHeight);
std::memcpy(&imagesBufferPtr.get()[frameId * imageSize], img.data(), imageSize);
frameId++;
frame.reset();
colorTable.reset();
}
result = newPixelData->putUint8Array(imagesBufferPtr.get(), imageSize * m_nbFrames).good();
header->setProperty(DCM_NumberOfFrames, nb_frame);
header->setProperty(DCM_SamplesPerPixel, "3");
header->setProperty(DCM_PhotometricInterpretation, "RGB");
header->setProperty(DCM_Rows, m_imageHeight);
header->setProperty(DCM_Cols, m_imageWidth);
header->setProperty(DCM_BitsAllocated, "8");
header->setProperty(DCM_BitsStored, "8");
header->setProperty(DCM_HighBit, "7");
header->setProperty(DCM_PixelRepresentation, "0");
header->setProperty(DCM_FrameIncrementPointer, "(0018, 1065)\(F9E4, 3317)"); // Found this in a multiframe image that already existed.
dataset->chooseRepresentation(EXS_JPEGProcess14, &params); 
dataset->saveFile(path.c_str(), EXS_JPEGProcess14); 

最新更新