/*========================================================================= medInria Copyright (c) INRIA 2013 - 2018. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =========================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include itkDataImageReaderBase::itkDataImageReaderBase() : medAbstractDataReader() { this->io = 0; } itkDataImageReaderBase::~itkDataImageReaderBase() { } bool itkDataImageReaderBase::canRead (const QString& path) { if (this->io.IsNull()) return false; // Avoid to display log of each metadata not read by itk::ImageIOBase this->io->SetGlobalWarningDisplay(false); if (!this->io->CanReadFile( path.toUtf8().constData() )) { return false; } else { // regular image readers can only read images with 4 or less // components if the pixel type is vector. images with more // will be handled by more specific image readers // (e.g. tensors if 6 or 9 components) this->io->SetFileName( path.toUtf8().constData() ); try { this->io->ReadImageInformation(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } if (this->io->GetPixelType() == itk::IOPixelEnum::VECTOR) { return this->io->GetNumberOfComponents() <= 4 ; } else { return true; } } } bool itkDataImageReaderBase::canRead (const QStringList& paths) { if (!paths.count()) return false; return this->canRead ( paths[0] ); } bool itkDataImageReaderBase::readInformation (const QString& path) { if (this->io.IsNull()) return false; this->io->SetFileName(path.toUtf8().constData()); try { this->io->ReadImageInformation(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } medAbstractData *medData = nullptr; if (this->io->GetPixelType()==itk::IOPixelEnum::SCALAR ) { const int dim = this->io->GetNumberOfDimensions(); if (!(dim>0 && dim<=4)) { qDebug() << "Unrecognized component type"; return false; } const char cdim = '0'+((dim<=3) ? 3 : 4); switch (this->io->GetComponentType()) { case itk::IOComponentEnum::UCHAR: medData = medAbstractDataFactory::instance()->create(QString("itkDataImageUChar").append(cdim)); break; case itk::IOComponentEnum::CHAR: medData = medAbstractDataFactory::instance()->create (QString("itkDataImageChar").append(cdim)); break; case itk::IOComponentEnum::USHORT: medData = medAbstractDataFactory::instance()->create (QString("itkDataImageUShort").append(cdim)); break; case itk::IOComponentEnum::SHORT: medData = medAbstractDataFactory::instance()->create (QString("itkDataImageShort").append(cdim)); break; case itk::IOComponentEnum::UINT: medData = medAbstractDataFactory::instance()->create (QString("itkDataImageUInt").append(cdim)); break; case itk::IOComponentEnum::INT: medData = medAbstractDataFactory::instance()->create (QString("itkDataImageInt").append(cdim)); break; case itk::IOComponentEnum::ULONG: medData = medAbstractDataFactory::instance()->create (QString("itkDataImageULong").append(cdim)); break; case itk::IOComponentEnum::LONG: medData = medAbstractDataFactory::instance()->create (QString("itkDataImageLong").append(cdim)); break; case itk::IOComponentEnum::FLOAT: medData = medAbstractDataFactory::instance()->create (QString("itkDataImageDouble").append(cdim)); // Bug ??? break; case itk::IOComponentEnum::DOUBLE: medData = medAbstractDataFactory::instance()->create (QString("itkDataImageDouble").append(cdim)); // Bug (added 4 which was not existing) ?? break; default: qDebug() << "Unrecognized component type"; return false; } } else if (this->io->GetPixelType()==itk::IOPixelEnum::RGB) { switch (this->io->GetComponentType()) { case itk::IOComponentEnum::UCHAR: medData = medAbstractDataFactory::instance()->create ("itkDataImageRGB3"); break; default: qDebug() << "Unrecognized component type"; return false; } } else if (this->io->GetPixelType()==itk::IOPixelEnum::VECTOR) { // Added by Theo. switch (this->io->GetComponentType()) { case itk::IOComponentEnum::UCHAR: medData = medAbstractDataFactory::instance()->create ("itkDataImageVectorUChar3"); break; case itk::IOComponentEnum::FLOAT: medData = medAbstractDataFactory::instance()->create ("itkDataImageVectorFloat3"); break; case itk::IOComponentEnum::DOUBLE: medData = medAbstractDataFactory::instance()->create ("itkDataImageVectorDouble3"); break; default: qDebug() << "Unrecognized component type"; return false; } } else if ( this->io->GetPixelType()==itk::IOPixelEnum::RGBA ) { switch (this->io->GetComponentType()) { case itk::IOComponentEnum::UCHAR: medData = medAbstractDataFactory::instance()->create ("itkDataImageRGBA3"); break; default: qDebug() << "Unrecognized component type"; return false; } } else { qDebug() << "Unsupported pixel type"; return false; } if (medData) { this->setData(medData); medData->addMetaData ("FilePath", QStringList() << path); extractMetaData(); return true; } else { return false; } } bool itkDataImageReaderBase::readInformation (const QStringList& paths) { if (!paths.count()) return false; return this->readInformation ( paths[0] ); } template bool itkDataImageReaderBase::read_image(const QString& path,const char* type) { medAbstractData* medData = dynamic_cast(this->data()); if ((medData && medData->identifier()!=type) || medData==nullptr) return false; typedef itk::Image Image; typename itk::ImageFileReader::Pointer TReader = itk::ImageFileReader::New(); TReader->SetImageIO(this->io); TReader->SetFileName(path.toUtf8().constData()); TReader->SetUseStreaming(true); TReader->Update(); typename Image::Pointer im = TReader->GetOutput(); medData->setData(im); medData->setMetaData("seriesdescription", QFileInfo(path).baseName()); return extractMetaData(); } bool itkDataImageReaderBase::extractMetaData() { itk::Object* itkImage = static_cast(data()->data()); if (itkImage) { itk::MetaDataDictionary& metaDataDictionary = itkImage->GetMetaDataDictionary(); std::vector keys = metaDataDictionary.GetKeys(); for (unsigned int i = 0; i < keys.size(); i++) { QString key = QString::fromStdString(keys[i]); std::string value; itk::ExposeMetaData(metaDataDictionary, keys[i], value); medMetaDataKeys::addKeyToChapter(key, "itk"); QString metaDataKey = medMetaDataKeys::pivot(key, "itk"); data()->setMetaData(metaDataKey, QString::fromStdString(value)); } return true; } else { return false; } } bool itkDataImageReaderBase::read(const QString& path) { if (this->io.IsNull()) return false; this->setProgress(0); if ( ! this->readInformation(path) ) return false; this->setProgress(50); /* itk::DataImageReaderCommand::Pointer command = itk::DataImageReaderCommand::New(); command->SetDCMTKDataImageReader ( this ); this->io->AddObserver ( itk::ProgressEvent(), command); */ try { if (!(read_image<3,unsigned char>(path,"itkDataImageUChar3") || read_image<3,char>(path,"itkDataImageChar3") || read_image<3,unsigned short>(path,"itkDataImageUShort3") || read_image<4,unsigned short>(path,"itkDataImageUShort4") || read_image<4,unsigned int>(path,"itkDataImageUInt4") || read_image<4,unsigned long>(path,"itkDataImageULong4") || read_image<4,unsigned char>(path,"itkDataImageUChar4") || read_image<4,char>(path,"itkDataImageChar4") || read_image<4,long>(path,"itkDataImageLong4") || read_image<4,int>(path,"itkDataImageInt4") || read_image<3,short>(path,"itkDataImageShort3") || read_image<4,short>(path,"itkDataImageShort4") || read_image<3,unsigned int>(path,"itkDataImageUInt3") || read_image<3,int>(path,"itkDataImageInt3") || read_image<3,unsigned long>(path,"itkDataImageULong3") || read_image<3,long>(path,"itkDataImageLong3") || read_image<3,float>(path,"itkDataImageFloat3") || read_image<4,float>(path,"itkDataImageFloat4") || read_image<3,double>(path,"itkDataImageDouble3") || read_image<4,double>(path,"itkDataImageDouble4") || read_image<3,itk::Vector >(path,"itkDataImageVectorUChar3") || // Added by Theo. read_image<3,itk::Vector >(path,"itkDataImageVectorFloat3") || read_image<3,itk::Vector >(path,"itkDataImageVectorDouble3") || read_image<3,itk::RGBAPixel >(path,"itkDataImageRGBA3") || read_image<3,itk::RGBPixel >(path,"itkDataImageRGB3"))) { qWarning() << "Unrecognized pixel type"; return false; } } catch (itk::ExceptionObject &e) { qWarning() << e.GetDescription(); return false; } this->setProgress (100); return true; } bool itkDataImageReaderBase::read (const QStringList& paths) { if (paths.count() < 1) return false; return this->read(paths[0]); } void itkDataImageReaderBase::setProgress (int value) { emit progressed (value); }