Mercurial > hg > orthanc-stone
comparison Framework/Toolbox/DicomFrameConverter.cpp @ 119:ba83e38cf3ff wasm
rendering of rt-dose
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 02 Oct 2017 22:01:41 +0200 |
parents | a4d0b6c82b29 |
children | 063f7f3d9f14 |
comparison
equal
deleted
inserted
replaced
118:a4d0b6c82b29 | 119:ba83e38cf3ff |
---|---|
37 hasRescale_ = false; | 37 hasRescale_ = false; |
38 rescaleIntercept_ = 0; | 38 rescaleIntercept_ = 0; |
39 rescaleSlope_ = 1; | 39 rescaleSlope_ = 1; |
40 defaultWindowCenter_ = 128; | 40 defaultWindowCenter_ = 128; |
41 defaultWindowWidth_ = 256; | 41 defaultWindowWidth_ = 256; |
42 } | 42 expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16; |
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 } | 43 } |
63 | 44 |
64 | 45 |
65 void DicomFrameConverter::ReadParameters(const Orthanc::DicomMap& dicom) | 46 void DicomFrameConverter::ReadParameters(const Orthanc::DicomMap& dicom) |
66 { | 47 { |
83 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | 64 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
84 } | 65 } |
85 | 66 |
86 isSigned_ = (tmp == 1); | 67 isSigned_ = (tmp == 1); |
87 | 68 |
88 if (dicom.ParseFloat(rescaleIntercept_, Orthanc::DICOM_TAG_RESCALE_INTERCEPT) && | 69 double doseGridScaling; |
89 dicom.ParseFloat(rescaleSlope_, Orthanc::DICOM_TAG_RESCALE_SLOPE)) | 70 bool isRTDose = false; |
71 | |
72 if (dicom.ParseDouble(rescaleIntercept_, Orthanc::DICOM_TAG_RESCALE_INTERCEPT) && | |
73 dicom.ParseDouble(rescaleSlope_, Orthanc::DICOM_TAG_RESCALE_SLOPE)) | |
90 { | 74 { |
91 hasRescale_ = true; | 75 hasRescale_ = true; |
76 } | |
77 else if (dicom.ParseDouble(doseGridScaling, Orthanc::DICOM_TAG_DOSE_GRID_SCALING)) | |
78 { | |
79 // This is for RT-DOSE | |
80 hasRescale_ = true; | |
81 isRTDose = true; | |
82 rescaleIntercept_ = 0; | |
83 rescaleSlope_ = doseGridScaling; | |
92 } | 84 } |
93 | 85 |
94 std::string photometric; | 86 std::string photometric; |
95 if (dicom.CopyToString(photometric, Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION, false)) | 87 if (dicom.CopyToString(photometric, Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION, false)) |
96 { | 88 { |
102 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | 94 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
103 } | 95 } |
104 | 96 |
105 isColor_ = (photometric != "MONOCHROME1" && | 97 isColor_ = (photometric != "MONOCHROME1" && |
106 photometric != "MONOCHROME2"); | 98 photometric != "MONOCHROME2"); |
99 | |
100 // TODO Add more checks, e.g. on the number of bytes per value | |
101 // (cf. DicomImageInformation.h in Orthanc) | |
102 | |
103 if (isRTDose) | |
104 { | |
105 expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale32; | |
106 } | |
107 else if (isColor_) | |
108 { | |
109 expectedPixelFormat_ = Orthanc::PixelFormat_RGB24; | |
110 } | |
111 else if (isSigned_) | |
112 { | |
113 expectedPixelFormat_ = Orthanc::PixelFormat_SignedGrayscale16; | |
114 } | |
115 else | |
116 { | |
117 expectedPixelFormat_ = Orthanc::PixelFormat_Grayscale16; | |
118 } | |
107 } | 119 } |
108 | 120 |
109 | 121 |
110 void DicomFrameConverter::ConvertFrame(std::auto_ptr<Orthanc::ImageAccessor>& source) const | 122 void DicomFrameConverter::ConvertFrame(std::auto_ptr<Orthanc::ImageAccessor>& source) const |
111 { | 123 { |
128 // No conversion has to be done | 140 // No conversion has to be done |
129 return; | 141 return; |
130 } | 142 } |
131 | 143 |
132 assert(sourceFormat == Orthanc::PixelFormat_Grayscale16 || | 144 assert(sourceFormat == Orthanc::PixelFormat_Grayscale16 || |
145 sourceFormat == Orthanc::PixelFormat_Grayscale32 || | |
133 sourceFormat == Orthanc::PixelFormat_SignedGrayscale16); | 146 sourceFormat == Orthanc::PixelFormat_SignedGrayscale16); |
134 | 147 |
135 // This is the case of a grayscale frame. Convert it to Float32. | 148 // This is the case of a grayscale frame. Convert it to Float32. |
136 std::auto_ptr<Orthanc::Image> converted(new Orthanc::Image(Orthanc::PixelFormat_Float32, | 149 std::auto_ptr<Orthanc::Image> converted(new Orthanc::Image(Orthanc::PixelFormat_Float32, |
137 source->GetWidth(), | 150 source->GetWidth(), |
140 Orthanc::ImageProcessing::Convert(*converted, *source); | 153 Orthanc::ImageProcessing::Convert(*converted, *source); |
141 | 154 |
142 source.reset(NULL); // We don't need the source frame anymore | 155 source.reset(NULL); // We don't need the source frame anymore |
143 | 156 |
144 // Correct rescale slope/intercept if need be | 157 // Correct rescale slope/intercept if need be |
158 ApplyRescale(*converted, sourceFormat != Orthanc::PixelFormat_Grayscale32); | |
159 | |
160 source = converted; | |
161 } | |
162 | |
163 | |
164 void DicomFrameConverter::ApplyRescale(Orthanc::ImageAccessor& image, | |
165 bool useDouble) const | |
166 { | |
167 if (image.GetFormat() != Orthanc::PixelFormat_Float32) | |
168 { | |
169 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat); | |
170 } | |
171 | |
145 if (hasRescale_) | 172 if (hasRescale_) |
146 { | 173 { |
147 for (unsigned int y = 0; y < converted->GetHeight(); y++) | 174 for (unsigned int y = 0; y < image.GetHeight(); y++) |
148 { | 175 { |
149 float* p = reinterpret_cast<float*>(converted->GetRow(y)); | 176 float* p = reinterpret_cast<float*>(image.GetRow(y)); |
150 for (unsigned int x = 0; x < converted->GetWidth(); x++, p++) | 177 |
178 if (useDouble) | |
151 { | 179 { |
152 float value = *p; | 180 // Slower, accurate implementation using double |
153 | 181 for (unsigned int x = 0; x < image.GetWidth(); x++, p++) |
154 if (hasRescale_) | |
155 { | 182 { |
156 value = value * rescaleSlope_ + rescaleIntercept_; | 183 double value = static_cast<double>(*p); |
184 *p = static_cast<float>(value * rescaleSlope_ + rescaleIntercept_); | |
157 } | 185 } |
158 | 186 } |
159 *p = value; | 187 else |
188 { | |
189 // Fast, approximate implementation using float | |
190 for (unsigned int x = 0; x < image.GetWidth(); x++, p++) | |
191 { | |
192 *p = (*p) * static_cast<float>(rescaleSlope_) + static_cast<float>(rescaleIntercept_); | |
193 } | |
160 } | 194 } |
161 } | 195 } |
162 } | 196 } |
163 | 197 } |
164 source = converted; | 198 |
165 } | 199 |
200 double DicomFrameConverter::Apply(double x) const | |
201 { | |
202 return x * rescaleSlope_ + rescaleIntercept_; | |
203 } | |
204 | |
166 } | 205 } |