7 #include "fwDcmtkIO/reader/ImageStorageReader.hpp" 9 #include "fwDcmtkIO/reader/main/ImageLazyStream.hpp" 10 #include "fwDcmtkIO/reader/main/ImageReader.hpp" 11 #include "fwDcmtkIO/reader/rgblookup/ImageRGBLookupLazyStream.hpp" 12 #include "fwDcmtkIO/reader/rgblookup/ImageRGBLookupReader.hpp" 14 #include <fwDataTools/helper/Array.hpp> 16 #include <fwDicomTools/Image.hpp> 17 #include <fwDicomTools/Series.hpp> 19 #include <fwMedData/ImageSeries.hpp> 21 #include <boost/assign/list_of.hpp> 22 #include <boost/assign/std/vector.hpp> 24 #include <dcmtk/config/osconfig.h> 25 #include <dcmtk/dcmdata/dcdeftag.h> 26 #include <dcmtk/dcmdata/dcfilefo.h> 27 #include <dcmtk/dcmdata/dcistrmb.h> 28 #include <dcmtk/dcmimgle/dcmimage.h> 29 #include <dcmtk/dcmnet/diutil.h> 52 ::fwMedData::DicomSeries::SOPClassUIDContainerType sopClassUIDContainer = series->getSOPClassUIDs();
53 std::string sopClassUID = dcmFindNameOfUID(sopClassUIDContainer.begin()->c_str());
56 DicomContainerType instances = series->getDicomContainer();
58 ::fwData::Image::sptr image = ::fwData::Image::New();
59 DcmFileFormat fileFormat;
64 const auto firstItem = series->getDicomContainer().begin();
65 const ::fwMemory::BufferObject::sptr bufferObj = firstItem->second;
66 const size_t buffSize = bufferObj->getSize();
67 const std::string dicomPath = bufferObj->getStreamInfo().fsFile.string();
69 char* buffer =
static_cast< char*
>( lock.
getBuffer() );
71 DcmInputBufferStream is;
72 is.setBuffer(buffer, offile_off_t(buffSize));
75 fileFormat.transferInit();
76 if (!fileFormat.read(is).good())
78 FW_RAISE(
"Unable to read Dicom file '"<< dicomPath <<
"' "<<
79 "(slice: '" << firstItem->first <<
"')");
82 fileFormat.loadAllDataIntoMemory();
83 fileFormat.transferEnd();
85 dataset = fileFormat.getDataset();
87 DicomImage dicomImage(dataset, dataset->getOriginalXfer());
89 FW_RAISE_IF(
"Unable to read the file: \""+dicomPath+
"\"", status.bad() || (
90 dicomImage.getStatus() != EIS_Normal
91 && dicomImage.getStatus() != EIS_MissingAttribute
92 && dicomImage.getStatus() != EIS_NotSupportedValue
96 dataset->chooseRepresentation(EXS_LittleEndianExplicit,
nullptr);
98 if(dicomImage.getStatus() != EIS_MissingAttribute)
100 SLM_WARN(
"Some informations are missing. The file may have not been read properly.");
105 dataset->findAndGetFloat64(DCM_PixelSpacing, spacing[0], 0);
106 dataset->findAndGetFloat64(DCM_PixelSpacing, spacing[1], 1);
107 dataset->findAndGetFloat64(DCM_SliceThickness, spacing[2]);
109 if(series->hasComputedValues(
"SliceThickness"))
111 spacing[2] = ::boost::lexical_cast<
double >(series->getComputedTagValues().at(
"SliceThickness"));
114 if(spacing[0] == 0 || spacing[1] == 0 || spacing[2] == 0)
116 spacing[0] = spacing[1] = spacing[2] = 1;
117 OSLM_WARN(
"Invalid value for pixel spacing. Assuming pixel value is 1.");
120 image->setSpacing(std::vector< double >(spacing, spacing+3));
124 double imagePosition[3];
125 dataset->findAndGetFloat64(DCM_ImagePositionPatient, imagePosition[0], 0);
126 dataset->findAndGetFloat64(DCM_ImagePositionPatient, imagePosition[1], 1);
127 dataset->findAndGetFloat64(DCM_ImagePositionPatient, imagePosition[2], 2);
128 image->setOrigin(::boost::assign::list_of(imagePosition[0])(imagePosition[1])(imagePosition[2]));
131 unsigned short rows, columns;
132 dataset->findAndGetUint16(DCM_Rows, rows);
133 dataset->findAndGetUint16(DCM_Columns, columns);
136 if(instances.size() == 1)
138 OFString sframesNumber =
"";
140 if(dataset->findAndGetOFString(DCM_NumberOfFrames, sframesNumber).good())
142 depth =
static_cast<uint32_t
>(std::stoi(sframesNumber.c_str()));
151 depth =
static_cast<unsigned short>(instances.size());
155 image->setSize(::boost::assign::list_of(columns)(rows)(depth));
158 double windowCenter = 0;
159 dataset->findAndGetFloat64(DCM_WindowCenter, windowCenter);
160 image->setWindowCenter(windowCenter);
163 double windowWidth = 0;
164 dataset->findAndGetFloat64(DCM_WindowWidth, windowWidth);
165 image->setWindowWidth(windowWidth);
169 dataset->findAndGetOFStringArray(DCM_PhotometricInterpretation, data);
170 std::string photometricInterpretation = data.c_str();
171 dataset->findAndGetOFStringArray(DCM_PixelPresentation, data);
172 std::string pixelPresentation = data.c_str();
174 if(photometricInterpretation ==
"MONOCHROME2")
176 image->setNumberOfComponents(1);
178 else if(photometricInterpretation ==
"RGB" || photometricInterpretation ==
"YBR")
180 image->setNumberOfComponents(3);
182 else if(photometricInterpretation ==
"ARGB" || photometricInterpretation ==
"CMYK")
184 image->setNumberOfComponents(4);
186 else if(photometricInterpretation ==
"PALETTE COLOR" || pixelPresentation ==
"COLOR")
188 image->setNumberOfComponents(3);
192 FW_RAISE(
"The photometric interpretation \"" << photometricInterpretation <<
"\" is not supported.");
197 double rescaleIntercept;
198 status = dataset->findAndGetFloat64(DCM_RescaleSlope, rescaleSlope);
199 rescaleSlope = (status.bad()) ? 1 : rescaleSlope;
200 status = dataset->findAndGetFloat64(DCM_RescaleIntercept, rescaleIntercept);
201 rescaleIntercept = (status.bad()) ? 0 : rescaleIntercept;
204 unsigned short samplesPerPixel = 1;
205 unsigned short bitsAllocated = 8;
206 unsigned short bitsStored = 8;
207 unsigned short highBit = 7;
208 unsigned short pixelRepresentation = 0;
210 dataset->findAndGetUint16(DCM_SamplesPerPixel, samplesPerPixel);
211 dataset->findAndGetUint16(DCM_BitsAllocated, bitsAllocated);
212 dataset->findAndGetUint16(DCM_BitsStored, bitsStored);
213 dataset->findAndGetUint16(DCM_HighBit, highBit);
214 dataset->findAndGetUint16(DCM_PixelRepresentation, pixelRepresentation);
217 if(photometricInterpretation ==
"COLOR" || photometricInterpretation ==
"PALETTE COLOR")
219 unsigned short colorBitsAllocated = 0;
220 dataset->findAndGetUint16(DCM_RedPaletteColorLookupTableDescriptor, colorBitsAllocated, 2);
221 bitsStored = bitsAllocated = colorBitsAllocated;
222 highBit =
static_cast<unsigned short>(colorBitsAllocated-1);
227 samplesPerPixel, bitsAllocated, bitsStored, highBit, pixelRepresentation, rescaleSlope, rescaleIntercept);
231 image->setType(imageType);
236 SLM_INFO(
"Reading using DIRECT mode.");
239 if(photometricInterpretation !=
"PALETTE COLOR" && pixelPresentation !=
"COLOR")
241 this->
directRead(image, instances, rows, columns, depth, rescaleSlope, rescaleIntercept,
242 pixelRepresentation, imageType);
247 this->
directRGBLookupRead(image, *dataset, instances, rows, columns, depth, bitsAllocated);
254 SLM_INFO(
"Reading using LAZY mode.");
257 if(photometricInterpretation !=
"PALETTE COLOR" && pixelPresentation !=
"COLOR")
259 this->
lazyRead(image, series, rows, columns, depth, rescaleSlope, rescaleIntercept, pixelRepresentation,
265 this->
lazyRGBLookupRead(image, series, *dataset, instances, rows, columns, depth, bitsAllocated, imageType);
270 imageSeries->setImage(image);
278 DicomContainerType instances,
279 unsigned short rows,
unsigned short columns,
280 int depth,
double rescaleSlope,
281 double rescaleIntercept,
282 unsigned short pixelRepresentation,
287 ::fwData::Array::sptr array = image->getDataArray();
292 arrayHelper.
getBuffer(), rescaleSlope, rescaleIntercept, pixelRepresentation,
300 DicomContainerType instances,
301 unsigned short rows,
unsigned short columns,
302 int depth,
unsigned short bitsAllocated)
306 ::fwData::Array::sptr array = image->getDataArray();
309 unsigned short pixelValueBitsAllocated = 8;
310 dataset.findAndGetUint16(DCM_BitsAllocated, pixelValueBitsAllocated);
313 if(bitsAllocated == 16)
315 const Uint16* redLookup;
316 const Uint16* greenLookup;
317 const Uint16* blueLookup;
319 dataset.findAndGetUint16Array(DCM_RedPaletteColorLookupTableData, redLookup);
320 dataset.findAndGetUint16Array(DCM_GreenPaletteColorLookupTableData, greenLookup);
321 dataset.findAndGetUint16Array(DCM_BluePaletteColorLookupTableData, blueLookup);
323 if(pixelValueBitsAllocated == 16)
325 ::fwDcmtkIO::reader::rgblookup::ImageRGBLookupReader::fillImageBuffer<Uint16, Uint16>(rows,
328 arrayHelper.
getBuffer(), redLookup, greenLookup,
333 ::fwDcmtkIO::reader::rgblookup::ImageRGBLookupReader::fillImageBuffer<Uint16, Uint8>(rows,
336 arrayHelper.
getBuffer(), redLookup, greenLookup,
343 const Uint8* redLookup;
344 const Uint8* greenLookup;
345 const Uint8* blueLookup;
347 dataset.findAndGetUint8Array(DCM_RedPaletteColorLookupTableData, redLookup);
348 dataset.findAndGetUint8Array(DCM_GreenPaletteColorLookupTableData, greenLookup);
349 dataset.findAndGetUint8Array(DCM_BluePaletteColorLookupTableData, blueLookup);
351 if(pixelValueBitsAllocated == 16)
353 ::fwDcmtkIO::reader::rgblookup::ImageRGBLookupReader::fillImageBuffer<Uint8, Uint16>(rows,
356 arrayHelper.
getBuffer(), redLookup, greenLookup,
361 ::fwDcmtkIO::reader::rgblookup::ImageRGBLookupReader::fillImageBuffer<Uint8, Uint8>(rows,
364 arrayHelper.
getBuffer(), redLookup, greenLookup,
373 const ::fwMedData::DicomSeries::csptr& series,
374 unsigned short rows,
unsigned short columns,
375 int depth,
double rescaleSlope,
376 double rescaleIntercept,
377 unsigned short pixelRepresentation,
381 ::fwDcmtkIO::reader::main::ImageLazyInformation::sptr dcmInfo =
382 std::make_shared< ::fwDcmtkIO::reader::main::ImageLazyInformation >();
383 dcmInfo->m_dicomSeries = series;
384 dcmInfo->m_rows = rows;
385 dcmInfo->m_columns = columns;
386 dcmInfo->m_depth = depth;
387 dcmInfo->m_rescaleSlope = rescaleSlope;
388 dcmInfo->m_rescaleIntercept = rescaleIntercept;
389 dcmInfo->m_pixelRepresentation = pixelRepresentation;
390 dcmInfo->m_imageType = imageType;
393 ::fwMemory::BufferObject::sptr buffObj = image->getDataArray()->getBufferObject();
394 buffObj->setIStreamFactory(
395 std::make_shared< ::fwDcmtkIO::reader::main::ImageLazyStream >( dcmInfo ),
396 image->getSizeInBytes() );
402 const ::fwMedData::DicomSeries::csptr& series,
404 DicomContainerType instances,
405 unsigned short rows,
unsigned short columns,
406 int depth,
unsigned short bitsAllocated,
409 unsigned short pixelValueBitsAllocated = 8;
410 dataset.findAndGetUint16(DCM_BitsAllocated, pixelValueBitsAllocated);
413 ::fwDcmtkIO::reader::rgblookup::ImageRGBLookupLazyInformation::sptr dcmInfo =
414 std::make_shared< ::fwDcmtkIO::reader::rgblookup::ImageRGBLookupLazyInformation >();
415 dcmInfo->m_dicomSeries = series;
416 dcmInfo->m_rows = rows;
417 dcmInfo->m_columns = columns;
418 dcmInfo->m_depth = depth;
419 dcmInfo->m_bitsAllocated = bitsAllocated;
420 dcmInfo->m_pixelValueBitsAllocated = pixelValueBitsAllocated;
421 dcmInfo->m_imageType = imageType;
424 ::fwMemory::BufferObject::sptr buffObj = image->getDataArray()->getBufferObject();
425 buffObj->setIStreamFactory(
426 std::make_shared< ::fwDcmtkIO::reader::rgblookup::ImageRGBLookupLazyStream >( dcmInfo ),
427 image->getSizeInBytes() );
static FWMEMORY_API BufferManager::sptr getDefault()
Returns the current BufferManager instance.
base class for BufferObject Lock
#define SLM_WARN(message)
static void fillImageBuffer(unsigned int rows, unsigned int columns, unsigned int depth, DicomContainerType &instances, void *destination, double rescaleSlope, double rescaleIntercept, unsigned short pixelRepresentation,::fwTools::Type imageType)
Fill the buffer of an image.
LockBase< T >::BufferType getBuffer() const
Returns BufferObject's buffer pointer.
#define OSLM_WARN(message)
virtual FWDCMTKIO_API::fwMedData::Series::sptr read(const ::fwMedData::DicomSeries::csptr &series)
Override.
FWDCMTKIO_API void lazyRGBLookupRead(const ::fwData::Image::sptr &image, const ::fwMedData::DicomSeries::csptr &series, DcmDataset &dataset, DicomContainerType instances, unsigned short rows, unsigned short columns, int depth, unsigned short bitsAllocated,::fwTools::Type imageType)
Read an image using lazy mode and perform a RGB lookup.
fwDcmtkIO contains classes used to pull Dicom images from a pacs using dcmtk library.
virtual FWDCMTKIO_API ~ImageStorageReader()
Destructor.
FWDCMTKIO_API void directRead(const ::fwData::Image::sptr &image, DicomContainerType instances, unsigned short rows, unsigned short columns, int depth, double rescaleSlope, double rescaleIntercept, unsigned short pixelRepresentation,::fwTools::Type imageType)
Read an image using direct mode.
#define SLM_INFO(message)
FWDCMTKIO_API void directRGBLookupRead(const ::fwData::Image::sptr &image, DcmDataset &dataset, DicomContainerType instances, unsigned short rows, unsigned short columns, int depth, unsigned short bitsAllocated)
Read an image using direct mode and perform a RGB lookup.
FWDCMTKIO_API ImageStorageReader()
Constructor.
FWDCMTKIO_API void lazyRead(const ::fwData::Image::sptr &image, const ::fwMedData::DicomSeries::csptr &series, unsigned short rows, unsigned short columns, int depth, double rescaleSlope, double rescaleIntercept, unsigned short pixelRepresentation,::fwTools::Type imageType)
Read an image using lazy mode.