182
|
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 "../Enumerations.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 SubpixelReaderBase : public boost::noncopyable
|
|
37 {
|
|
38 private:
|
|
39 const Orthanc::ImageAccessor& source_;
|
|
40 unsigned int width_;
|
|
41 unsigned int height_;
|
|
42
|
|
43 public:
|
|
44 SubpixelReaderBase(const Orthanc::ImageAccessor& source) :
|
|
45 source_(source),
|
|
46 width_(source.GetWidth()),
|
|
47 height_(source.GetHeight())
|
|
48 {
|
|
49 }
|
|
50
|
|
51 ORTHANC_FORCE_INLINE
|
|
52 const Orthanc::ImageAccessor& GetSource() const
|
|
53 {
|
|
54 return source_;
|
|
55 }
|
|
56
|
|
57 ORTHANC_FORCE_INLINE
|
|
58 unsigned int GetWidth() const
|
|
59 {
|
|
60 return width_;
|
|
61 }
|
|
62
|
|
63 ORTHANC_FORCE_INLINE
|
|
64 unsigned int GetHeight() const
|
|
65 {
|
|
66 return height_;
|
|
67 }
|
|
68 };
|
|
69 }
|
|
70
|
|
71
|
|
72 template <Orthanc::PixelFormat Format,
|
|
73 ImageInterpolation Interpolation>
|
|
74 class SubpixelReader;
|
|
75
|
|
76
|
|
77 template <Orthanc::PixelFormat Format>
|
|
78 class SubpixelReader<Format, ImageInterpolation_Nearest> :
|
|
79 public Internals::SubpixelReaderBase
|
|
80 {
|
|
81 public:
|
|
82 typedef Orthanc::PixelTraits<Format> Traits;
|
|
83 typedef typename Traits::PixelType PixelType;
|
|
84
|
|
85 SubpixelReader(const Orthanc::ImageAccessor& source) :
|
|
86 SubpixelReaderBase(source)
|
|
87 {
|
|
88 }
|
|
89
|
|
90 inline bool GetValue(PixelType& target,
|
|
91 float x,
|
|
92 float y) const;
|
183
|
93
|
|
94 inline bool GetFloatValue(float& target,
|
|
95 float x,
|
|
96 float y) const;
|
182
|
97 };
|
183
|
98
|
182
|
99
|
|
100
|
|
101 template <Orthanc::PixelFormat Format>
|
|
102 class SubpixelReader<Format, ImageInterpolation_Bilinear> :
|
|
103 public Internals::SubpixelReaderBase
|
|
104 {
|
|
105 public:
|
|
106 typedef Orthanc::PixelTraits<Format> Traits;
|
|
107 typedef typename Traits::PixelType PixelType;
|
|
108
|
|
109 SubpixelReader(const Orthanc::ImageAccessor& source) :
|
|
110 SubpixelReaderBase(source)
|
|
111 {
|
|
112 }
|
|
113
|
183
|
114 inline bool GetFloatValue(float& target,
|
|
115 float x,
|
|
116 float y) const;
|
|
117
|
182
|
118 inline bool GetValue(PixelType& target,
|
|
119 float x,
|
183
|
120 float y) const;
|
182
|
121 };
|
|
122
|
|
123
|
|
124
|
|
125 template <Orthanc::PixelFormat Format>
|
|
126 bool SubpixelReader<Format, ImageInterpolation_Nearest>::GetValue(PixelType& target,
|
|
127 float x,
|
|
128 float y) const
|
|
129 {
|
|
130 if (x < 0 ||
|
|
131 y < 0)
|
|
132 {
|
|
133 return false;
|
|
134 }
|
|
135 else
|
|
136 {
|
|
137 unsigned int ux = static_cast<unsigned int>(std::floor(x));
|
|
138 unsigned int uy = static_cast<unsigned int>(std::floor(y));
|
|
139
|
|
140 if (ux < GetWidth() &&
|
|
141 uy < GetHeight())
|
|
142 {
|
|
143 Orthanc::ImageTraits<Format>::GetPixel(target, GetSource(), ux, uy);
|
|
144 return true;
|
|
145 }
|
|
146 else
|
|
147 {
|
|
148 return false;
|
|
149 }
|
|
150 }
|
|
151 }
|
|
152
|
|
153
|
|
154
|
|
155 template <Orthanc::PixelFormat Format>
|
183
|
156 bool SubpixelReader<Format, ImageInterpolation_Nearest>::GetFloatValue(float& target,
|
|
157 float x,
|
|
158 float y) const
|
|
159 {
|
|
160 PixelType value;
|
|
161
|
|
162 if (GetValue(value, x, y))
|
|
163 {
|
|
164 target = Traits::PixelToFloat(value);
|
|
165 return true;
|
|
166 }
|
|
167 else
|
|
168 {
|
|
169 return false;
|
|
170 }
|
|
171 }
|
|
172
|
|
173
|
|
174
|
|
175 template <Orthanc::PixelFormat Format>
|
182
|
176 bool SubpixelReader<Format, ImageInterpolation_Bilinear>::GetValue(PixelType& target,
|
|
177 float x,
|
183
|
178 float y) const
|
|
179 {
|
|
180 float value;
|
|
181
|
|
182 if (GetFloatValue(value, x, y))
|
|
183 {
|
|
184 Traits::FloatToPixel(target, value);
|
|
185 return true;
|
|
186 }
|
|
187 else
|
|
188 {
|
|
189 return false;
|
|
190 }
|
|
191 }
|
|
192
|
|
193
|
|
194
|
|
195 template <Orthanc::PixelFormat Format>
|
|
196 bool SubpixelReader<Format, ImageInterpolation_Bilinear>::GetFloatValue(float& target,
|
|
197 float x,
|
|
198 float y) const
|
182
|
199 {
|
|
200 x -= 0.5f;
|
|
201 y -= 0.5f;
|
|
202
|
|
203 if (x < 0 ||
|
|
204 y < 0)
|
|
205 {
|
|
206 return false;
|
|
207 }
|
|
208 else
|
|
209 {
|
|
210 unsigned int ux = static_cast<unsigned int>(std::floor(x));
|
|
211 unsigned int uy = static_cast<unsigned int>(std::floor(y));
|
|
212
|
|
213 float f00, f01, f10, f11;
|
|
214
|
|
215 if (ux < GetWidth() &&
|
|
216 uy < GetHeight())
|
|
217 {
|
|
218 f00 = Orthanc::ImageTraits<Format>::GetFloatPixel(GetSource(), ux, uy);
|
|
219 }
|
|
220 else
|
|
221 {
|
|
222 return false;
|
|
223 }
|
|
224
|
|
225 if (ux + 1 < GetWidth())
|
|
226 {
|
|
227 f01 = Orthanc::ImageTraits<Format>::GetFloatPixel(GetSource(), ux + 1, uy);
|
|
228 }
|
|
229 else
|
|
230 {
|
|
231 f01 = f00;
|
|
232 }
|
|
233
|
|
234 if (uy + 1 < GetHeight())
|
|
235 {
|
|
236 f10 = Orthanc::ImageTraits<Format>::GetFloatPixel(GetSource(), ux, uy + 1);
|
|
237 }
|
|
238 else
|
|
239 {
|
|
240 f10 = f00;
|
|
241 }
|
|
242
|
|
243 if (ux + 1 < GetWidth() &&
|
|
244 uy + 1 < GetHeight())
|
|
245 {
|
|
246 f11 = Orthanc::ImageTraits<Format>::GetFloatPixel(GetSource(), ux + 1, uy + 1);
|
|
247 }
|
|
248 else
|
|
249 {
|
|
250 f11 = f00;
|
|
251 }
|
|
252
|
|
253 float ax = x - static_cast<float>(ux);
|
|
254 float ay = y - static_cast<float>(uy);
|
183
|
255 target = GeometryToolbox::ComputeBilinearInterpolationUnitSquare(ax, ay, f00, f01, f10, f11);
|
182
|
256
|
|
257 return true;
|
|
258 }
|
|
259 }
|
|
260 }
|