Selaa lähdekoodia

Add thumbnail generator classes and re-implement thumbnail generation in ctkDICOMDatabase

nherlambang 14 vuotta sitten
vanhempi
commit
2aaccd7804

+ 3 - 0
Libs/DICOM/Core/CMakeLists.txt

@@ -27,6 +27,8 @@ SET(KIT_SRCS
   ctkDICOMRetrieve.h
   ctkDICOMTester.cpp
   ctkDICOMTester.h
+  ctkDICOMAbstractThumbnailGenerator.cpp
+  ctkDICOMAbstractThumbnailGenerator.h
 )
 
 IF(CTK_WRAP_PYTHONQT_LIGHT)
@@ -49,6 +51,7 @@ SET(KIT_MOC_SRCS
   ctkDICOMQuery.h
   ctkDICOMRetrieve.h
   ctkDICOMTester.h
+  ctkDICOMAbstractThumbnailGenerator.h
   )
 
 IF(CTK_WRAP_PYTHONQT_LIGHT)

+ 4 - 2
Libs/DICOM/Core/Testing/Cpp/ctkDICOMDatabaseTest1.cpp

@@ -85,8 +85,10 @@ int ctkDICOMDatabaseTest1( int argc, char * argv [] )
 
   // check if it doesn't crash
   database.pathForDataset(0);
-  database.insert(0, true);
-  database.insert(0, false);
+  database.insert(0, true, true);
+  database.insert(0, true, false);
+  database.insert(0, false, true);
+  database.insert(0, false, false);
 
   database.closeDatabase();
   database.initializeDatabase();

+ 64 - 0
Libs/DICOM/Core/ctkDICOMAbstractThumbnailGenerator.cpp

@@ -0,0 +1,64 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// ctkDICOMCore includes
+#include "ctkDICOMAbstractThumbnailGenerator.h"
+#include "ctkLogger.h"
+
+static ctkLogger logger ( "org.commontk.dicom.DICOMAbstractThumbnailGenerator" );
+struct Node;
+
+//------------------------------------------------------------------------------
+class ctkDICOMAbstractThumbnailGeneratorPrivate
+{
+  Q_DECLARE_PUBLIC(ctkDICOMAbstractThumbnailGenerator);
+protected:
+  ctkDICOMAbstractThumbnailGenerator* const q_ptr;
+
+public:
+  ctkDICOMAbstractThumbnailGeneratorPrivate(ctkDICOMAbstractThumbnailGenerator&);
+  virtual ~ctkDICOMAbstractThumbnailGeneratorPrivate();
+};
+
+//------------------------------------------------------------------------------
+ctkDICOMAbstractThumbnailGeneratorPrivate::ctkDICOMAbstractThumbnailGeneratorPrivate(ctkDICOMAbstractThumbnailGenerator& o):q_ptr(&o)
+{
+
+}
+
+//------------------------------------------------------------------------------
+ctkDICOMAbstractThumbnailGeneratorPrivate::~ctkDICOMAbstractThumbnailGeneratorPrivate()
+{
+
+}
+
+
+//------------------------------------------------------------------------------
+ctkDICOMAbstractThumbnailGenerator::ctkDICOMAbstractThumbnailGenerator(QObject* parentValue)
+  : d_ptr(new ctkDICOMAbstractThumbnailGeneratorPrivate(*this))
+{
+
+}
+
+//------------------------------------------------------------------------------
+ctkDICOMAbstractThumbnailGenerator::~ctkDICOMAbstractThumbnailGenerator()
+{
+}

+ 55 - 0
Libs/DICOM/Core/ctkDICOMAbstractThumbnailGenerator.h

