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);
225 CX_LOG_WARNING() <<
"Unknown pixel format: " << pixels->getRepresentation();
230 int bytesPerPixel = data->GetScalarSize() * samplesPerPixel;
232 if (pixels->getCount()!=scalarSize)
234 CX_LOG_WARNING() <<
"DicomImageReader::createVtkImageData: Mismatch in pixel counts: " << pixels->getCount() <<
" != " << scalarSize <<
" Wrong number of bytesPerPixel? = " << bytesPerPixel;
237 memcpy(data->GetScalarPointer(), pixels->getData(), pixels->getCount()*bytesPerPixel);
242 Eigen::Array3d DicomImageReader::getSpacing()
const 244 Eigen::Array3d spacing;
245 spacing[0] = this->getDouble(DCM_PixelSpacing, 0, OFTrue);
246 spacing[1] = this->getDouble(DCM_PixelSpacing, 1, OFTrue);
249 if(this->isMultiFrameImage())
251 double sliceSpacing = this->getSliceSpacing();
253 CX_LOG_WARNING() <<
"Cannot get slice spacing. Spacing set to 0. ";
255 spacing[2] = sliceSpacing;
261 bool DicomImageReader::isMultiFrameImage()
const 264 QVector<double> zPos = this->getPositions(2);
270 double DicomImageReader::calculateMultiFrameSpacing(
int frameIndex)
const 272 static QVector<double> xPos = this->getPositions(0);
273 static QVector<double> yPos = this->getPositions(1);
274 static QVector<double> zPos = this->getPositions(2);
276 if (frameIndex < 1 || frameIndex > (zPos.length()-1))
279 double dist = std::sqrt( pow(xPos[frameIndex] - xPos[frameIndex-1],2)
280 + pow(yPos[frameIndex] - yPos[frameIndex-1],2) + pow(zPos[frameIndex] - zPos[frameIndex-1],2) );
284 double DicomImageReader::getSliceSpacing()
const 286 QVector<double> zPos = this->getPositions(2);
290 double retval = calculateMultiFrameSpacing(1);
292 double tolerance = retval/10000;
294 for(
int i = 2; i < zPos.size(); ++i)
296 double dist = calculateMultiFrameSpacing(i);
297 if(!
similar(dist, retval,tolerance))
298 CX_LOG_WARNING() <<
"Distance between frame: " << i - 1 <<
" and " << i <<
" is: " 299 << dist <<
" != " <<
"Dist between frame 0 and 1: " << retval;
304 QVector<double> DicomImageReader::getPositions(
int cIndex)
const 306 QVector<double> retval;
308 DcmElement* stackElement;
309 OFCondition condition;
314 condition = mDataset->nextObject(cleanStack, OFTrue);
315 while(condition.good() && cleanStack.top()->getTag() != DCM_ImagePositionPatient);
320 stackElement =
dynamic_cast<DcmElement*
>(cleanStack.top());
322 condition = stackElement->getFloat64(val, cIndex);
332 while(condition.good());
347 Eigen::Array3i DicomImageReader::getDim(
const DicomImage& dicomImage)
const 350 dim[0] = dicomImage.getWidth();
351 dim[1] = dicomImage.getHeight();
352 dim[2] = dicomImage.getFrameCount();
358 QString rawName = this->
item()->GetElementAsString(DCM_PatientName);
359 return this->formatPatientName(rawName);
362 QString DicomImageReader::formatPatientName(QString rawName)
const 366 OFString dicomName = rawName.toStdString().c_str();
367 OFString formattedName;
368 OFString lastName, firstName, middleName, namePrefix, nameSuffix;
369 OFCondition l_error = DcmPersonName::getNameComponentsFromString(dicomName,
370 lastName, firstName, middleName, namePrefix, nameSuffix);
373 formattedName.clear();
377 if (!lastName.empty())
379 formattedName += lastName;
380 if ( !(firstName.empty() && middleName.empty()) )
382 formattedName +=
",";
385 if (!firstName.empty())
387 formattedName +=
" ";
388 formattedName += firstName;
390 if (!middleName.empty())
392 formattedName +=
" ";
393 formattedName += middleName;
395 if (!nameSuffix.empty())
397 formattedName +=
", ";
398 formattedName += nameSuffix;
400 if (!namePrefix.empty())
402 formattedName +=
" (";
403 formattedName += namePrefix;
404 formattedName +=
")";
407 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()
boost::shared_ptr< class ctkDICOMItem > ctkDICOMItemPtr
Transform3D createTransformIJC(const Vector3D &ivec, const Vector3D &jvec, const Vector3D ¢er)
QString getPatientName() const
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.