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);
242 if(this->isMultiFrameImage())
244 double sliceSpacing = this->getSliceSpacing();
246 CX_LOG_WARNING() <<
"Cannot get slice spacing. Spacing set to 0. ";
248 spacing[2] = sliceSpacing;
254 bool DicomImageReader::isMultiFrameImage()
const
257 QVector<double> zPos = this->getPositions(2);
263 double DicomImageReader::calculateMultiFrameSpacing(
int frameIndex)
const
265 static QVector<double> xPos = this->getPositions(0);
266 static QVector<double> yPos = this->getPositions(1);
267 static QVector<double> zPos = this->getPositions(2);
269 if (frameIndex < 1 || frameIndex > (zPos.length()-1))
272 double dist = std::sqrt( pow(xPos[frameIndex] - xPos[frameIndex-1],2)
273 + pow(yPos[frameIndex] - yPos[frameIndex-1],2) + pow(zPos[frameIndex] - zPos[frameIndex-1],2) );
277 double DicomImageReader::getSliceSpacing()
const
279 QVector<double> zPos = this->getPositions(2);
283 double retval = calculateMultiFrameSpacing(1);
285 double tolerance = retval/10000;
287 for(
int i = 2; i < zPos.size(); ++i)
289 double dist = calculateMultiFrameSpacing(i);
290 if(!
similar(dist, retval,tolerance))
291 CX_LOG_WARNING() <<
"Distance between frame: " << i - 1 <<
" and " << i <<
" is: "
292 << dist <<
" != " <<
"Dist between frame 0 and 1: " << retval;
297 QVector<double> DicomImageReader::getPositions(
int cIndex)
const
299 QVector<double> retval;
301 DcmElement* stackElement;
302 OFCondition condition;
307 condition = mDataset->nextObject(cleanStack, OFTrue);
308 while(condition.good() && cleanStack.top()->getTag() != DCM_ImagePositionPatient);
313 stackElement =
dynamic_cast<DcmElement*
>(cleanStack.top());
315 condition = stackElement->getFloat64(val, cIndex);
325 while(condition.good());
340 Eigen::Array3i DicomImageReader::getDim(
const DicomImage& dicomImage)
const
343 dim[0] = dicomImage.getWidth();
344 dim[1] = dicomImage.getHeight();
345 dim[2] = dicomImage.getFrameCount();
351 QString rawName = this->
item()->GetElementAsString(DCM_PatientName);
352 return this->formatPatientName(rawName);
355 QString DicomImageReader::formatPatientName(QString rawName)
const
359 OFString dicomName = rawName.toStdString().c_str();
360 OFString formattedName;
361 OFString lastName, firstName, middleName, namePrefix, nameSuffix;
362 OFCondition l_error = DcmPersonName::getNameComponentsFromString(dicomName,
363 lastName, firstName, middleName, namePrefix, nameSuffix);
366 formattedName.clear();
370 if (!lastName.empty())
372 formattedName += lastName;
373 if ( !(firstName.empty() && middleName.empty()) )
375 formattedName +=
",";
378 if (!firstName.empty())
380 formattedName +=
" ";
381 formattedName += firstName;
383 if (!middleName.empty())
385 formattedName +=
" ";
386 formattedName += middleName;
388 if (!nameSuffix.empty())
390 formattedName +=
", ";
391 formattedName += nameSuffix;
393 if (!namePrefix.empty())
395 formattedName +=
" (";
396 formattedName += namePrefix;
397 formattedName +=
")";
400 return QString(formattedName.c_str());