@@ -0,0 +1,55 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkDICOMAbstractThumbnailGenerator_h
+#define __ctkDICOMAbstractThumbnailGenerator_h
+
+// Qt includes
+#include <QObject>
+
+#include "ctkDICOMCoreExport.h"
+
+class ctkDICOMAbstractThumbnailGeneratorPrivate;
+class DicomImage;
+
+/**
+  \brief Abstract thumbnail generator class
+*/
+class CTK_DICOM_CORE_EXPORT ctkDICOMAbstractThumbnailGenerator : public QObject
+{
+  Q_OBJECT
+public:
+  /** \brief Construct a ctkDICOMAbstractThumbnailGenerator object
+  */
+  explicit ctkDICOMAbstractThumbnailGenerator(QObject* parent = 0);
+  virtual ~ctkDICOMAbstractThumbnailGenerator();
+
+  virtual bool generateThumbnail(DicomImage* dcmImage, const QString& path ){return false;}
+
+protected:
+  QScopedPointer<ctkDICOMAbstractThumbnailGeneratorPrivate> d_ptr;
+
+private:
+  Q_DECLARE_PRIVATE(ctkDICOMAbstractThumbnailGenerator);
+  Q_DISABLE_COPY(ctkDICOMAbstractThumbnailGenerator);
+};
+
+#endif

+ 29 - 2
Libs/DICOM/Core/ctkDICOMDatabase.cpp

@@ -36,6 +36,7 @@
 
 // ctkDICOM includes
 #include "ctkDICOMDatabase.h"
+#include "ctkDICOMAbstractThumbnailGenerator.h"
 
 #include "ctkLogger.h"
 
@@ -80,6 +81,8 @@ public:
   QString      LastError;
   QSqlDatabase Database;
   QMap<QString, QString> LoadedHeader;
+
+  ctkDICOMAbstractThumbnailGenerator* thumbnailGenerator;
 };
 
 //------------------------------------------------------------------------------
@@ -88,7 +91,7 @@ public:
 //------------------------------------------------------------------------------
 ctkDICOMDatabasePrivate::ctkDICOMDatabasePrivate(ctkDICOMDatabase& o): q_ptr(&o)
 {
-
+    this->thumbnailGenerator = NULL;
 }
 
 //------------------------------------------------------------------------------
@@ -198,6 +201,16 @@ const QSqlDatabase& ctkDICOMDatabase::database() const {
   return d->Database;
 }
 
