45 if (retval->loadFile(filename))
51 DicomImageReader::DicomImageReader() :
56 bool DicomImageReader::loadFile(QString filename)
59 OFCondition status = mFileFormat.loadFile(filename.toLatin1().data());
65 mDataset = mFileFormat.getDataset();
71 return this->wrapInCTK(mDataset);
74 double DicomImageReader::getDouble(
const DcmTagKey& tag,
const unsigned long pos,
const OFBool searchIntoSub)
const
78 OFCondition condition;
79 condition = mDataset->findAndGetFloat64(tag, retval, pos, searchIntoSub);
80 if (!condition.good())
82 QString tagName = this->
item()->TagDescription(tag);
83 this->error(QString(
"Failed to get tag %1/%2").arg(tagName).arg(pos));
120 retval.
center = this->getDouble(DCM_WindowCenter, 0, OFTrue);
121 retval.
width = this->getDouble(DCM_WindowWidth, 0, OFTrue);
131 OFCondition condition;
133 condition = mDataset->findAndGetOFString(DCM_ImageType, value, 2, OFTrue);
134 if (condition.good())
136 QString imageSpesialization(value.c_str());
137 if (imageSpesialization.compare(
"LOCALIZER", Qt::CaseSensitive) == 0)
145 int numberOfFrames = this->
item()->GetElementAsInteger(DCM_NumberOfFrames);
146 if (numberOfFrames==0)
148 unsigned short rows = 0;
149 unsigned short columns = 0;
150 mDataset->findAndGetUint16(DCM_Rows, rows, 0, OFTrue);
151 mDataset->findAndGetUint16(DCM_Columns, columns, 0, OFTrue);
152 if (rows*columns > 0)
155 return numberOfFrames;
164 for (
int i=0; i<3; ++i)
166 e_x[i] = this->getDouble(DCM_ImageOrientationPatient, i, OFTrue);
167 e_y[i] = this->getDouble(DCM_ImageOrientationPatient, i+3, OFTrue);
168 pos[i] = this->getDouble(DCM_ImagePositionPatient, i, OFTrue);
174 report(
"Set transform matrix to identity");
187 retval->InitializeFromItem(item);
191 void DicomImageReader::error(QString message)
const
193 reportError(QString(
"Dicom convert: [%1] in %2").arg(message).arg(mFilename));
200 DicomImage dicomImage(mFilename.toLatin1().data());
201 const DiPixel *pixels = dicomImage.getInterData();
204 this->error(
"Found no pixel data");
210 data->SetSpacing(this->getSpacing().data());
212 Eigen::Array3i dim = this->getDim(dicomImage);
213 data->SetExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1);
215 int samplesPerPixel = pixels->getPlanes();
216 int scalarSize = dim.prod() * samplesPerPixel;
217 int pixelDepth = dicomImage.getDepth();
219 switch (pixels->getRepresentation())
223 data->AllocateScalars(VTK_UNSIGNED_CHAR, samplesPerPixel);
227 data->AllocateScalars(VTK_UNSIGNED_SHORT, samplesPerPixel);
230 this->error(
"DICOM EPR_Uint32 not supported");
235 data->AllocateScalars(VTK_CHAR, samplesPerPixel);
239 data->AllocateScalars(VTK_SHORT, samplesPerPixel);
242 this->error(
"DICOM EPR_Sint32 not supported");
247 int bytesPerPixel = data->GetScalarSize() * samplesPerPixel;
249 memcpy(data->GetScalarPointer(), pixels->getData(), pixels->getCount()*bytesPerPixel);
250 if (pixels->getCount()!=scalarSize)
251 this->error(
"Mismatch in pixel counts");
256 Eigen::Array3d DicomImageReader::getSpacing()
const
258 Eigen::Array3d spacing;
259 spacing[0] = this->getDouble(DCM_PixelSpacing, 0, OFTrue);
260 spacing[1] = this->getDouble(DCM_PixelSpacing, 1, OFTrue);
262 double sliceThickness = this->getDouble(DCM_SliceThickness, 0, OFTrue);
263 spacing[2] = sliceThickness;
265 if(this->isMultiFrameImage())
267 double sliceSpacing = this->getSliceSpacing();
269 CX_LOG_WARNING() <<
"Cannot get slice spacing. Using slice thickness instead: " << sliceThickness;
271 spacing[2] = sliceSpacing;
281 bool DicomImageReader::isMultiFrameImage()
const
284 QVector<double> zPos = this->getZPositions();
290 double DicomImageReader::getSliceSpacing()
const
294 QVector<double> zPos = this->getZPositions();
297 retval = zPos[1] - zPos[0];
299 for(
int i = 2; i < zPos.size(); ++i)
301 double dist = zPos[i] - zPos[i-1];
303 CX_LOG_WARNING() <<
"Distance between frame: " << i <<
" and " << i+1 <<
" is: " << dist <<
" != " <<
"dist between frame 0 and 1: " << retval;
306 retval = zPos[0] - zPos[1];
310 QVector<double> DicomImageReader::getZPositions()
const
312 QVector<double> retval;
314 DcmElement* stackElement;
315 OFCondition condition;
320 condition = mDataset->nextObject(cleanStack, OFTrue);
321 while(condition.good() && cleanStack.top()->getTag() != DCM_ImagePositionPatient);
326 stackElement =
dynamic_cast<DcmElement*
>(cleanStack.top());
328 condition = stackElement->getFloat64(val, 2);
338 while(condition.good());
353 Eigen::Array3i DicomImageReader::getDim(
const DicomImage& dicomImage)
const
356 dim[0] = dicomImage.getWidth();
357 dim[1] = dicomImage.getHeight();
358 dim[2] = dicomImage.getFrameCount();
364 QString rawName = this->
item()->GetElementAsString(DCM_PatientName);
365 return this->formatPatientName(rawName);
368 QString DicomImageReader::formatPatientName(QString rawName)
const
372 OFString dicomName = rawName.toStdString().c_str();
373 OFString formattedName;
374 OFString lastName, firstName, middleName, namePrefix, nameSuffix;
375 OFCondition l_error = DcmPersonName::getNameComponentsFromString(dicomName,
376 lastName, firstName, middleName, namePrefix, nameSuffix);
379 formattedName.clear();
383 if (!lastName.empty())
385 formattedName += lastName;
386 if ( !(firstName.empty() && middleName.empty()) )
388 formattedName +=
",";
391 if (!firstName.empty())
393 formattedName +=
" ";
394 formattedName += firstName;
396 if (!middleName.empty())
398 formattedName +=
" ";
399 formattedName += middleName;
401 if (!nameSuffix.empty())
403 formattedName +=
", ";
404 formattedName += nameSuffix;
406 if (!namePrefix.empty())
408 formattedName +=
" (";
409 formattedName += namePrefix;
410 formattedName +=
")";
413 return QString(formattedName.c_str());
static DicomImageReaderPtr createFromFile(QString filename)
bool isLocalizerImage() const
void reportError(QString msg)
int getNumberOfFrames() const
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
WindowLevel getWindowLevel() const
ctkDICOMItemPtr item() const
Transform3D getImageTransformPatient() const
vtkImageDataPtr createVtkImageData()
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
Transform3D createTransformIJC(const Vector3D &ivec, const Vector3D &jvec, const Vector3D ¢er)
QString getPatientName() const
boost::shared_ptr< class ctkDICOMItem > ctkDICOMItemPtr
boost::shared_ptr< class DicomImageReader > DicomImageReaderPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
void setDeepModified(vtkImageDataPtr image)