24
24
#include " ctkLogger.h"
25
25
26
26
// Qt includes
27
+ #include < QDebug>
28
+ #include < QDir>
27
29
#include < QImage>
28
30
29
31
// DCMTK includes
30
32
#include " dcmtk/dcmimgle/dcmimage.h"
31
33
32
34
static ctkLogger logger ( " org.commontk.dicom.DICOMThumbnailGenerator" );
33
- struct Node ;
34
35
35
36
// ------------------------------------------------------------------------------
36
37
class ctkDICOMThumbnailGeneratorPrivate
@@ -44,20 +45,26 @@ class ctkDICOMThumbnailGeneratorPrivate
44
45
protected:
45
46
ctkDICOMThumbnailGenerator* const q_ptr;
46
47
48
+ int Width;
49
+ int Height;
50
+ bool SmoothResize;
51
+
47
52
private:
48
53
Q_DISABLE_COPY ( ctkDICOMThumbnailGeneratorPrivate );
49
54
};
50
55
51
56
// ------------------------------------------------------------------------------
52
- ctkDICOMThumbnailGeneratorPrivate::ctkDICOMThumbnailGeneratorPrivate (ctkDICOMThumbnailGenerator& o):q_ptr(&o)
57
+ ctkDICOMThumbnailGeneratorPrivate::ctkDICOMThumbnailGeneratorPrivate (ctkDICOMThumbnailGenerator& o)
58
+ : q_ptr(&o)
59
+ , Width(256 )
60
+ , Height(256 )
61
+ , SmoothResize(false )
53
62
{
54
-
55
63
}
56
64
57
65
// ------------------------------------------------------------------------------
58
66
ctkDICOMThumbnailGeneratorPrivate::~ctkDICOMThumbnailGeneratorPrivate ()
59
67
{
60
-
61
68
}
62
69
63
70
@@ -74,64 +81,117 @@ ctkDICOMThumbnailGenerator::~ctkDICOMThumbnailGenerator()
74
81
}
75
82
76
83
// ------------------------------------------------------------------------------
77
- bool ctkDICOMThumbnailGenerator::generateThumbnail (DicomImage *dcmImage, const QString &path){
78
- QImage image;
79
- // Check whether we have a valid image
80
- EI_Status result = dcmImage->getStatus ();
81
- if (result != EIS_Normal)
82
- {
83
- logger.error (QString (" Rendering of DICOM image failed for thumbnail failed: " ) + DicomImage::getString (result));
84
- return false ;
85
- }
86
- // Select first window defined in image. If none, compute min/max window as best guess.
87
- // Only relevant for monochrome.
88
- if (dcmImage->isMonochrome ())
89
- {
90
- if (dcmImage->getWindowCount () > 0 )
91
- {
92
- dcmImage->setWindow (0 );
93
- }
94
- else
95
- {
96
- dcmImage->setMinMaxWindow (OFTrue /* ignore extreme values */ );
97
- }
98
- }
99
- /* get image extension and prepare image header */
100
- const unsigned long width = dcmImage->getWidth ();
101
- const unsigned long height = dcmImage->getHeight ();
102
- unsigned long offset = 0 ;
103
- unsigned long length = 0 ;
104
- QString header;
105
-
106
- if (dcmImage->isMonochrome ())
84
+ int ctkDICOMThumbnailGenerator::width ()const
85
+ {
86
+ Q_D (const ctkDICOMThumbnailGenerator);
87
+ return d->Width ;
88
+ }
89
+
90
+ // ------------------------------------------------------------------------------
91
+ void ctkDICOMThumbnailGenerator::setWidth (int width)
92
+ {
93
+ Q_D (ctkDICOMThumbnailGenerator);
94
+ d->Width = width;
95
+ }
96
+
97
+ // ------------------------------------------------------------------------------
98
+ int ctkDICOMThumbnailGenerator::height ()const
99
+ {
100
+ Q_D (const ctkDICOMThumbnailGenerator);
101
+ return d->Height ;
102
+ }
103
+
104
+ // ------------------------------------------------------------------------------
105
+ void ctkDICOMThumbnailGenerator::setHeight (int height)
106
+ {
107
+ Q_D (ctkDICOMThumbnailGenerator);
108
+ d->Height = height;
109
+ }
110
+
111
+ // ------------------------------------------------------------------------------
112
+ bool ctkDICOMThumbnailGenerator::smoothResize ()const
113
+ {
114
+ Q_D (const ctkDICOMThumbnailGenerator);
115
+ return d->SmoothResize ;
116
+ }
117
+
118
+ // ------------------------------------------------------------------------------
119
+ void ctkDICOMThumbnailGenerator::setSmoothResize (bool on)
120
+ {
121
+ Q_D (ctkDICOMThumbnailGenerator);
122
+ d->SmoothResize = on;
123
+ }
124
+
125
+ // ------------------------------------------------------------------------------
126
+ bool ctkDICOMThumbnailGenerator::generateThumbnail (DicomImage *dcmImage, const QString &path)
127
+ {
128
+ Q_D (ctkDICOMThumbnailGenerator);
129
+
130
+ QImage image;
131
+ // Check whether we have a valid image
132
+ EI_Status result = dcmImage->getStatus ();
133
+ if (result != EIS_Normal)
134
+ {
135
+ qCritical () << Q_FUNC_INFO << QString (" Rendering of DICOM image failed for thumbnail failed: " ) + DicomImage::getString (result);
136
+ return false ;
137
+ }
138
+ // Select first window defined in image. If none, compute min/max window as best guess.
139
+ // Only relevant for monochrome.
140
+ if (dcmImage->isMonochrome ())
141
+ {
142
+ if (dcmImage->getWindowCount () > 0 )
107
143
{
108
- // write PGM header (binary monochrome image format)
109
- header = QString (" P5 %1 %2 255\n " ).arg (width).arg (height);
110
- offset = header.length ();
111
- length = width * height + offset;
144
+ dcmImage->setWindow (0 );
112
145
}
113
146
else
114
147
{
115
- // write PPM header (binary color image format)
116
- header = QString (" P6 %1 %2 255\n " ).arg (width).arg (height);
117
- offset = header.length ();
118
- length = width * height * 3 /* RGB */ + offset;
148
+ dcmImage->setMinMaxWindow (OFTrue /* ignore extreme values */ );
119
149
}
120
- /* create output buffer for DicomImage class */
121
- QByteArray buffer;
122
- /* copy header to output buffer and resize it for pixel data */
123
- buffer.append (header);
124
- buffer.resize (length);
125
-
126
- /* render pixel data to buffer */
127
- if (dcmImage->getOutputData (static_cast <void *>(buffer.data () + offset), length - offset, 8 , 0 ))
128
- {
129
- if (!image.loadFromData ( buffer ))
130
- {
131
- logger.error (" QImage couldn't created" );
132
- return false ;
133
- }
150
+ }
151
+ /* get image extension and prepare image header */
152
+ const unsigned long width = dcmImage->getWidth ();
153
+ const unsigned long height = dcmImage->getHeight ();
154
+ unsigned long offset = 0 ;
155
+ unsigned long length = 0 ;
156
+ QString header;
157
+
158
+ if (dcmImage->isMonochrome ())
159
+ {
160
+ // write PGM header (binary monochrome image format)
161
+ header = QString (" P5 %1 %2 255\n " ).arg (width).arg (height);
162
+ offset = header.length ();
163
+ length = width * height + offset;
164
+ }
165
+ else
166
+ {
167
+ // write PPM header (binary color image format)
168
+ header = QString (" P6 %1 %2 255\n " ).arg (width).arg (height);
169
+ offset = header.length ();
170
+ length = width * height * 3 /* RGB */ + offset;
171
+ }
172
+ /* create output buffer for DicomImage class */
173
+ QByteArray buffer;
174
+ /* copy header to output buffer and resize it for pixel data */
175
+ buffer.append (header);
176
+ buffer.resize (length);
177
+
178
+ /* render pixel data to buffer */
179
+ if (dcmImage->getOutputData (static_cast <void *>(buffer.data () + offset), length - offset, 8 , 0 ))
180
+ {
181
+ if (!image.loadFromData ( buffer ))
182
+ {
183
+ qCritical () << Q_FUNC_INFO << " QImage couldn't created" ;
184
+ return false ;
134
185
}
135
- image.scaled (128 ,128 ,Qt::KeepAspectRatio).save (path," PNG" );
136
- return true ;
186
+ }
187
+ image.scaled ( d->Width , d->Height , Qt::KeepAspectRatio,
188
+ (d->SmoothResize ? Qt::SmoothTransformation : Qt::FastTransformation) ).save (path," PNG" );
189
+ return true ;
190
+ }
191
+
192
+ // ------------------------------------------------------------------------------
193
+ bool ctkDICOMThumbnailGenerator::generateThumbnail (const QString dcmImagePath, const QString& thumbnailPath)
194
+ {
195
+ DicomImage dcmImage (QDir::toNativeSeparators (dcmImagePath).toUtf8 ());
196
+ return this ->generateThumbnail (&dcmImage, thumbnailPath);
137
197
}
0 commit comments