24 if (retval->loadFile(filename))
30 DicomImageReader::DicomImageReader() :
35 bool DicomImageReader::loadFile(QString filename)
38 OFCondition status = mFileFormat.loadFile(filename.toLatin1().data());
44 mDataset = mFileFormat.getDataset();
50 return this->wrapInCTK(mDataset);
53 double DicomImageReader::getDouble(
const DcmTagKey& tag,
const unsigned long pos,
const OFBool searchIntoSub)
const 57 OFCondition condition;
58 condition = mDataset->findAndGetFloat64(tag, retval, pos, searchIntoSub);
59 if (!condition.good())
61 QString tagName = this->
item()->TagDescription(tag);
62 this->error(QString(
"Failed to get tag %1/%2").arg(tagName).arg(pos));
99 retval.
center = this->getDouble(DCM_WindowCenter, 0, OFTrue);
100 retval.
width = this->getDouble(DCM_WindowWidth, 0, OFTrue);
110 OFCondition condition;
112 condition = mDataset->findAndGetOFString(DCM_ImageType, value, 2, OFTrue);
113 if (condition.good())
115 QString imageSpesialization(value.c_str());
116 if (imageSpesialization.compare(
"LOCALIZER", Qt::CaseSensitive) == 0)
124 int numberOfFrames = this->
item()->GetElementAsInteger(DCM_NumberOfFrames);
125 if (numberOfFrames==0)
127 unsigned short rows = 0;
128 unsigned short columns = 0;
129 mDataset->findAndGetUint16(DCM_Rows, rows, 0, OFTrue);
130 mDataset->findAndGetUint16(DCM_Columns, columns, 0, OFTrue);
131 if (rows*columns > 0)
134 return numberOfFrames;
143 for (
int i=0; i<3; ++i)
145 e_x[i] = this->getDouble(DCM_ImageOrientationPatient, i, OFTrue);
146 e_y[i] = this->getDouble(DCM_ImageOrientationPatient, i+3, OFTrue);
147 pos[i] = this->getDouble(DCM_ImagePositionPatient, i, OFTrue);
153 report(
"Set transform matrix to identity");
166 retval->InitializeFromItem(item);
170 void DicomImageReader::error(QString message)
const 172 reportError(QString(
"Dicom convert: [%1] in %2").arg(message).arg(mFilename));
179 DicomImage dicomImage(mFilename.toLatin1().data());
180 const DiPixel *pixels = dicomImage.getInterData();
183 this->error(
"Found no pixel data");
189 data->SetSpacing(this->getSpacing().data());
191 Eigen::Array3i dim = this->getDim(dicomImage);
192 data->SetExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1);
194 int samplesPerPixel = pixels->getPlanes();
195 int scalarSize = dim.prod() * samplesPerPixel;
196 int pixelDepth = dicomImage.getDepth();
198 switch (pixels->getRepresentation())
202 data->AllocateScalars(VTK_UNSIGNED_CHAR, samplesPerPixel);
206 data->AllocateScalars(VTK_UNSIGNED_SHORT, samplesPerPixel);
210 data->AllocateScalars(VTK_UNSIGNED_INT, samplesPerPixel);
214 data->AllocateScalars(VTK_CHAR, samplesPerPixel);
218 data->AllocateScalars(VTK_SHORT, samplesPerPixel);
222 data->AllocateScalars(VTK_INT, samplesPerPixel);
226 int bytesPerPixel = data->GetScalarSize() * samplesPerPixel;
228 memcpy(data->GetScalarPointer(), pixels->getData(), pixels->getCount()*bytesPerPixel);
229 if (pixels->getCount()!=scalarSize)
230 this->error(
"Mismatch in pixel counts");
235 Eigen::Array3d DicomImageReader::getSpacing()
const 237 Eigen::Array3d spacing;
238 spacing[0] = this->getDouble(DCM_PixelSpacing, 0, OFTrue);
239 spacing[1] = this->getDouble(DCM_PixelSpacing, 1, OFTrue);
241 double sliceThickness = this->getDouble(DCM_SliceThickness, 0, OFTrue);
242 spacing[2] = sliceThickness;
244 if(this->isMultiFrameImage())
246 double sliceSpacing = this->getSliceSpacing();
248 CX_LOG_WARNING() <<
"Cannot get slice spacing. Using slice thickness instead: " << sliceThickness;
250 spacing[2] = sliceSpacing;
260 bool DicomImageReader::isMultiFrameImage()
const 263 QVector<double> zPos = this->getZPositions();
269 double DicomImageReader::getSliceSpacing()
const 273 QVector<double> zPos = this->getZPositions();
276 retval = zPos[1] - zPos[0];
278 for(
int i = 2; i < zPos.size(); ++i)
280 double dist = zPos[i] - zPos[i-1];
282 CX_LOG_WARNING() <<
"Distance between frame: " << i <<
" and " << i+1 <<
" is: " << dist <<
" != " <<
"dist between frame 0 and 1: " << retval;
285 retval = zPos[0] - zPos[1];
289 QVector<double> DicomImageReader::getZPositions()
const 291 QVector<double> retval;
293 DcmElement* stackElement;
294 OFCondition condition;
299 condition = mDataset->nextObject(cleanStack, OFTrue);
300 while(condition.good() && cleanStack.top()->getTag() != DCM_ImagePositionPatient);
305 stackElement =
dynamic_cast<DcmElement*
>(cleanStack.top());
307 condition = stackElement->getFloat64(val, 2);
317 while(condition.good());
332 Eigen::Array3i DicomImageReader::getDim(
const DicomImage& dicomImage)
const 335 dim[0] = dicomImage.getWidth();
336 dim[1] = dicomImage.getHeight();
337 dim[2] = dicomImage.getFrameCount();
343 QString rawName = this->
item()->GetElementAsString(DCM_PatientName);
344 return this->formatPatientName(rawName);
347 QString DicomImageReader::formatPatientName(QString rawName)
const 351 OFString dicomName = rawName.toStdString().c_str();
352 OFString formattedName;
353 OFString lastName, firstName, middleName, namePrefix, nameSuffix;
354 OFCondition l_error = DcmPersonName::getNameComponentsFromString(dicomName,
355 lastName, firstName, middleName, namePrefix, nameSuffix);
358 formattedName.clear();
362 if (!lastName.empty())
364 formattedName += lastName;
365 if ( !(firstName.empty() && middleName.empty()) )
367 formattedName +=
",";
370 if (!firstName.empty())
372 formattedName +=
" ";
373 formattedName += firstName;
375 if (!middleName.empty())
377 formattedName +=
" ";
378 formattedName += middleName;
380 if (!nameSuffix.empty())
382 formattedName +=
", ";
383 formattedName += nameSuffix;
385 if (!namePrefix.empty())
387 formattedName +=
" (";
388 formattedName += namePrefix;
389 formattedName +=
")";
392 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()
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)
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
Namespace for all CustusX production code.