|
@@ -36,6 +36,7 @@
|
|
|
|
|
|
// ctkDICOM includes
|
|
|
#include "ctkDICOMDatabase.h"
|
|
|
+#include "ctkDICOMImage.h"
|
|
|
|
|
|
#include "ctkLogger.h"
|
|
|
|
|
@@ -51,6 +52,7 @@
|
|
|
#include <dcmtk/ofstd/ofstring.h>
|
|
|
#include <dcmtk/ofstd/ofstd.h> /* for class OFStandard */
|
|
|
#include <dcmtk/dcmdata/dcddirif.h> /* for class DicomDirInterface */
|
|
|
+#include <dcmimage.h>
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
static ctkLogger logger("org.commontk.dicom.DICOMDatabase" );
|
|
@@ -221,22 +223,27 @@ void ctkDICOMDatabase::closeDatabase()
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
+/*
|
|
|
void ctkDICOMDatabase::insert ( DcmDataset *dataset ) {
|
|
|
this->insert ( dataset, QString() );
|
|
|
}
|
|
|
+*/
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
-void ctkDICOMDatabase::insert ( DcmDataset *dataset, QString filename ) {
|
|
|
+void ctkDICOMDatabase::insert ( DcmDataset *dataset, bool storeFile, bool createThumbnail ) {
|
|
|
Q_D(ctkDICOMDatabase);
|
|
|
|
|
|
// 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 FROM Images WHERE Filename == ?");
|
|
|
- fileExists.bindValue(0,filename);
|
|
|
+ fileExists.prepare("SELECT InsertTimestamp,Filename FROM Images WHERE SOPInstanceUID == ?");
|
|
|
+ fileExists.bindValue(0,QString::fromStdString(sopInstanceUID));
|
|
|
fileExists.exec();
|
|
|
- if ( fileExists.next() && QFileInfo(filename).lastModified() < QDateTime::fromString(fileExists.value(0).toString(),Qt::ISODate) )
|
|
|
+ if ( fileExists.next() && QFileInfo(fileExists.value(1).toString()).lastModified() < QDateTime::fromString(fileExists.value(0).toString(),Qt::ISODate) )
|
|
|
{
|
|
|
- logger.debug ( "File " + filename + " already added" );
|
|
|
+ logger.debug ( "File " + fileExists.value(1).toString() + " already added" );
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -249,7 +256,7 @@ void ctkDICOMDatabase::insert ( DcmDataset *dataset, QString filename ) {
|
|
|
OFString seriesInstanceUID, seriesDate, seriesTime,
|
|
|
seriesDescription, bodyPartExamined, frameOfReferenceUID,
|
|
|
contrastAgent, scanningSequence;
|
|
|
- OFString instanceNumber, sopInstanceUID ;
|
|
|
+ OFString instanceNumber;
|
|
|
|
|
|
Sint32 seriesNumber = 0, acquisitionNumber = 0, echoNumber = 0, temporalPosition = 0;
|
|
|
|
|
@@ -258,7 +265,7 @@ void ctkDICOMDatabase::insert ( DcmDataset *dataset, QString filename ) {
|
|
|
dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID);
|
|
|
dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID);
|
|
|
dataset->findAndGetOFString(DCM_PatientID, patientID);
|
|
|
- dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID);
|
|
|
+
|
|
|
|
|
|
dataset->findAndGetOFString(DCM_PatientsBirthDate, patientsBirthDate);
|
|
|
dataset->findAndGetOFString(DCM_PatientsBirthTime, patientsBirthTime);
|
|
@@ -288,6 +295,24 @@ void ctkDICOMDatabase::insert ( DcmDataset *dataset, QString filename ) {
|
|
|
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 );
|
|
|
+ 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;
|
|
@@ -393,8 +418,46 @@ void ctkDICOMDatabase::insert ( DcmDataset *dataset, QString filename ) {
|
|
|
statement.exec();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (createThumbnail)
|
|
|
+ {
|
|
|
+ QString thumbnailBaseDir = databaseDirectory() + "/thumbs/";
|
|
|
+ QString thumbnailFilename = thumbnailBaseDir + "/" + pathForDataset(dataset) + ".png";
|
|
|
+ QFileInfo thumbnailInfo(thumbnailFilename);
|
|
|
+ if ( ! ( thumbnailInfo.exists() && thumbnailInfo.lastModified() < QFileInfo(filename).lastModified() ) )
|
|
|
+ {
|
|
|
+ QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + seriesInstanceUID.c_str();
|
|
|
+ QDir(thumbnailBaseDir).mkpath(studySeriesDirectory);
|
|
|
+ // TODO: reuse dataset
|
|
|
+ DicomImage dcmtkImage(filename.toAscii());
|
|
|
+ ctkDICOMImage ctkImage(&dcmtkImage);
|
|
|
+ QImage image( ctkImage.getImage(0) );
|
|
|
+ image.scaled(128,128,Qt::KeepAspectRatio).save(thumbnailFilename,"PNG");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (d->DatabaseFileName == ":memory:")
|
|
|
{
|
|
|
emit databaseChanged();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+bool ctkDICOMDatabase::isInMemory() const
|
|
|
+{
|
|
|
+ Q_D(const ctkDICOMDatabase);
|
|
|
+ return d->DatabaseFileName == ":memory:";
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+QString ctkDICOMDatabase::pathForDataset( DcmDataset *dataset)
|
|
|
+{
|
|
|
+ Q_D(ctkDICOMDatabase);
|
|
|
+
|
|
|
+ OFString studyInstanceUID, seriesInstanceUID, sopInstanceUID;
|
|
|
+ dataset->findAndGetOFString(DCM_StudyInstanceUID, studyInstanceUID);
|
|
|
+ dataset->findAndGetOFString(DCM_SeriesInstanceUID, seriesInstanceUID);
|
|
|
+ dataset->findAndGetOFString(DCM_SOPInstanceUID, sopInstanceUID);
|
|
|
+
|
|
|
+ return QString(studyInstanceUID.c_str()) + "/" + seriesInstanceUID.c_str() + "/" + sopInstanceUID.c_str();
|
|
|
+
|
|
|
+}
|