Volume* VolumeBuilderFromCaptures::build() { Q_ASSERT(m_parentStudy); Q_ASSERT(m_vtkImageAppend->GetNumberOfInputs()); // Creem la nova sèrie Series *newSeries = new Series(); // Omplim la informació de la sèrie a partir de la sèrie de referència // Assignem la modalitat segons el valor introduit. El valor per defecte és 'OT' (Other). newSeries->setModality(m_modality); newSeries->setSOPClassUID(QString(UID_SecondaryCaptureImageStorage)); // Generem el SeriesInstanceUID a partir del generador de DCMTK. \TODO Utilitzar el nostre UID_ROOT? char seriesUid[100]; dcmGenerateUniqueIdentifier(seriesUid, SITE_SERIES_UID_ROOT); newSeries->setInstanceUID(QString(seriesUid)); // \TODO Quin criteri volem seguir per donar nous noms? newSeries->setSeriesNumber(QString("0000") + QString::number(m_parentStudy->getSeries().count())); newSeries->setDescription(this->getSeriesDescription()); // Assignem la sèrie a l'estudi al qual partenyia l'inputVolume. newSeries->setParentStudy(m_parentStudy); m_parentStudy->addSeries(newSeries); // Obtenim el nou vtkImageData a partir de la sortida del vtkImageAppend. // Fem un flip horitzontal per tal utilitzar el mateix sistema de coordenades que DICOM. m_vtkImageAppend->Update(); vtkSmartPointer<vtkImageData> newVtkData = vtkSmartPointer<vtkImageData>::New(); newVtkData->ShallowCopy(m_vtkImageAppend->GetOutput()); // Creem el nou volume Volume *newVolume = new Volume(); newSeries->addVolume(newVolume); // Generem les noves imatges a partir del vtkData generat per vtkImageAppend int samplesPerPixel = newVtkData->GetNumberOfScalarComponents(); int bitsAllocated; int bitsStored; int highBit; int pixelRepresentation; int rows; int columns; // \TODO Potser podriem ser mes precisos QString photometricInterpretation; if (samplesPerPixel == 1) { photometricInterpretation = QString("MONOCHROME2"); } else if (samplesPerPixel == 3) { photometricInterpretation = QString("RGB"); } int scalarType = newVtkData->GetScalarType(); switch (scalarType) { //case VTK_CHAR: //break; case VTK_SIGNED_CHAR: bitsAllocated = 8; pixelRepresentation = 1; break; case VTK_UNSIGNED_CHAR: bitsAllocated = 8; pixelRepresentation = 0; break; case VTK_SHORT: bitsAllocated = 16; pixelRepresentation = 1; break; case VTK_UNSIGNED_SHORT: bitsAllocated = 16; pixelRepresentation = 0; break; case VTK_INT: bitsAllocated = 32; pixelRepresentation = 1; break; case VTK_UNSIGNED_INT: bitsAllocated = 32; pixelRepresentation = 0; break; // case VTK_FLOAT: // bitsAllocated = 32; // pixelRepresentation = 1; ? // break; // case VTK_DOUBLE: // bitsAllocated = 64; // pixelRepresentation = 1; ? // break; default: DEBUG_LOG(QString("Pixel Type no suportat: ") + newVtkData->GetScalarTypeAsString()); } bitsStored = bitsAllocated; highBit = bitsStored - 1; int *dimensions = newVtkData->GetDimensions(); double *spacing = newVtkData->GetSpacing(); rows = dimensions[1]; columns = dimensions[0]; Image *currentImage; for (int i = 0; i < dimensions[2]; i++) { currentImage = new Image(); // Generem el SOPInstanceUID a partir del generador de DCMTK. \TODO Utilitzar el nostre UID_ROOT? char instanceUid[100]; dcmGenerateUniqueIdentifier(instanceUid, SITE_INSTANCE_UID_ROOT); currentImage->setSOPInstanceUID(QString(instanceUid)); newSeries->addImage(currentImage); newVolume->addImage(currentImage); currentImage->setParentSeries(newSeries); currentImage->setOrderNumberInVolume(i); currentImage->setVolumeNumberInSeries(0); currentImage->setBitsAllocated(bitsAllocated); currentImage->setBitsStored(bitsStored); currentImage->setHighBit(highBit); currentImage->setColumns(columns); currentImage->setInstanceNumber(QString::number(i + 1)); currentImage->setPhotometricInterpretation(photometricInterpretation); currentImage->setPixelRepresentation(pixelRepresentation); currentImage->setPixelSpacing(spacing[0], spacing[1]); currentImage->setRows(rows); currentImage->setSamplesPerPixel(samplesPerPixel); } // Es fa després d'haver inserit les imatges perquè el nou Volume activi el flag de dades carregades. newVolume->setData(newVtkData); newVolume->setNumberOfPhases(1); newVolume->setNumberOfSlicesPerPhase(newSeries->getImages().count()); // Informació de DEBUG DEBUG_LOG(QString("\nNova sèrie generada:") + QString("\n SeriesInstanceUID: ") + newSeries->getInstanceUID() + QString("\n SeriesNumber: ") + newSeries->getSeriesNumber() + QString("\n SeriesDescription: ") + newSeries->getDescription() + QString("\n SOPClassUID: ") + newSeries->getSOPClassUID() + QString("\n Modality: ") + newSeries->getModality() + QString("\n SamplesPerPixel: ") + QString::number(samplesPerPixel) + QString("\n PhotometricInterpretation: ") + photometricInterpretation + QString("\n BitsAllocated: ") + QString::number(bitsAllocated) + QString("\n BitsStored: ") + QString::number(bitsStored) + QString("\n HighBit: ") + QString::number(highBit) + QString("\n PixelRepresentation: ") + QString::number(pixelRepresentation) + QString("\n PixelSpacing: ") + QString::number(spacing[0]) + QString(",") + QString::number(spacing[1]) + QString("\n Num.Imatges: ") + QString::number(newSeries->getImages().count())); return newVolume; }
/** * \author Jules Gorny - ALCoV team, ISIT, UMR 6284 UdA – CNRS **/ void fillPatientFromXMLFile(Patient &pat, QString xmlPath, Ui::MainWindow *ui) { addProgressMessage(ui,"Retrieving data from database...\n", Qt::black, "", false); QString tab = " "; QFile f(xmlPath); if(!f.open(QIODevice::ReadOnly)) addProgressMessage(ui,"Can't read the existing database.\n", Qt::red, "", true); QTextStream in(&f); Image* img = NULL; Study* study = NULL; Series* series = NULL; Extract* extr = NULL; File* file = NULL; while(!in.atEnd()) { QString line = in.readLine(); if( line.endsWith(">") && !line.contains("</") ) { //Image if( line.startsWith(tab + "<") ) { if( line.contains("<Property") ) { QString tag, tagName, value; int start = line.indexOf("tag=")+5, end = line.indexOf("\"", start); tag = line.mid(start, end-start); start = line.indexOf("tagName=")+9; end = line.indexOf("\"", start); tagName = line.mid(start, end-start); start = line.indexOf("value=")+7; end = line.indexOf("\"", start); value = line.mid(start, end-start); Property prop(tag, tagName, value); pat.addProperty(prop); } else { line = line.trimmed(); int start = line.indexOf("<")+1, end = line.lastIndexOf(">"); QString imgType = line.mid(start, end-start); img = new Image(imgType); pat.addImage(img); } } //Study else if( line.startsWith(tab + tab + "<") ) { line = line.trimmed(); study = new Study(); int start = line.indexOf("\"")+1, end = line.lastIndexOf("\""); QString descr = line.mid(start, end-start); study->setDescription(descr); img->addStudy(study); } //Series else if( line.startsWith(tab + tab + tab + "<") ) { if( line.contains("<Property") ) { QString tag, tagName, value; int start = line.indexOf("tag=")+5, end = line.indexOf("\"", start); tag = line.mid(start, end-start); start = line.indexOf("tagName=")+9; end = line.indexOf("\"", start); tagName = line.mid(start, end-start); start = line.indexOf("value=")+7; end = line.indexOf("\"", start); value = line.mid(start, end-start); Property prop(tag, tagName, value); study->addProperty(prop); } else if( line.contains("<Series") ) { line = line.trimmed(); series = new Series(); int start = line.indexOf("\"")+1, end = line.lastIndexOf("\""); QString descr = line.mid(start, end-start); series->setDescription(descr); study->addSeries(series); } } //Extract else if( line.startsWith(tab + tab + tab + tab + "<") ) { if( line.contains("<Property") ) { QString tag, tagName, value; int start = line.indexOf("tag=")+5, end = line.indexOf("\"", start); tag = line.mid(start, end-start); start = line.indexOf("tagName=")+9; end = line.indexOf("\"", start); tagName = line.mid(start, end-start); start = line.indexOf("value=")+7; end = line.indexOf("\"", start); value = line.mid(start, end-start); Property prop(tag, tagName, value); series->addProperty(prop); } else if( line.contains("<Extract") ) { line = line.trimmed(); int start = line.indexOf("\"")+1, end = line.lastIndexOf("\""); extr = new Extract(line.mid(start, end-start).toInt()); series->addExtract(extr); } } //File or Property (from Extract) else if( line.startsWith(tab + tab + tab + tab + tab + "<") ) { if( line.contains("<Property") ) { QString tag, tagName, value; int start = line.indexOf("tag=")+5, end = line.indexOf("\"", start); tag = line.mid(start, end-start); start = line.indexOf("tagName=")+9; end = line.indexOf("\"", start); tagName = line.mid(start, end-start); start = line.indexOf("value=")+7; end = line.indexOf("\"", start); value = line.mid(start, end-start); Property prop(tag, tagName, value); extr->addProperty(prop); } else if( line.contains("<File") ) { line = line.trimmed(); int start = line.indexOf("\"")+1, end = line.lastIndexOf("\""); QString location = line.mid(start, end-start); file = new File(location); extr->addFile(file); } } //Property else if( line.startsWith(tab + tab + tab + tab + tab + tab + "<") ) { line = line.trimmed(); QString tag, tagName, value; int start = line.indexOf("tag=")+5, end = line.indexOf("\"", start); tag = line.mid(start, end-start); start = line.indexOf("tagName=")+9; end = line.indexOf("\"", start); tagName = line.mid(start, end-start); start = line.indexOf("value=")+7; end = line.indexOf("\"", start); value = line.mid(start, end-start); Property prop(tag, tagName, value); file->addProperty(prop); } } } f.close(); }