CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxDICOMThumbnailGenerator.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Library: CTK
4 
5  Copyright (c) German Cancer Research Center,
6  Division of Medical and Biological Informatics
7 
8  Licensed under the Apache License, Version 2.0 (the "License");
9  you may not use this file except in compliance with the License.
10  You may obtain a copy of the License at
11 
12  http://www.apache.org/licenses/LICENSE-2.0.txt
13 
14  Unless required by applicable law or agreed to in writing, software
15  distributed under the License is distributed on an "AS IS" BASIS,
16  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  See the License for the specific language governing permissions and
18  limitations under the License.
19 
20 =========================================================================*/
21 
22 // ctkDICOMCore includes
24 #include "ctkLogger.h"
25 
26 // Qt includes
27 #include <QImage>
28 #include <QStringList>
29 
30 // DCMTK includes
31 #include "dcmimage.h"
32 
33 static ctkLogger logger ( "org.commontk.dicom.DICOMThumbnailGenerator" );
34 struct Node;
35 
36 namespace cx
37 {
38 //------------------------------------------------------------------------------
40 {
41  Q_DECLARE_PUBLIC(ctkDICOMThumbnailGenerator);
42 
43 public:
46 
47 protected:
49 
50 private:
51  Q_DISABLE_COPY( ctkDICOMThumbnailGeneratorPrivate );
52 };
53 
54 //------------------------------------------------------------------------------
56 {
57 
58 }
59 
60 //------------------------------------------------------------------------------
62 {
63 
64 }
65 
66 
67 //------------------------------------------------------------------------------
69  : d_ptr(new ctkDICOMThumbnailGeneratorPrivate(*this))
70 {
71  Q_UNUSED(parentValue);
72 }
73 
74 //------------------------------------------------------------------------------
76 {
77 }
78 
79 //------------------------------------------------------------------------------
80 bool ctkDICOMThumbnailGenerator::generateThumbnail(DicomImage *dcmImage, const QString &path){
81  QImage image;
82  // Check whether we have a valid image
83  EI_Status result = dcmImage->getStatus();
84  if (result != EIS_Normal)
85  {
86  logger.error(QString("Rendering of DICOM image failed for thumbnail failed: ") + DicomImage::getString(result));
87  return false;
88  }
89  // Select first window defined in image. If none, compute min/max window as best guess.
90  // Only relevant for monochrome.
91  if (dcmImage->isMonochrome())
92  {
93  if (dcmImage->getWindowCount() > 0)
94  {
95  dcmImage->setWindow(0);
96  }
97  else
98  {
99  dcmImage->setMinMaxWindow(OFTrue /* ignore extreme values */);
100  }
101  }
102  /* get image extension and prepare image header */
103  const unsigned long width = dcmImage->getWidth();
104  const unsigned long height = dcmImage->getHeight();
105  const unsigned long frameCount = dcmImage->getFrameCount();
106  unsigned long offset = 0;
107  unsigned long length = 0;
108  QString header;
109 
110  if (dcmImage->isMonochrome())
111  {
112  // write PGM header (binary monochrome image format)
113  header = QString("P5 %1 %2 255\n").arg(width).arg(height);
114  offset = header.length();
115  length = width * height + offset;
116  }
117  else
118  {
119  // write PPM header (binary color image format)
120  header = QString("P6 %1 %2 255\n").arg(width).arg(height);
121  offset = header.length();
122  length = width * height * 3 /* RGB */ + offset;
123  }
124  /* create output buffer for DicomImage class */
125  QByteArray buffer;
126  /* copy header to output buffer and resize it for pixel data */
127  buffer.append(header);
128  buffer.resize(length);
129 
130  for (int i=0; i<frameCount; ++i)
131  {
132  /* render pixel data to buffer */
133  if (dcmImage->getOutputData(static_cast<void *>(buffer.data() + offset), length - offset, 8, i))
134  {
135  if (!image.loadFromData( buffer ))
136  {
137  logger.error("QImage couldn't created");
138  return false;
139  }
140  }
141 
142  QString savePath = path;
143  if (frameCount>1)
144  {
145  QStringList splitPath = path.split(".");
146  splitPath.back() = QString("frame_%1.png").arg(i);
147  savePath = splitPath.join(".");
148 
149  if (i==0) // write to original location anyway; this shuts up some complaints from similar code in the dicom database on remove
150  {
151  image.scaled(128,128,Qt::KeepAspectRatio).save(path,"PNG");
152  }
153  }
154 
155  image.scaled(128,128,Qt::KeepAspectRatio).save(savePath,"PNG");
156  }
157  return true;
158 }
159 
160 } // namespace cx
161 
ctkDICOMThumbnailGeneratorPrivate(ctkDICOMThumbnailGenerator &)
ctkDICOMThumbnailGenerator *const q_ptr
ctkDICOMThumbnailGenerator(QObject *parent=0)
Construct a ctkDICOMThumbnailGenerator object.
virtual bool generateThumbnail(DicomImage *dcmImage, const QString &path)
RealScalar length() const
Namespace for all CustusX production code.