comparison Framework/Toolbox/SubvoxelReader.h @ 183:98da3a8d4820 wasm

SubvoxelReader
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 15 Mar 2018 15:19:24 +0100
parents
children e9c7a78a3e77
comparison
equal deleted inserted replaced
182:2cbfb08f3a95 183:98da3a8d4820
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
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.
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
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
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #pragma once
23
24 #include "../Volumes/ImageBuffer3D.h"
25 #include "GeometryToolbox.h"
26
27 #include <Core/Images/ImageTraits.h>
28
29 #include <boost/noncopyable.hpp>
30 #include <cmath>
31
32 namespace OrthancStone
33 {
34 namespace Internals
35 {
36 class SubvoxelReaderBase : public boost::noncopyable
37 {
38 private:
39 const ImageBuffer3D& source_;
40 unsigned int width_;
41 unsigned int height_;
42 unsigned int depth_;
43
44 public:
45 SubvoxelReaderBase(const ImageBuffer3D& source) :
46 source_(source),
47 width_(source.GetWidth()),
48 height_(source.GetHeight()),
49 depth_(source.GetDepth())
50 {
51 }
52
53 ORTHANC_FORCE_INLINE
54 const Orthanc::ImageAccessor& GetSource() const
55 {
56 return source_.GetInternalImage();
57 }
58
59 ORTHANC_FORCE_INLINE
60 unsigned int GetWidth() const
61 {
62 return width_;
63 }
64
65 ORTHANC_FORCE_INLINE
66 unsigned int GetHeight() const
67 {
68 return height_;
69 }
70
71 ORTHANC_FORCE_INLINE
72 unsigned int GetDepth() const
73 {
74 return depth_;
75 }
76
77 ORTHANC_FORCE_INLINE
78 unsigned int ComputeRow(unsigned int y,
79 unsigned int z) const
80 {
81 return z * height_ + y;
82 }
83 };
84 }
85
86
87 template <Orthanc::PixelFormat Format,
88 ImageInterpolation Interpolation>
89 class SubvoxelReader;
90
91
92 template <Orthanc::PixelFormat Format>
93 class SubvoxelReader<Format, ImageInterpolation_Nearest> :
94 public Internals::SubvoxelReaderBase
95 {
96 public:
97 typedef Orthanc::PixelTraits<Format> Traits;
98 typedef typename Traits::PixelType PixelType;
99
100 SubvoxelReader(const ImageBuffer3D& source) :
101 SubvoxelReaderBase(source)
102 {
103 }
104
105 inline bool GetValue(PixelType& target,
106 float x,
107 float y,
108 float z) const;
109
110 inline bool GetFloatValue(float& target,
111 float x,
112 float y,
113 float z) const;
114 };
115
116
117 template <Orthanc::PixelFormat Format>
118 class SubvoxelReader<Format, ImageInterpolation_Bilinear> :
119 public Internals::SubvoxelReaderBase
120 {
121 public:
122 typedef Orthanc::PixelTraits<Format> Traits;
123 typedef typename Traits::PixelType PixelType;
124
125 SubvoxelReader(const ImageBuffer3D& source) :
126 SubvoxelReaderBase(source)
127 {
128 }
129
130 inline bool Sample(float& f00,
131 float& f01,
132 float& f10,
133 float& f11,
134 unsigned int ux,
135 unsigned int uy,
136 unsigned int uz) const;
137
138 inline bool GetValue(PixelType& target,
139 float x,
140 float y,
141 float z) const;
142
143 inline bool GetFloatValue(float& target,
144 float x,
145 float y,
146 float z) const;
147 };
148
149
150 template <Orthanc::PixelFormat Format>
151 class SubvoxelReader<Format, ImageInterpolation_Trilinear> :
152 public Internals::SubvoxelReaderBase
153 {
154 private:
155 SubvoxelReader<Format, ImageInterpolation_Bilinear> bilinear_;
156
157 public:
158 typedef Orthanc::PixelTraits<Format> Traits;
159 typedef typename Traits::PixelType PixelType;
160
161 SubvoxelReader(const ImageBuffer3D& source) :
162 SubvoxelReaderBase(source),
163 bilinear_(source)
164 {
165 }
166
167 inline bool GetValue(PixelType& target,
168 float x,
169 float y,
170 float z) const;
171
172 inline bool GetFloatValue(float& target,
173 float x,
174 float y,
175 float z) const;
176 };
177
178
179
180 template <Orthanc::PixelFormat Format>
181 bool SubvoxelReader<Format, ImageInterpolation_Nearest>::GetValue(PixelType& target,
182 float x,
183 float y,
184 float z) const
185 {
186 if (x < 0 ||
187 y < 0 ||
188 z < 0)
189 {
190 return false;
191 }
192 else
193 {
194 unsigned int ux = static_cast<unsigned int>(std::floor(x));
195 unsigned int uy = static_cast<unsigned int>(std::floor(y));
196 unsigned int uz = static_cast<unsigned int>(std::floor(z));
197
198 if (ux < GetWidth() &&
199 uy < GetHeight() &&
200 uz < GetDepth())
201 {
202 Orthanc::ImageTraits<Format>::GetPixel(target, GetSource(), ux, ComputeRow(uy, uz));
203 return true;
204 }
205 else
206 {
207 return false;
208 }
209 }
210 }
211
212
213 template <Orthanc::PixelFormat Format>
214 bool SubvoxelReader<Format, ImageInterpolation_Nearest>::GetFloatValue(float& target,
215 float x,
216 float y,
217 float z) const
218 {
219 PixelType value;
220
221 if (GetValue(value, x, y, z))
222 {
223 target = Traits::PixelToFloat(value);
224 return true;
225 }
226 else
227 {
228 return false;
229 }
230 }
231
232
233
234 template <Orthanc::PixelFormat Format>
235 bool SubvoxelReader<Format, ImageInterpolation_Bilinear>::Sample(float& f00,
236 float& f01,
237 float& f10,
238 float& f11,
239 unsigned int ux,
240 unsigned int uy,
241 unsigned int uz) const
242 {
243 if (ux < GetWidth() &&
244 uy < GetHeight() &&
245 uz < GetDepth())
246 {
247 f00 = Orthanc::ImageTraits<Format>::GetFloatPixel(GetSource(), ux, ComputeRow(uy, uz));
248 }
249 else
250 {
251 // Pixel is out of the volume
252 return false;
253 }
254
255 if (ux + 1 < GetWidth())
256 {
257 f01 = Orthanc::ImageTraits<Format>::GetFloatPixel(GetSource(), ux + 1, ComputeRow(uy, uz));
258 }
259 else
260 {
261 f01 = f00;
262 }
263
264 if (uy + 1 < GetHeight())
265 {
266 f10 = Orthanc::ImageTraits<Format>::GetFloatPixel(GetSource(), ux, ComputeRow(uy + 1, uz));
267 }
268 else
269 {
270 f10 = f00;
271 }
272
273 if (ux + 1 < GetWidth() &&
274 uy + 1 < GetHeight())
275 {
276 f11 = Orthanc::ImageTraits<Format>::GetFloatPixel(GetSource(), ux + 1, ComputeRow(uy + 1, uz));
277 }
278 else
279 {
280 f11 = f00;
281 }
282
283 return true;
284 }
285
286
287
288 template <Orthanc::PixelFormat Format>
289 bool SubvoxelReader<Format, ImageInterpolation_Bilinear>::GetFloatValue(float& target,
290 float x,
291 float y,
292 float z) const
293 {
294 x -= 0.5f;
295 y -= 0.5f;
296
297 if (x < 0 ||
298 y < 0 ||
299 z < 0)
300 {
301 return false;
302 }
303 else
304 {
305 unsigned int ux = static_cast<unsigned int>(std::floor(x));
306 unsigned int uy = static_cast<unsigned int>(std::floor(y));
307 unsigned int uz = static_cast<unsigned int>(std::floor(z));
308
309 float f00, f01, f10, f11;
310 if (Sample(f00, f01, f10, f11, ux, uy, uz))
311 {
312 float ax = x - static_cast<float>(ux);
313 float ay = y - static_cast<float>(uy);
314
315 target = GeometryToolbox::ComputeBilinearInterpolationUnitSquare(ax, ay, f00, f01, f10, f11);
316 return true;
317 }
318 else
319 {
320 return false;
321 }
322 }
323 }
324
325
326
327 template <Orthanc::PixelFormat Format>
328 bool SubvoxelReader<Format, ImageInterpolation_Bilinear>::GetValue(PixelType& target,
329 float x,
330 float y,
331 float z) const
332 {
333 float value;
334
335 if (GetFloatValue(value, x, y, z))
336 {
337 Traits::FloatToPixel(target, value);
338 return true;
339 }
340 else
341 {
342 return false;
343 }
344 }
345
346
347
348 template <Orthanc::PixelFormat Format>
349 bool SubvoxelReader<Format, ImageInterpolation_Trilinear>::GetFloatValue(float& target,
350 float x,
351 float y,
352 float z) const
353 {
354 x -= 0.5f;
355 y -= 0.5f;
356 z -= 0.5f;
357
358 if (x < 0 ||
359 y < 0 ||
360 z < 0)
361 {
362 return false;
363 }
364 else
365 {
366 unsigned int ux = static_cast<unsigned int>(std::floor(x));
367 unsigned int uy = static_cast<unsigned int>(std::floor(y));
368 unsigned int uz = static_cast<unsigned int>(std::floor(z));
369
370 float f000, f001, f010, f011;
371 if (bilinear_.Sample(f000, f001, f010, f011, ux, uy, uz))
372 {
373 const float ax = x - static_cast<float>(ux);
374 const float ay = y - static_cast<float>(uy);
375
376 float f100, f101, f110, f111;
377
378 if (bilinear_.Sample(f100, f101, f110, f111, ux, uy, uz + 1))
379 {
380 const float az = z - static_cast<float>(uz);
381 target = GeometryToolbox::ComputeTrilinearInterpolationUnitSquare
382 (ax, ay, az, f000, f001, f010, f011, f100, f101, f110, f111);
383 }
384 else
385 {
386 target = GeometryToolbox::ComputeBilinearInterpolationUnitSquare
387 (ax, ay, f000, f001, f010, f011);
388 }
389
390 return true;
391 }
392 else
393 {
394 return false;
395 }
396 }
397 }
398
399
400
401 template <Orthanc::PixelFormat Format>
402 bool SubvoxelReader<Format, ImageInterpolation_Trilinear>::GetValue(PixelType& target,
403 float x,
404 float y,
405 float z) const
406 {
407 float value;
408
409 if (GetFloatValue(value, x, y, z))
410 {
411 Traits::FloatToPixel(target, value);
412 return true;
413 }
414 else
415 {
416 return false;
417 }
418 }
419 }