+void ctkDICOMDatabase::setThumbnailGenerator(ctkDICOMAbstractThumbnailGenerator *generator){
+    Q_D(ctkDICOMDatabase);
+    d->thumbnailGenerator = generator;
+}
+
+ctkDICOMAbstractThumbnailGenerator* ctkDICOMDatabase::thumbnailGenerator(){
+    Q_D(const ctkDICOMDatabase);
+    return d->thumbnailGenerator;
+}
+
 //------------------------------------------------------------------------------
 bool ctkDICOMDatabasePrivate::executeScript(const QString script) {
   QFile scriptFile(script);
@@ -361,7 +374,7 @@ void ctkDICOMDatabase::insert ( DcmDataset *dataset ) {
 */
 
 //------------------------------------------------------------------------------
-void ctkDICOMDatabase::insert ( DcmDataset *dataset, bool storeFile)
+void ctkDICOMDatabase::insert ( DcmDataset *dataset, bool storeFile, bool generateThumbnail)
 {
   Q_D(ctkDICOMDatabase);
 
@@ -561,6 +574,20 @@ void ctkDICOMDatabase::insert ( DcmDataset *dataset, bool storeFile)
       }
     }
 
+  if(generateThumbnail){
+      if(d->thumbnailGenerator){
+        DicomImage dcmImage(filename.toAscii());
+        QString studySeriesDirectory = QString(studyInstanceUID.c_str()) + "/" + QString(seriesInstanceUID.c_str());
+        //Create thumbnail here
+        QDir(databaseDirectory() + "/thumbs/").mkpath(studySeriesDirectory);
+        QString thumbnailPath = databaseDirectory() +
+                                "/thumbs/" + QString(studyInstanceUID.c_str()) + "/" +
+                                QString(seriesInstanceUID.c_str()) + "/" +
+                                QString(sopInstanceUID.c_str()) + ".png";
+        d->thumbnailGenerator->generateThumbnail(&dcmImage, thumbnailPath);
+      }
+  }
+
   if (d->DatabaseFileName == ":memory:")
     {
       emit databaseChanged();

+ 9 - 1
Libs/DICOM/Core/ctkDICOMDatabase.h

@@ -30,6 +30,7 @@
 
 class ctkDICOMDatabasePrivate;
 class DcmDataset;
+class ctkDICOMAbstractThumbnailGenerator;
 
 class CTK_DICOM_CORE_EXPORT ctkDICOMDatabase : public QObject
 {
@@ -46,6 +47,13 @@ public:
   bool isInMemory() const;
 
   ///
+  /// set thumbnail generator object
+  void setThumbnailGenerator(ctkDICOMAbstractThumbnailGenerator* generator);
+  ///
+  /// get thumbnail genrator object
+  ctkDICOMAbstractThumbnailGenerator* thumbnailGenerator();
+
+  ///
   /// open the SQLite database in @param databaseFile . If the file does not
   /// exist, a new database is created and initialized with the
   /// default schema
@@ -81,7 +89,7 @@ public:
   /**
    * Insert into the database if not already exsting.
    */
-  void insert ( DcmDataset *dataset, bool storeFile = true);
+  void insert ( DcmDataset *dataset, bool storeFile = true, bool generateThumbnail = true);
   /***
     * Helper method: get the path that should be used to store this  image.
     */

+ 2 - 2
Libs/DICOM/Core/ctkDICOMQuery.cpp

@@ -362,7 +362,7 @@ bool ctkDICOMQuery::query(ctkDICOMDatabase& database )
     DcmDataset *dataset = (*it)->m_dataset;
     if ( dataset != NULL )
       {
-      database.insert ( dataset, false);
+      database.insert ( dataset, false, false);
       OFString StudyInstanceUID;
       dataset->findAndGetOFString ( DCM_StudyInstanceUID, StudyInstanceUID );
       d->addStudyInstanceUID ( QString ( StudyInstanceUID.c_str() ) );
@@ -390,7 +390,7 @@ bool ctkDICOMQuery::query(ctkDICOMDatabase& database )
         DcmDataset *dataset = (*it)->m_dataset;
         if ( dataset != NULL )
           {
-          database.insert ( dataset, false);
+          database.insert ( dataset, false, false);
           }
         }
       logger.debug ( "Find succeded for Series: " + StudyInstanceUID );

+ 3 - 0
Libs/DICOM/Widgets/CMakeLists.txt

@@ -31,6 +31,8 @@ SET(KIT_SRCS
   ctkDICOMThumbnailListWidget.h
   ctkDICOMImportWidget.cpp
   ctkDICOMImportWidget.h
+  ctkDICOMThumbnailGenerator.cpp
+  ctkDICOMThumbnailGenerator.h
   )
 
 IF(CTK_WRAP_PYTHONQT_LIGHT)
@@ -54,6 +56,7 @@ SET(KIT_MOC_SRCS
   ctkDICOMThumbnailListWidget.h
   ctkDICOMImportWidget.h
   ctkDICOMQueryRetrieveWidget.h
+  ctkDICOMThumbnailGenerator.h
   )
 
 IF(CTK_WRAP_PYTHONQT_LIGHT)

+ 4 - 0
Libs/DICOM/Widgets/ctkDICOMAppWidget.cpp

@@ -27,6 +27,7 @@
 #include "ctkDICOMQueryRetrieveWidget.h"
 #include "ctkDICOMImportWidget.h"
 #include "ctkDICOMThumbnailWidget.h"
+#include "ctkDICOMThumbnailGenerator.h"
 
 //logger
 #include <ctkLogger.h>
@@ -42,6 +43,7 @@ public:
   ctkDICOMQueryRetrieveWidget* QueryRetrieveWidget;
 
   QSharedPointer<ctkDICOMDatabase> DICOMDatabase;
+  QSharedPointer<ctkDICOMThumbnailGenerator> thumbnailGenerator;
   ctkDICOMModel DICOMModel;
   QSharedPointer<ctkDICOMIndexer> DICOMIndexer;
 
@@ -52,6 +54,8 @@ public:
 
 ctkDICOMAppWidgetPrivate::ctkDICOMAppWidgetPrivate(){
   DICOMDatabase = QSharedPointer<ctkDICOMDatabase> (new ctkDICOMDatabase);
+  thumbnailGenerator = QSharedPointer <ctkDICOMThumbnailGenerator> (new ctkDICOMThumbnailGenerator);
+  DICOMDatabase->setThumbnailGenerator(thumbnailGenerator.data());
   DICOMIndexer = QSharedPointer<ctkDICOMIndexer> (new ctkDICOMIndexer);
 }
 

+ 98 - 0
Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.cpp

@@ -0,0 +1,98 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// ctkDICOMCore includes
+#include "ctkDICOMThumbnailGenerator.h"
+#include "ctkLogger.h"
+
+// Qt includes
+#include <QImage>
+
+// DCMTK includes
+#include "dcmimage.h"
+
+static ctkLogger logger ( "org.commontk.dicom.DICOMThumbnailGenerator" );
+struct Node;
+
+//------------------------------------------------------------------------------
+class ctkDICOMThumbnailGeneratorPrivate
+{
+  Q_DECLARE_PUBLIC(ctkDICOMThumbnailGenerator);
+protected:
+  ctkDICOMThumbnailGenerator* const q_ptr;
+
+public:
+  ctkDICOMThumbnailGeneratorPrivate(ctkDICOMThumbnailGenerator&);
+  virtual ~ctkDICOMThumbnailGeneratorPrivate();
+};
+
+//------------------------------------------------------------------------------
+ctkDICOMThumbnailGeneratorPrivate::ctkDICOMThumbnailGeneratorPrivate(ctkDICOMThumbnailGenerator& o):q_ptr(&o)
+{
+
+}
+
+//------------------------------------------------------------------------------
+ctkDICOMThumbnailGeneratorPrivate::~ctkDICOMThumbnailGeneratorPrivate()
+{
+
+}
+
+
+//------------------------------------------------------------------------------
+ctkDICOMThumbnailGenerator::ctkDICOMThumbnailGenerator(QObject* parentValue)
+  : d_ptr(new ctkDICOMThumbnailGeneratorPrivate(*this))
+{
+
+}
+
+//------------------------------------------------------------------------------
+ctkDICOMThumbnailGenerator::~ctkDICOMThumbnailGenerator()
+{
+}
+
+bool ctkDICOMThumbnailGenerator::generateThumbnail(DicomImage *dcmImage, const QString &path){
+    QImage image;
+    if ((dcmImage->getStatus() == EIS_Normal)){
+        dcmImage->setWindow(0);
+        /* get image extension */
+        const unsigned long width = dcmImage->getWidth();
+        const unsigned long height = dcmImage->getHeight();
+        QString header = QString("P5 %1 %2 255\n").arg(width).arg(height);
+        const unsigned long offset = header.length();
+        const unsigned long length = width * height + offset;
+        /* create output buffer for DicomImage class */
+        QByteArray buffer;
+        buffer.append(header);
+        buffer.resize(length);
+
+        /* copy PGM header to buffer */
+
+        if (dcmImage->getOutputData(static_cast<void *>(buffer.data() + offset), length - offset, 8, 0)){
+            if (!image.loadFromData( buffer )){
+                logger.error("QImage couldn't created");
+                return false;
+            }
+        }
+    }
+    image.scaled(128,128,Qt::KeepAspectRatio).save(path,"PNG");
+    return true;
+}

+ 54 - 0
Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.h

@@ -0,0 +1,54 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkDICOMThumbnailGenerator_h
+#define __ctkDICOMThumbnailGenerator_h
+
+// CTK includes
+#include "ctkDICOMWidgetsExport.h"
+#include "ctkDICOMAbstractThumbnailGenerator.h"
+
+class ctkDICOMThumbnailGeneratorPrivate;
+class DicomImage;
+
+/**
+  \brief  thumbnail generator class
+*/
+class CTK_DICOM_WIDGETS_EXPORT ctkDICOMThumbnailGenerator : public ctkDICOMAbstractThumbnailGenerator
+{
+  Q_OBJECT
+public:
+  /** \brief Construct a ctkDICOMThumbnailGenerator object
+  */
+  explicit ctkDICOMThumbnailGenerator(QObject* parent = 0);
+  virtual ~ctkDICOMThumbnailGenerator();
+
+  virtual bool generateThumbnail(DicomImage* dcmImage, const QString& path );
+
+protected:
+  QScopedPointer<ctkDICOMThumbnailGeneratorPrivate> d_ptr;
+
+private:
+  Q_DECLARE_PRIVATE(ctkDICOMThumbnailGenerator);
+  Q_DISABLE_COPY(ctkDICOMThumbnailGenerator);
+};
+
+#endif