Status ConvertDicomToLittleEndian::convert(QString inputFile, QString outputFile) { DcmFileFormat fileformat; DcmDataset *dataset = fileformat.getDataset(); OFCondition error; Status state; // Transfer Syntax del fitxer d'entrada E_TransferSyntax opt_ixfer = EXS_Unknown; E_FileReadMode opt_readMode = ERM_autoDetect; E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit; QString descriptionError; E_EncodingType opt_oenctype = EET_ExplicitLength; E_GrpLenEncoding opt_oglenc = EGL_recalcGL; E_PaddingEncoding opt_opadenc = EPD_noChange; OFCmdUnsignedInt opt_filepad = 0; OFCmdUnsignedInt opt_itempad = 0; E_FileWriteMode writeMode = EWM_fileformat; error = fileformat.loadFile(qPrintable(QDir::toNativeSeparators(inputFile)), opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); if (error.bad()) { ERROR_LOG(QString("No s'ha pogut obrir el fitxer a convertir LittleEndian %1, descripcio error: %2").arg(inputFile, error.text())); return state.setStatus(error); } dataset->loadAllDataIntoMemory(); DcmXfer opt_oxferSyn(opt_oxfer); dataset->chooseRepresentation(opt_oxfer, NULL); if (!dataset->canWriteXfer(opt_oxfer)) { descriptionError = "Error: no conversion to transfer syntax " + QString(opt_oxferSyn.getXferName()) + " possible"; state.setStatus(qPrintable(descriptionError), false, 1300); ERROR_LOG(descriptionError); return state; } error = fileformat.saveFile(qPrintable(QDir::toNativeSeparators(outputFile)), opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), writeMode); if (!error.good()) { ERROR_LOG(QString("S'ha produit un error al intentar gravar la imatge %1 convertida a LittleEndian al path %2, descripcio error: %3") .arg(inputFile, outputFile, error.text())); } return state.setStatus(error); }
//------------------------------------------------------------------------------ bool ctkDICOMRetrievePrivate::retrieve ( QString UID, RetrieveType retriveType ) { if ( !this->RetrieveDatabase ) { logger.error ( "Must have RetrieveDatabase for retrieve transaction" ); return false; } // Register the JPEG libraries in case we need them // (registration only happens once, so it's okay to call repeatedly) // register global JPEG decompression codecs DJDecoderRegistration::registerCodecs(); // register global JPEG compression codecs DJEncoderRegistration::registerCodecs(); // register RLE compression codec DcmRLEEncoderRegistration::registerCodecs(); // register RLE decompression codec DcmRLEDecoderRegistration::registerCodecs(); // Set the DCMTK log level log4cplus::Logger rootLogger = log4cplus::Logger::getRoot(); rootLogger.setLogLevel(log4cplus::DEBUG_LOG_LEVEL); // TODO: use this->SCU instead ? DcmSCU scu; scu.setAETitle ( OFString(this->CallingAETitle.toStdString().c_str()) ); scu.setPort ( this->CallingPort ); scu.setPeerAETitle ( OFString(this->CalledAETitle.toStdString().c_str()) ); scu.setPeerHostName ( OFString(this->Host.toStdString().c_str()) ); scu.setPeerPort ( this->CalledPort ); scu.setMoveDestinationAETitle ( OFString(this->MoveDestinationAETitle.toStdString().c_str()) ); logger.info ( "Setting Transfer Syntaxes" ); OFList<OFString> transferSyntaxes; transferSyntaxes.push_back ( UID_LittleEndianExplicitTransferSyntax ); transferSyntaxes.push_back ( UID_BigEndianExplicitTransferSyntax ); transferSyntaxes.push_back ( UID_LittleEndianImplicitTransferSyntax ); scu.addPresentationContext ( UID_FINDStudyRootQueryRetrieveInformationModel, transferSyntaxes ); scu.addPresentationContext ( UID_MOVEStudyRootQueryRetrieveInformationModel, transferSyntaxes ); if ( !scu.initNetwork().good() ) { logger.error ( "Error initializing the network" ); return false; } logger.debug ( "Negotiating Association" ); if ( !scu.negotiateAssociation().good() ) { logger.error ( "Error negotiating association" ); return false;; } logger.debug ( "Setting Parameters" ); // Clear the query unsigned long elements = this->parameters->card(); // Clean it out for ( unsigned long i = 0; i < elements; i++ ) { this->parameters->remove ( 0ul ); } if ( retriveType == RetrieveSeries ) { this->parameters->putAndInsertString ( DCM_QueryRetrieveLevel, "SERIES" ); this->parameters->putAndInsertString ( DCM_SeriesInstanceUID, UID.toStdString().c_str() ); } else { this->parameters->putAndInsertString ( DCM_QueryRetrieveLevel, "STUDY" ); this->parameters->putAndInsertString ( DCM_StudyInstanceUID, UID.toStdString().c_str() ); } logger.debug ( "Sending Move Request" ); MOVEResponses *responses = new MOVEResponses(); OFCondition status = scu.sendMOVERequest ( 0, this->parameters, responses ); if (!status.good()) { logger.error ( "MOVE Request failed: " + QString ( status.text() ) ); return false; } logger.debug ( "Find succeded" ); logger.debug ( "Making Output Directory" ); QDir directory = QDir( RetrieveDatabase->databaseDirectory() ); if ( responses->begin() == responses->end() ) { logger.error ( "No responses!" ); throw std::runtime_error( std::string("No responses!") ); } // Write the responses out to disk for ( OFListIterator(FINDResponse*) it = responses->begin(); it != responses->end(); it++ ) { DcmDataset *dataset = (*it)->m_dataset; if ( dataset != NULL ) { logger.debug ( "Got a valid dataset" ); // Save in correct directory E_TransferSyntax output_transfersyntax = dataset->getOriginalXfer(); dataset->chooseRepresentation( output_transfersyntax, NULL ); if ( !dataset->canWriteXfer( output_transfersyntax ) ) { // Pick EXS_LittleEndianExplicit as our default output_transfersyntax = EXS_LittleEndianExplicit; } DcmXfer opt_oxferSyn( output_transfersyntax ); if ( !dataset->chooseRepresentation( opt_oxferSyn.getXfer(), NULL ).bad() ) { DcmFileFormat* fileformat = new DcmFileFormat ( dataset ); // Follow dcmdjpeg example fileformat->loadAllDataIntoMemory(); OFString SOPInstanceUID; dataset->findAndGetOFString ( DCM_SOPInstanceUID, SOPInstanceUID ); QFileInfo fi ( directory, QString ( SOPInstanceUID.c_str() ) ); logger.debug ( "Saving file: " + fi.absoluteFilePath() ); status = fileformat->saveFile ( fi.absoluteFilePath().toStdString().c_str(), opt_oxferSyn.getXfer() ); if ( !status.good() ) { logger.error ( "Error saving file: " + fi.absoluteFilePath() + " Error is " + status.text() ); } RetrieveDatabase->insert( dataset, true ); delete fileformat; } } } delete responses; //if ( !scu.dropNetwork().good() ) //{ //logger.error ( "Error dropping the network" ); //return false; //} return true; }
//------------------------------------------------------------------------------ void ctkDICOMDatabase::insert ( DcmDataset *dataset, bool storeFile, bool generateThumbnail) { Q_D(ctkDICOMDatabase); if (!dataset) { return; } // Check to see if the file has already been loaded OFString sopInstanceUID ; dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID); QSqlQuery fileExists ( d->Database ); fileExists.prepare("SELECT InsertTimestamp,Filename FROM Images WHERE SOPInstanceUID == ?"); fileExists.bindValue(0,QString(sopInstanceUID.c_str())); fileExists.exec(); if ( fileExists.next() && QFileInfo(fileExists.value(1).toString()).lastModified() < QDateTime::fromString(fileExists.value(0).toString(),Qt::ISODate) ) { logger.debug ( "File " + fileExists.value(1).toString() + " already added" ); return; } OFString patientsName, patientID, patientsBirthDate, patientsBirthTime, patientsSex, patientComments, patientsAge; OFString studyInstanceUID, studyID, studyDate, studyTime, accessionNumber, modalitiesInStudy, institutionName, performingPhysiciansName, referringPhysician, studyDescription; OFString seriesInstanceUID, seriesDate, seriesTime, seriesDescription, bodyPartExamined, frameOfReferenceUID, contrastAgent, scanningSequence; OFString instanceNumber; Sint32 seriesNumber = 0, acquisitionNumber = 0, echoNumber = 0, temporalPosition = 0; //If the following fields can not be evaluated, cancel evaluation of the DICOM file dataset->findAndGetOFString(DCM_PatientName, patientsName); dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID); dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID); dataset->findAndGetOFString(DCM_PatientID, patientID); dataset->findAndGetOFString(DCM_PatientBirthDate, patientsBirthDate); dataset->findAndGetOFString(DCM_PatientBirthTime, patientsBirthTime); dataset->findAndGetOFString(DCM_PatientSex, patientsSex); dataset->findAndGetOFString(DCM_PatientAge, patientsAge); dataset->findAndGetOFString(DCM_PatientComments, patientComments); dataset->findAndGetOFString(DCM_StudyID, studyID); dataset->findAndGetOFString(DCM_StudyDate, studyDate); dataset->findAndGetOFString(DCM_StudyTime, studyTime); dataset->findAndGetOFString(DCM_AccessionNumber, accessionNumber); dataset->findAndGetOFString(DCM_ModalitiesInStudy, modalitiesInStudy); dataset->findAndGetOFString(DCM_InstitutionName, institutionName); dataset->findAndGetOFString(DCM_PerformingPhysicianName, performingPhysiciansName); dataset->findAndGetOFString(DCM_ReferringPhysicianName, referringPhysician); dataset->findAndGetOFString(DCM_StudyDescription, studyDescription); dataset->findAndGetOFString(DCM_SeriesDate, seriesDate); dataset->findAndGetOFString(DCM_SeriesTime, seriesTime); dataset->findAndGetOFString(DCM_SeriesDescription, seriesDescription); dataset->findAndGetOFString(DCM_BodyPartExamined, bodyPartExamined); dataset->findAndGetOFString(DCM_FrameOfReferenceUID, frameOfReferenceUID); dataset->findAndGetOFString(DCM_ContrastBolusAgent, contrastAgent); dataset->findAndGetOFString(DCM_ScanningSequence, scanningSequence); dataset->findAndGetSint32(DCM_SeriesNumber, seriesNumber); dataset->findAndGetSint32(DCM_AcquisitionNumber, acquisitionNumber); dataset->findAndGetSint32(DCM_EchoNumbers, echoNumber); dataset->findAndGetSint32(DCM_TemporalPositionIdentifier, temporalPosition); // store the file if the database is not in memomry QString filename; if ( storeFile && !this->isInMemory() ) { DcmFileFormat* fileformat = new DcmFileFormat ( dataset ); QString destinationDirectoryName = databaseDirectory() + "/dicom/"; QDir destinationDir(destinationDirectoryName); QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + seriesInstanceUID.c_str(); destinationDir.mkpath(studySeriesDirectory); filename = databaseDirectory() + "/dicom/" + pathForDataset(dataset); logger.debug ( "Saving file: " + filename ); OFCondition status = fileformat->saveFile ( filename.toAscii() ); if ( !status.good() ) { logger.error ( "Error saving file: " + filename + "\nError is " + status.text() ); delete fileformat; return; } delete fileformat; } QSqlQuery check_exists_query(d->Database); //The patient UID is a unique number within the database, generated by the sqlite autoincrement int patientUID = -1; if ( patientID != "" && patientsName != "" ) { //Check if patient is already present in the db check_exists_query.prepare ( "SELECT * FROM Patients WHERE PatientID = ? AND PatientsName = ?" ); check_exists_query.bindValue ( 0, QString ( patientID.c_str() ) ); check_exists_query.bindValue ( 1, QString ( patientsName.c_str() ) ); check_exists_query.exec(); if (check_exists_query.next()) { patientUID = check_exists_query.value(check_exists_query.record().indexOf("UID")).toInt(); } else { // Insert it QSqlQuery statement ( d->Database ); statement.prepare ( "INSERT INTO Patients ('UID', 'PatientsName', 'PatientID', 'PatientsBirthDate', 'PatientsBirthTime', 'PatientsSex', 'PatientsAge', 'PatientsComments' ) values ( NULL, ?, ?, ?, ?, ?, ?, ? )" ); statement.bindValue ( 0, QString ( patientsName.c_str() ) ); statement.bindValue ( 1, QString ( patientID.c_str() ) ); statement.bindValue ( 2, QString ( patientsBirthDate.c_str() ) ); statement.bindValue ( 3, QString ( patientsBirthTime.c_str() ) ); statement.bindValue ( 4, QString ( patientsSex.c_str() ) ); // TODO: shift patient's age to study, since this is not a patient level attribute in images // statement.bindValue ( 5, QString ( patientsAge.c_str() ) ); statement.bindValue ( 6, QString ( patientComments.c_str() ) ); statement.exec (); patientUID = statement.lastInsertId().toInt(); logger.debug ( "New patient inserted: " + QString().setNum ( patientUID ) ); } } if ( studyInstanceUID != "" ) { check_exists_query.prepare ( "SELECT * FROM Studies WHERE StudyInstanceUID = ?" ); check_exists_query.bindValue ( 0, QString ( studyInstanceUID.c_str() ) ); check_exists_query.exec(); if(!check_exists_query.next()) { QSqlQuery statement ( d->Database ); statement.prepare ( "INSERT INTO Studies ( 'StudyInstanceUID', 'PatientsUID', 'StudyID', 'StudyDate', 'StudyTime', 'AccessionNumber', 'ModalitiesInStudy', 'InstitutionName', 'ReferringPhysician', 'PerformingPhysiciansName', 'StudyDescription' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ); statement.bindValue ( 0, QString ( studyInstanceUID.c_str() ) ); statement.bindValue ( 1, patientUID ); statement.bindValue ( 2, QString ( studyID.c_str() ) ); statement.bindValue ( 3, QDate::fromString ( studyDate.c_str(), "yyyyMMdd" ) ); statement.bindValue ( 4, QString ( studyTime.c_str() ) ); statement.bindValue ( 5, QString ( accessionNumber.c_str() ) ); statement.bindValue ( 6, QString ( modalitiesInStudy.c_str() ) ); statement.bindValue ( 7, QString ( institutionName.c_str() ) ); statement.bindValue ( 8, QString ( referringPhysician.c_str() ) ); statement.bindValue ( 9, QString ( performingPhysiciansName.c_str() ) ); statement.bindValue ( 10, QString ( studyDescription.c_str() ) ); if ( !statement.exec() ) { logger.error ( "Error executing statament: " + statement.lastQuery() + " Error: " + statement.lastError().text() ); } } } if ( seriesInstanceUID != "" ) { check_exists_query.prepare ( "SELECT * FROM Series WHERE SeriesInstanceUID = ?" ); check_exists_query.bindValue ( 0, QString ( seriesInstanceUID.c_str() ) ); logger.warn ( "Statement: " + check_exists_query.lastQuery() ); check_exists_query.exec(); if(!check_exists_query.next()) { QSqlQuery statement ( d->Database ); statement.prepare ( "INSERT INTO Series ( 'SeriesInstanceUID', 'StudyInstanceUID', 'SeriesNumber', 'SeriesDate', 'SeriesTime', 'SeriesDescription', 'BodyPartExamined', 'FrameOfReferenceUID', 'AcquisitionNumber', 'ContrastAgent', 'ScanningSequence', 'EchoNumber', 'TemporalPosition' ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ); statement.bindValue ( 0, QString ( seriesInstanceUID.c_str() ) ); statement.bindValue ( 1, QString ( studyInstanceUID.c_str() ) ); statement.bindValue ( 2, static_cast<int>(seriesNumber) ); statement.bindValue ( 3, QString ( seriesDate.c_str() ) ); statement.bindValue ( 4, QDate::fromString ( seriesTime.c_str(), "yyyyMMdd" ) ); statement.bindValue ( 5, QString ( seriesDescription.c_str() ) ); statement.bindValue ( 6, QString ( bodyPartExamined.c_str() ) ); statement.bindValue ( 7, QString ( frameOfReferenceUID.c_str() ) ); statement.bindValue ( 8, static_cast<int>(acquisitionNumber) ); statement.bindValue ( 9, QString ( contrastAgent.c_str() ) ); statement.bindValue ( 10, QString ( scanningSequence.c_str() ) ); statement.bindValue ( 11, static_cast<int>(echoNumber) ); statement.bindValue ( 12, static_cast<int>(temporalPosition) ); if ( !statement.exec() ) { logger.error ( "Error executing statament: " + statement.lastQuery() + " Error: " + statement.lastError().text() ); } } } if ( !filename.isEmpty() ) { check_exists_query.prepare ( "SELECT * FROM Images WHERE Filename = ?" ); check_exists_query.bindValue ( 0, filename ); check_exists_query.exec(); if(!check_exists_query.next()) { QSqlQuery statement ( d->Database ); statement.prepare ( "INSERT INTO Images ( 'SOPInstanceUID', 'Filename', 'SeriesInstanceUID', 'InsertTimestamp' ) VALUES ( ?, ?, ?, ? )" ); statement.bindValue ( 0, QString ( sopInstanceUID.c_str() ) ); statement.bindValue ( 1, filename ); statement.bindValue ( 2, QString ( seriesInstanceUID.c_str() ) ); statement.bindValue ( 3, QDateTime::currentDateTime() ); statement.exec(); } } if(generateThumbnail){ if(d->thumbnailGenerator){ QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + QString(seriesInstanceUID.c_str()); //Create thumbnail here QString thumbnailPath = databaseDirectory() + "/thumbs/" + this->pathForDataset(dataset) + ".png"; //QString(studyInstanceUID.c_str()) + "/" + //QString(seriesInstanceUID.c_str()) + "/" + //QString(sopInstanceUID.c_str()) + ".png"; QFileInfo thumbnailInfo(thumbnailPath); if(!(thumbnailInfo.exists() && (thumbnailInfo.lastModified() > QFileInfo(filename).lastModified()))){ QDir(databaseDirectory() + "/thumbs/").mkpath(studySeriesDirectory); DicomImage dcmImage(QDir::toNativeSeparators(filename).toAscii()); d->thumbnailGenerator->generateThumbnail(&dcmImage, thumbnailPath); } } } if (isInMemory()) { emit databaseChanged(); } }
/* Helper function to write a DICOM file using C++ */ static int write_dcm_cpp(const char *path, const Image *const im, const Dcm_meta *const meta, const float max_val) { #define BUF_LEN 1024 char buf[BUF_LEN]; // Ensure the image is monochromatic if (im->nc != 1) { SIFT3D_ERR("write_dcm_cpp: image %s has %d channels. " "Currently only signle-channel images are supported.\n", path, im->nc); return SIFT3D_FAILURE; } // If no metadata was provided, initialize default metadata Dcm_meta meta_new; set_meta_defaults(meta, &meta_new); // Create a new fileformat object DcmFileFormat fileFormat; // Set the file type to derived DcmDataset *const dataset = fileFormat.getDataset(); OFCondition status = dataset->putAndInsertString(DCM_ImageType, "DERIVED"); if (status.bad()) { std::cerr << "write_dcm_cpp: Failed to set the image type" << std::endl; return SIFT3D_FAILURE; } // Set the class UID dataset->putAndInsertString(DCM_SOPClassUID, UID_CTImageStorage); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the SOPClassUID\n"); return SIFT3D_FAILURE; } // Set the photometric interpretation const char *photoInterp; if (im->nc == 1) { photoInterp = "MONOCHROME2"; } else if (im->nc == 3) { photoInterp = "RGB"; } else { SIFT3D_ERR("write_dcm_cpp: failed to determine the " "photometric representation for %d channels \n", im->nc); return SIFT3D_FAILURE; } dataset->putAndInsertString(DCM_PhotometricInterpretation, photoInterp); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the photometric " "interpretation \n"); return SIFT3D_FAILURE; } // Set the pixel representation to unsigned dataset->putAndInsertUint16(DCM_PixelRepresentation, 0); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the pixel " "representation \n"); return SIFT3D_FAILURE; } // Set the number of channels (Samples Per Pixel) and set the planar // configuration to interlaced pixels assert(SIFT3D_IM_GET_IDX(im, 0, 0, 0, 1) == SIFT3D_IM_GET_IDX(im, 0, 0, 0, 0) + 1); snprintf(buf, BUF_LEN, "%d", im->nc); dataset->putAndInsertString(DCM_SamplesPerPixel, buf); dataset->putAndInsertString(DCM_PlanarConfiguration, "0"); // Set the bits allocated and stored, in big endian format const unsigned int dcm_high_bit = dcm_bit_width - 1; dataset->putAndInsertUint16(DCM_BitsAllocated, dcm_bit_width); dataset->putAndInsertUint16(DCM_BitsStored, dcm_bit_width); dataset->putAndInsertUint16(DCM_HighBit, dcm_high_bit); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the bit widths \n"); return SIFT3D_FAILURE; } // Set the patient name status = dataset->putAndInsertString(DCM_PatientName, meta_new.patient_name); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the patient name\n"); return SIFT3D_FAILURE; } // Set the patient ID status = dataset->putAndInsertString(DCM_PatientID, meta_new.patient_id); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the patient ID \n"); return SIFT3D_FAILURE; } // Set the study UID status = dataset->putAndInsertString(DCM_StudyInstanceUID, meta_new.study_uid); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the " "StudyInstanceUID \n"); return SIFT3D_FAILURE; } // Set the series UID status = dataset->putAndInsertString(DCM_SeriesInstanceUID, meta_new.series_uid); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the " "SeriesInstanceUID \n"); return SIFT3D_FAILURE; } // Set the series description status = dataset->putAndInsertString(DCM_SeriesDescription, meta_new.series_descrip); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the series " "description \n"); return SIFT3D_FAILURE; } // Set the instance UID status = dataset->putAndInsertString(DCM_SOPInstanceUID, meta_new.instance_uid); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: failed to set the " "SOPInstanceUID \n"); return SIFT3D_FAILURE; } // Set the dimensions OFCondition xstatus = dataset->putAndInsertUint16(DCM_Rows, im->ny); OFCondition ystatus = dataset->putAndInsertUint16(DCM_Columns, im->nx); snprintf(buf, BUF_LEN, "%d", im->nz); OFCondition zstatus = dataset->putAndInsertString(DCM_NumberOfFrames, buf); if (xstatus.bad() || ystatus.bad() || zstatus.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the dimensions \n"); return SIFT3D_FAILURE; } // Set the instance number snprintf(buf, BUF_LEN, "%u", meta_new.instance_num); status = dataset->putAndInsertString(DCM_InstanceNumber, buf); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the instance " "number \n"); return SIFT3D_FAILURE; } // Set the ImagePositionPatient vector const double imPosX = static_cast<double>(im->nx - 1) * im->ux; const double imPosY = static_cast<double>(im->ny - 1) * im->uy; const double imPosZ = static_cast<double>(meta_new.instance_num) * im->uz; snprintf(buf, BUF_LEN, "%f\\%f\\%f", imPosX, imPosY, imPosZ); status = dataset->putAndInsertString(DCM_ImagePositionPatient, buf); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the " "ImagePositionPatient vector \n"); return SIFT3D_FAILURE; } // Set the slice location snprintf(buf, BUF_LEN, "%f", imPosZ); status = dataset->putAndInsertString(DCM_SliceLocation, buf); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the slice " "location \n"); return SIFT3D_FAILURE; } // Set the pixel spacing snprintf(buf, BUF_LEN, "%f\\%f", im->ux, im->uy); status = dataset->putAndInsertString(DCM_PixelSpacing, buf); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the pixel " "spacing \n"); return SIFT3D_FAILURE; } // Set the aspect ratio snprintf(buf, BUF_LEN, "%f\\%f", im->ux, im->uy); status = dataset->putAndInsertString(DCM_PixelAspectRatio, buf); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the pixel aspect " "aspect ratio \n"); return SIFT3D_FAILURE; } // Set the slice thickness snprintf(buf, BUF_LEN, "%f", im->uz); status = dataset->putAndInsertString(DCM_SliceThickness, buf); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: Failed to set the slice " "thickness \n"); return SIFT3D_FAILURE; } // Count the number of pixels in the image unsigned long numPixels = im->dims[0]; for (int i = 1; i < IM_NDIMS; i++) { numPixels *= im->dims[i]; } // Get the image scaling factor const float dcm_max_val = static_cast<float>(1 << dcm_bit_width) - 1.0f; const float im_max = max_val < 0.0f ? im_max_abs(im) : max_val; const float scale = im_max == 0.0f ? 1.0f : dcm_max_val / im_max; // Render the data to an 8-bit unsigned integer array assert(dcm_bit_width == 8); assert(fabsf(dcm_max_val - 255.0f) < FLT_EPSILON); uint8_t *pixelData = new uint8_t[numPixels]; int x, y, z, c; SIFT3D_IM_LOOP_START_C(im, x, y, z, c) const float vox = SIFT3D_IM_GET_VOX(im, x, y, z, c); if (vox < 0.0f) { SIFT3D_ERR("write_dcm_cpp: Image cannot be " "negative \n"); return SIFT3D_FAILURE; } pixelData[c + x + y * im->nx + z * im->nx * im->ny] = static_cast<uint8_t>(vox * scale); SIFT3D_IM_LOOP_END_C // Write the data status = dataset->putAndInsertUint8Array(DCM_PixelData, pixelData, numPixels); delete[] pixelData; if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: failed to set the pixel data \n"); return SIFT3D_FAILURE; } // Choose the encoding format #if 0 DJEncoderRegistration::registerCodecs(); const E_TransferSyntax xfer = EXS_JPEGProcess14SV1TransferSyntax; DJ_RPLossless rp_lossless; status = dataset->chooseRepresentation(xfer, &rp_lossless); #else const E_TransferSyntax xfer = EXS_LittleEndianExplicit; dataset->chooseRepresentation(xfer, NULL); #endif if (!dataset->canWriteXfer(xfer)) { SIFT3D_ERR("write_dcm_cpp: Failed to choose the encoding " "format \n"); return SIFT3D_FAILURE; } // Force the media storage UIDs to be re-generated by removing them dataset->remove(DCM_MediaStorageSOPClassUID); dataset->remove(DCM_MediaStorageSOPInstanceUID); // Save the file status = fileFormat.saveFile(path, xfer); if (status.bad()) { SIFT3D_ERR("write_dcm_cpp: failed to write file %s (%s) \n", path, status.text()); return SIFT3D_FAILURE; } return SIFT3D_SUCCESS; #undef BUF_LEN }
int gendicom(const char* file_name, const std::vector<float> &data, unsigned int rows, unsigned int cols) { char uid[100]; DcmFileFormat fileformat; DcmDataset *dataset = fileformat.getDataset(); OFCondition result = EC_Normal; if (result.good()) result = dataset->putAndInsertString(DCM_SOPClassUID, UID_SecondaryCaptureImageStorage); //if (result.good()) result = dataset->putAndInsertString(DCM_MediaStorageSOPClassUID, UID_SecondaryCaptureImageStorage); //same as SOP if (result.good()) result = dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT)); //if (result.good()) result = dataset->putAndInsertString(DCM_MediaStorageSOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT)); if (result.good()) result = dataset->putAndInsertString(DCM_SeriesInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT)); if (result.good()) result = dataset->putAndInsertString(DCM_StudyInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT)); //if (result.good()) result = dataset->putAndInsertString(DCM_TransferSyntaxUID, UID_LittleEndianExplicitTransferSyntax); //if (result.good()) result = dataset->putAndInsertUint16(DCM_FileMetaInformationVersion, 1); if (result.good()) result = dataset->putAndInsertString(DCM_ImageType, "DERIVED"); if (result.good()) result = dataset->putAndInsertString(DCM_Modality, "MR"); if (result.good()) result = dataset->putAndInsertString(DCM_ConversionType, "WSD"); if (result.good()) result = dataset->putAndInsertString(DCM_DerivationDescription, "IRGN Processed MR Reconstruction"); if (result.good()) result = dataset->putAndInsertString(DCM_SecondaryCaptureDeviceManufacturer, "IMT TUGRAZ"); if (result.good()) result = dataset->putAndInsertString(DCM_SecondaryCaptureDeviceManufacturerModelName, "IMT Cuda Workstation"); if (result.good()) result = dataset->putAndInsertString(DCM_PatientName, "Doe^John"); // set instance creation date and time OFString s; if (result.good()) result = DcmDate::getCurrentDate(s); if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationDate, s); if (result.good()) result = DcmTime::getCurrentTime(s); if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationTime, s); //--- Write image-data --- std::vector<Uint16> uint16_data; float val=0; float min_val; float max_val = *std::max_element(data.begin(),data.end()); for(unsigned int i=0; i<data.size(); ++i) { val = (data[i]/max_val)*65535; uint16_data.push_back(Uint16(val)); } max_val = *std::max_element(uint16_data.begin(),uint16_data.end()); min_val = *std::min_element(uint16_data.begin(),uint16_data.end()); std::cout<<"\n max-val: "<<max_val; std::cout<<"\n min-val: "<<min_val; unsigned bits=16; Uint16 bitsAllocated=((bits-1)/8+1)*8; Uint16 bitsStored=bits; Uint16 highBit=bits-1; if (result.good()) result = dataset->putAndInsertUint16(DCM_BitsAllocated, bitsAllocated); if (result.good()) result = dataset->putAndInsertUint16(DCM_BitsStored, bitsStored); if (result.good()) result = dataset->putAndInsertUint16(DCM_HighBit, highBit); if (result.good()) result = dataset->putAndInsertUint16(DCM_Rows, rows); if (result.good()) result = dataset->putAndInsertUint16(DCM_Columns, cols); if (result.good()) result = dataset->putAndInsertUint16(DCM_PixelRepresentation, 0); // 1 signed, 0 unsigned if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2"); if (result.good()) result = dataset->putAndInsertUint16(DCM_SamplesPerPixel, 1); if (result.good()) result = dataset->putAndInsertUint16(DCM_SmallestImagePixelValue, min_val); if (result.good()) result = dataset->putAndInsertUint16(DCM_LargestImagePixelValue, max_val); Uint8* pixelData = (Uint8*)&uint16_data[0]; Uint32 pixelLength; pixelLength = uint16_data.size()*2; //number of elements in vector * 2bytes (for Uint16) dataset->putAndInsertUint8Array(DCM_PixelData, pixelData, pixelLength); OFCondition status = fileformat.saveFile(file_name, EXS_LittleEndianExplicit); if (result.bad()) std::cerr << "Error: cannot write DICOM file (" << result.text() << ")" << std::endl; if (status.bad()) std::cerr << "Error: cannot write DICOM file (" << status.text() << ")" << std::endl; return 0; }
Uint16 StoreHandler::handleSTORERequest(boost::filesystem::path filename) { Uint16 statusCode = STATUS_STORE_Error_CannotUnderstand; DcmFileFormat dfile; OFCondition cond = dfile.loadFile(filename.c_str()); OFString sopuid, seriesuid, studyuid; dfile.getDataset()->findAndGetOFString(DCM_StudyInstanceUID, studyuid); dfile.getDataset()->findAndGetOFString(DCM_SeriesInstanceUID, seriesuid); dfile.getDataset()->findAndGetOFString(DCM_SOPInstanceUID, sopuid); DCMNET_INFO("StudyInstanceUID = " << studyuid); if (studyuid.length() == 0 || seriesuid.length() == 0 || sopuid.length() == 0) { DCMNET_ERROR("No SOP UID"); boost::filesystem::remove(filename); return STATUS_STORE_Refused_OutOfResources; } boost::filesystem::path newpath = config::getStoragePath(); newpath /= studyuid.c_str(); newpath /= seriesuid.c_str(); boost::filesystem::create_directories(newpath); newpath /= std::string(sopuid.c_str()) + ".dcm"; std::stringstream msg; #ifdef _WIN32 // on Windows, boost::filesystem::path is a wstring, so we need to convert to utf8 msg << "Saving file: " << newpath.string(std::codecvt_utf8<boost::filesystem::path::value_type>()); #else msg << "Saving file: " << newpath.string(); #endif DCMNET_INFO(msg.str()); DcmXfer origxfer(dfile.getDataset()->getOriginalXfer()); // if it's already compressed.. if (origxfer.getXfer() != EXS_JPEGLSLossless && origxfer.isEncapsulated()) { // uncompress dfile.getDataset()->chooseRepresentation(EXS_LittleEndianExplicit, NULL); } dfile.getDataset()->chooseRepresentation(EXS_JPEGLSLossless, NULL); if (dfile.getDataset()->canWriteXfer(EXS_JPEGLSLossless)) { dfile.getDataset()->loadAllDataIntoMemory(); if (dfile.saveFile(newpath.c_str(), EXS_JPEGLSLossless).good()) { DCMNET_INFO("Changed to JPEG LS lossless"); } else { boost::system::error_code ec; boost::filesystem::copy(filename, newpath, ec); DCMNET_INFO("Copied because wasn't able to change to JPEG LS lossless"); } } else { boost::system::error_code ec; boost::filesystem::copy(filename, newpath, ec); DCMNET_INFO("Copied"); } // tell upstream about the object and get an S3 upload info // UploadToS3(newpath, sopuid.c_str(), seriesuid.c_str(), studyuid.c_str()); // now try to add the file into the database if(!AddDICOMFileInfoToDatabase(dfile)) return STATUS_STORE_Refused_OutOfResources; statusCode = STATUS_Success; // delete the temp file boost::filesystem::remove(filename); return statusCode; }
int main(int, char ** argv) { std::string inputFolder = argv[1]; std::string outputFolder = argv[2]; std::string lookupFilename = argv[3]; // load the lookup file and read the image filenames LookupMap lookup; FilenamesType imageFilenames; readFilenames(inputFolder, imageFilenames); loadLookupFile(lookupFilename, lookup); // looop through the list of images for(unsigned int i = 0; i < imageFilenames.size(); i++) { std::string fname = imageFilenames[i]; QFileInfo finfo(QString::fromStdString(fname)); std::string basename = finfo.completeBaseName().toStdString() + ".nrrd"; FilenamesType dicomFilenames = lookup[basename]; // slice up the input image to recreate the output typedef utils::ImageVolume ImageType; ImageType::Pointer input = utils::ImageVolumeIO::Read(fname); const unsigned int slices = input->GetLargestPossibleRegion().GetSize()[2]; for(unsigned int slice = 0; slice < slices; slice++) { typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> ROIFilter; ROIFilter::Pointer roiFilter = ROIFilter::New(); roiFilter->SetInput(input); ImageType::RegionType roi = input->GetLargestPossibleRegion(); ImageType::IndexType roiIndex = roi.GetIndex(); ImageType::SizeType roiSize = roi.GetSize(); roiIndex[2] = slice; roiSize[2] = 1; roi.SetSize(roiSize); roi.SetIndex(roiIndex); roiFilter->SetRegionOfInterest(roi); roiFilter->Update(); ImageType::Pointer imSlice = roiFilter->GetOutput(); // load the dicom file std::string dicomFilename = dicomFilenames[slice]; DcmFileFormat fileFormat; fileFormat.loadFile(dicomFilename.c_str()); unsigned int numberOfPixels = imSlice->GetLargestPossibleRegion().GetNumberOfPixels(); unsigned short * buffer = new unsigned short[numberOfPixels]; fileFormat.getDataset()->putAndInsertUint16Array(DCM_PixelData, buffer, imSlice->GetLargestPossibleRegion().GetNumberOfPixels()); // reset the pixel values itk::ImageRegionConstIterator<ImageType> it(imSlice, imSlice->GetLargestPossibleRegion()); unsigned int count = 0; while(!it.IsAtEnd()) { buffer[count] = it.Get(); ++it; ++count; } fileFormat.getDataset()->putAndInsertUint16Array(DCM_PixelData, buffer, imSlice->GetLargestPossibleRegion().GetNumberOfPixels()); // create the output filename std::stringstream ss; ss << outputFolder << "/dicom_" << i << "_" << slice << ".dcm"; fileFormat.saveFile(ss.str().c_str()); } } return 0; }
OFCondition StoreHandler::handleSTORERequest(boost::filesystem::path filename) { OFCondition status = EC_IllegalParameter; DcmFileFormat dfile; OFCondition cond = dfile.loadFile(filename.c_str()); OFString sopuid, seriesuid, studyuid; dfile.getDataset()->findAndGetOFString(DCM_StudyInstanceUID, studyuid); dfile.getDataset()->findAndGetOFString(DCM_SeriesInstanceUID, seriesuid); dfile.getDataset()->findAndGetOFString(DCM_SOPInstanceUID, sopuid); if (studyuid.length() == 0) { // DEBUGLOG(sessionguid, DB_ERROR, L"No Study UID\r\n"); return status; } if (seriesuid.length() == 0) { // DEBUGLOG(sessionguid, DB_ERROR, L"No Series UID\r\n"); return status; } if (sopuid.length() == 0) { // DEBUGLOG(sessionguid, DB_ERROR, L"No SOP UID\r\n"); return status; } boost::filesystem::path newpath = config::getStoragePath(); newpath /= studyuid.c_str(); newpath /= seriesuid.c_str(); boost::filesystem::create_directories(newpath); newpath /= std::string(sopuid.c_str()) + ".dcm"; std::stringstream msg; #ifdef _WIN32 // on Windows, boost::filesystem::path is a wstring, so we need to convert to utf8 msg << "Saving file: " << newpath.string(std::codecvt_utf8<boost::filesystem::path::value_type>()); #else msg << "Saving file: " << newpath.string(); #endif DCMNET_INFO(msg.str()); dfile.getDataset()->chooseRepresentation(EXS_JPEGLSLossless, NULL); if(dfile.getDataset()->canWriteXfer(EXS_JPEGLSLossless)) { dfile.getDataset()->loadAllDataIntoMemory(); dfile.saveFile(newpath.c_str(), EXS_JPEGLSLossless); DCMNET_INFO("Changed to JPEG LS lossless"); } else { boost::filesystem::copy(filename, newpath); DCMNET_INFO("Copied"); } // now try to add the file into the database if(!AddDICOMFileInfoToDatabase(newpath)) { status = OFCondition(OFM_dcmqrdb, 1, OF_error, "Database error"); } else status = EC_Normal; // delete the temp file boost::filesystem::remove(filename); return status; }