Mercurial > hg > orthanc-stone
annotate Framework/Toolbox/DicomFrameConverter.cpp @ 134:4cff7b1ed31d
upgrade to year 2018
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 02 Jan 2018 09:51:36 +0100 |
parents | 28956ed68280 |
children | fccffbf99ba1 |
rev | line source |
---|---|
0 | 1 /** |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
134
4cff7b1ed31d
upgrade to year 2018
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
47
diff
changeset
|
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium |
0 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
47 | 8 * modify it under the terms of the GNU Affero General Public License |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
0 | 11 * |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
47 | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
0 | 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 **/ | |
20 | |
21 | |
22 #include "DicomFrameConverter.h" | |
23 | |
32 | 24 #include "GeometryToolbox.h" |
25 | |
16 | 26 #include "../../Resources/Orthanc/Core/Images/Image.h" |
27 #include "../../Resources/Orthanc/Core/Images/ImageProcessing.h" | |
28 #include "../../Resources/Orthanc/Core/OrthancException.h" | |
29 #include "../../Resources/Orthanc/Core/Toolbox.h" | |
0 | 30 |
31 namespace OrthancStone | |
32 { | |
33 void DicomFrameConverter::SetDefaultParameters() | |
34 { | |
35 isSigned_ = true; | |
36 isColor_ = false; | |
37 hasRescale_ = false; | |
38 rescaleIntercept_ = 0; | |
39 rescaleSlope_ = 1; | |
40 defaultWindowCenter_ = 128; | |
41 defaultWindowWidth_ = 256; | |
42 } | |
43 | |
44 | |
45 Orthanc::PixelFormat DicomFrameConverter::GetExpectedPixelFormat() const | |
46 { | |
47 // TODO Add more checks, e.g. on the number of bytes per value | |
48 // (cf. DicomImageInformation.h in Orthanc) | |
49 | |
50 if (isColor_) | |
51 { | |
52 return Orthanc::PixelFormat_RGB24; | |
53 } | |
54 else if (isSigned_) | |
55 { | |
56 return Orthanc::PixelFormat_SignedGrayscale16; | |
57 } | |
58 else | |
59 { | |
60 return Orthanc::PixelFormat_Grayscale16; | |
61 } | |
62 } | |
63 | |
64 | |
32 | 65 void DicomFrameConverter::ReadParameters(const OrthancPlugins::IDicomDataset& dicom) |
0 | 66 { |
67 SetDefaultParameters(); | |
68 | |
32 | 69 Vector c, w; |
70 if (GeometryToolbox::ParseVector(c, dicom, OrthancPlugins::DICOM_TAG_WINDOW_CENTER) && | |
34 | 71 GeometryToolbox::ParseVector(w, dicom, OrthancPlugins::DICOM_TAG_WINDOW_WIDTH) && |
72 c.size() > 0 && | |
73 w.size() > 0) | |
0 | 74 { |
34 | 75 defaultWindowCenter_ = static_cast<float>(c[0]); |
76 defaultWindowWidth_ = static_cast<float>(w[0]); | |
0 | 77 } |
78 | |
32 | 79 OrthancPlugins::DicomDatasetReader reader(dicom); |
0 | 80 |
32 | 81 int tmp; |
82 if (!reader.GetIntegerValue(tmp, OrthancPlugins::DICOM_TAG_PIXEL_REPRESENTATION)) | |
0 | 83 { |
32 | 84 // Type 1 tag, must be present |
85 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
86 } | |
87 | |
88 isSigned_ = (tmp == 1); | |
89 | |
90 if (reader.GetFloatValue(rescaleIntercept_, OrthancPlugins::DICOM_TAG_RESCALE_INTERCEPT) && | |
91 reader.GetFloatValue(rescaleSlope_, OrthancPlugins::DICOM_TAG_RESCALE_SLOPE)) | |
92 { | |
0 | 93 hasRescale_ = true; |
94 } | |
95 | |
32 | 96 // Type 1 tag, must be present |
97 std::string photometric = reader.GetMandatoryStringValue(OrthancPlugins::DICOM_TAG_PHOTOMETRIC_INTERPRETATION); | |
0 | 98 photometric = Orthanc::Toolbox::StripSpaces(photometric); |
99 isColor_ = (photometric != "MONOCHROME1" && | |
100 photometric != "MONOCHROME2"); | |
101 } | |
102 | |
103 | |
104 void DicomFrameConverter::ConvertFrame(std::auto_ptr<Orthanc::ImageAccessor>& source) const | |
105 { | |
106 assert(sizeof(float) == 4); | |
107 | |
108 if (source.get() == NULL) | |
109 { | |
110 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
111 } | |
112 | |
113 Orthanc::PixelFormat sourceFormat = source->GetFormat(); | |
114 | |
115 if (sourceFormat != GetExpectedPixelFormat()) | |
116 { | |
117 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
118 } | |
119 | |
120 if (sourceFormat == Orthanc::PixelFormat_RGB24) | |
121 { | |
122 // No conversion has to be done | |
123 return; | |
124 } | |
125 | |
126 assert(sourceFormat == Orthanc::PixelFormat_Grayscale16 || | |
127 sourceFormat == Orthanc::PixelFormat_SignedGrayscale16); | |
128 | |
129 // This is the case of a grayscale frame. Convert it to Float32. | |
130 std::auto_ptr<Orthanc::Image> converted(new Orthanc::Image(Orthanc::PixelFormat_Float32, | |
131 source->GetWidth(), | |
11 | 132 source->GetHeight(), |
133 false)); | |
0 | 134 Orthanc::ImageProcessing::Convert(*converted, *source); |
135 | |
136 source.reset(NULL); // We don't need the source frame anymore | |
137 | |
138 // Correct rescale slope/intercept if need be | |
139 if (hasRescale_) | |
140 { | |
141 for (unsigned int y = 0; y < converted->GetHeight(); y++) | |
142 { | |
143 float* p = reinterpret_cast<float*>(converted->GetRow(y)); | |
144 for (unsigned int x = 0; x < converted->GetWidth(); x++, p++) | |
145 { | |
146 float value = *p; | |
147 | |
148 if (hasRescale_) | |
149 { | |
150 value = value * rescaleSlope_ + rescaleIntercept_; | |
151 } | |
152 | |
153 *p = value; | |
154 } | |
155 } | |
156 } | |
157 | |
158 source = converted; | |
159 } | |
160 } |