Reputation: 49
I am new at DICOM and DCMTK. I have a set of BITMAP Ultrasound data that I would like to save as a lossless DICOM file.
After loadding the data in a queue frame_queue
and setting all the mandatory DICOM necessary parameters for Ultrasound Multiframe images I realise a loop to add the images in the DcmDataset as follows:
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, ¶ms);
dataset->saveFile(path.c_str());
The call of dataset->chooseRepresentation(EXS_JPEGProcess14, ¶ms);
raises the error:
DcmDataset: Wrong class for pixel data element, cannot change representation
A DICOM File is saved but it is empty.
Does anyone know what's causing this error?
Upvotes: 0
Views: 1051
Reputation: 49
So I finaly got it to work:
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, ¶ms);
dataset->saveFile(path.c_str(), EXS_JPEGProcess14);
Upvotes: 1
Reputation: 4013
Just a guess but you are creating the dataset in uncompressed representation. In this case, the pixel data must NOT be represented as a sequence of frames. You should try calling putUint8Array()
directly on the DcmPixelData
element instead of inserting sequences to it.
DCMTK will change that way of encoding to the one you want to achieve directly, when you call DcmDataset::chooseRepresentation()
.
For uncompressed pixel data, it is not allowed to used the "encapsulated" pixel data encoding with sequences, and I suspect that this is why DcmDataset::chooseRepresentation()
complains about "not finding what was expected".
Upvotes: 1