1 /**
2  * Orthanc - A Lightweight, RESTful DICOM Store
3  * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4  * Department, University Hospital of Liege, Belgium
5  * Copyright (C) 2017-2021 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 Lesser 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  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program. If not, see
19  * <http://www.gnu.org/licenses/>.
20  **/
21 
22 
23 #pragma once
24 
25 #include "../Compatibility.h"  // For ORTHANC_FORCE_INLINE
26 #include "../Enumerations.h"
27 
28 #include <limits>
29 
30 namespace Orthanc
31 {
32   template <PixelFormat format,
33             typename _PixelType>
34   struct IntegerPixelTraits
35   {
36     typedef _PixelType  PixelType;
37 
38     ORTHANC_FORCE_INLINE
GetPixelFormatIntegerPixelTraits39     static PixelFormat GetPixelFormat()
40     {
41       return format;
42     }
43 
44     ORTHANC_FORCE_INLINE
IntegerToPixelIntegerPixelTraits45     static PixelType IntegerToPixel(int64_t value)
46     {
47       if (value < static_cast<int64_t>(std::numeric_limits<PixelType>::min()))
48       {
49         return std::numeric_limits<PixelType>::min();
50       }
51       else if (value > static_cast<int64_t>(std::numeric_limits<PixelType>::max()))
52       {
53         return std::numeric_limits<PixelType>::max();
54       }
55       else
56       {
57         return static_cast<PixelType>(value);
58       }
59     }
60 
61     ORTHANC_FORCE_INLINE
SetZeroIntegerPixelTraits62     static void SetZero(PixelType& target)
63     {
64       target = 0;
65     }
66 
67     ORTHANC_FORCE_INLINE
SetMinValueIntegerPixelTraits68     static void SetMinValue(PixelType& target)
69     {
70       target = std::numeric_limits<PixelType>::min();
71     }
72 
73     ORTHANC_FORCE_INLINE
SetMaxValueIntegerPixelTraits74     static void SetMaxValue(PixelType& target)
75     {
76       target = std::numeric_limits<PixelType>::max();
77     }
78 
79     ORTHANC_FORCE_INLINE
CopyIntegerPixelTraits80     static void Copy(PixelType& target,
81                      const PixelType& source)
82     {
83       target = source;
84     }
85 
86     ORTHANC_FORCE_INLINE
PixelToFloatIntegerPixelTraits87     static float PixelToFloat(const PixelType& source)
88     {
89       return static_cast<float>(source);
90     }
91 
92     ORTHANC_FORCE_INLINE
FloatToPixelIntegerPixelTraits93     static void FloatToPixel(PixelType& target,
94                              float value)
95     {
96       value += 0.5f;
97       if (value < static_cast<float>(std::numeric_limits<PixelType>::min()))
98       {
99         target = std::numeric_limits<PixelType>::min();
100       }
101       else if (value > static_cast<float>(std::numeric_limits<PixelType>::max()))
102       {
103         target = std::numeric_limits<PixelType>::max();
104       }
105       else
106       {
107         target = static_cast<PixelType>(value);
108       }
109     }
110 
111     ORTHANC_FORCE_INLINE
IsEqualIntegerPixelTraits112     static bool IsEqual(const PixelType& a,
113                         const PixelType& b)
114     {
115       return a == b;
116     }
117   };
118 
119 
120   template <PixelFormat Format>
121   struct PixelTraits;
122 
123 
124   template <>
125   struct PixelTraits<PixelFormat_Grayscale8> :
126     public IntegerPixelTraits<PixelFormat_Grayscale8, uint8_t>
127   {
128   };
129 
130 
131   template <>
132   struct PixelTraits<PixelFormat_Grayscale16> :
133     public IntegerPixelTraits<PixelFormat_Grayscale16, uint16_t>
134   {
135   };
136 
137 
138   template <>
139   struct PixelTraits<PixelFormat_SignedGrayscale16> :
140     public IntegerPixelTraits<PixelFormat_SignedGrayscale16, int16_t>
141   {
142   };
143 
144 
145   template <>
146   struct PixelTraits<PixelFormat_Grayscale32> :
147     public IntegerPixelTraits<PixelFormat_Grayscale32, uint32_t>
148   {
149   };
150 
151 
152   template <>
153   struct PixelTraits<PixelFormat_Grayscale64> :
154     public IntegerPixelTraits<PixelFormat_Grayscale64, uint64_t>
155   {
156   };
157 
158 
159   template <>
160   struct PixelTraits<PixelFormat_RGB24>
161   {
162     struct PixelType
163     {
164       uint8_t  red_;
165       uint8_t  green_;
166       uint8_t  blue_;
167     };
168 
169     ORTHANC_FORCE_INLINE
170     static PixelFormat GetPixelFormat()
171     {
172       return PixelFormat_RGB24;
173     }
174 
175     ORTHANC_FORCE_INLINE
176     static void SetZero(PixelType& target)
177     {
178       target.red_ = 0;
179       target.green_ = 0;
180       target.blue_ = 0;
181     }
182 
183     ORTHANC_FORCE_INLINE
184     static void Copy(PixelType& target,
185                      const PixelType& source)
186     {
187       target.red_ = source.red_;
188       target.green_ = source.green_;
189       target.blue_ = source.blue_;
190     }
191 
192     ORTHANC_FORCE_INLINE
193     static bool IsEqual(const PixelType& a,
194                         const PixelType& b)
195     {
196       return (a.red_ == b.red_ &&
197               a.green_ == b.green_ &&
198               a.blue_ == b.blue_);
199     }
200 
201     ORTHANC_FORCE_INLINE
202     static void FloatToPixel(PixelType& target,
203                              float value)
204     {
205       uint8_t v;
206       PixelTraits<PixelFormat_Grayscale8>::FloatToPixel(v, value);
207 
208       target.red_ = v;
209       target.green_ = v;
210       target.blue_ = v;
211     }
212   };
213 
214 
215   template <>
216   struct PixelTraits<PixelFormat_BGRA32>
217   {
218     struct PixelType
219     {
220       uint8_t  blue_;
221       uint8_t  green_;
222       uint8_t  red_;
223       uint8_t  alpha_;
224     };
225 
226     ORTHANC_FORCE_INLINE
227     static PixelFormat GetPixelFormat()
228     {
229       return PixelFormat_BGRA32;
230     }
231 
232     ORTHANC_FORCE_INLINE
233     static void SetZero(PixelType& target)
234     {
235       target.blue_ = 0;
236       target.green_ = 0;
237       target.red_ = 0;
238       target.alpha_ = 0;
239     }
240 
241     ORTHANC_FORCE_INLINE
242     static void Copy(PixelType& target,
243                      const PixelType& source)
244     {
245       target.blue_ = source.blue_;
246       target.green_ = source.green_;
247       target.red_ = source.red_;
248       target.alpha_ = source.alpha_;
249     }
250 
251     ORTHANC_FORCE_INLINE
252     static bool IsEqual(const PixelType& a,
253                         const PixelType& b)
254     {
255       return (a.blue_ == b.blue_ &&
256               a.green_ == b.green_ &&
257               a.red_ == b.red_ &&
258               a.alpha_ == b.alpha_);
259     }
260 
261     ORTHANC_FORCE_INLINE
262     static void FloatToPixel(PixelType& target,
263                              float value)
264     {
265       uint8_t v;
266       PixelTraits<PixelFormat_Grayscale8>::FloatToPixel(v, value);
267 
268       target.blue_ = v;
269       target.green_ = v;
270       target.red_ = v;
271       target.alpha_ = 255;
272     }
273   };
274 
275 
276   template <>
277   struct PixelTraits<PixelFormat_RGBA32>
278   {
279     struct PixelType
280     {
281       uint8_t  red_;
282       uint8_t  green_;
283       uint8_t  blue_;
284       uint8_t  alpha_;
285     };
286 
287     ORTHANC_FORCE_INLINE
288     static PixelFormat GetPixelFormat()
289     {
290       return PixelFormat_RGBA32;
291     }
292 
293     ORTHANC_FORCE_INLINE
294     static void SetZero(PixelType& target)
295     {
296       target.red_ = 0;
297       target.green_ = 0;
298       target.blue_ = 0;
299       target.alpha_ = 0;
300     }
301 
302     ORTHANC_FORCE_INLINE
303     static void Copy(PixelType& target,
304                      const PixelType& source)
305     {
306       target.red_ = source.red_;
307       target.green_ = source.green_;
308       target.blue_ = source.blue_;
309       target.alpha_ = source.alpha_;
310     }
311 
312     ORTHANC_FORCE_INLINE
313     static bool IsEqual(const PixelType& a,
314                         const PixelType& b)
315     {
316       return (a.red_ == b.red_ &&
317               a.green_ == b.green_ &&
318               a.blue_ == b.blue_ &&
319               a.alpha_ == b.alpha_);
320     }
321 
322     ORTHANC_FORCE_INLINE
323     static void FloatToPixel(PixelType& target,
324                              float value)
325     {
326       uint8_t v;
327       PixelTraits<PixelFormat_Grayscale8>::FloatToPixel(v, value);
328 
329       target.red_ = v;
330       target.green_ = v;
331       target.blue_ = v;
332       target.alpha_ = 255;
333     }
334   };
335 
336 
337   template <>
338   struct PixelTraits<PixelFormat_Float32>
339   {
340     typedef float  PixelType;
341 
342     ORTHANC_FORCE_INLINE
343     static PixelFormat GetPixelFormat()
344     {
345       return PixelFormat_Float32;
346     }
347 
348     ORTHANC_FORCE_INLINE
349     static void SetZero(PixelType& target)
350     {
351       target = 0.0f;
352     }
353 
354     ORTHANC_FORCE_INLINE
355     static void Copy(PixelType& target,
356                      const PixelType& source)
357     {
358       target = source;
359     }
360 
361     ORTHANC_FORCE_INLINE
362     static bool IsEqual(const PixelType& a,
363                         const PixelType& b)
364     {
365       float tmp = (a - b);
366 
367       if (tmp < 0)
368       {
369         tmp = -tmp;
370       }
371 
372       return tmp <= std::numeric_limits<float>::epsilon();
373     }
374 
375     ORTHANC_FORCE_INLINE
376     static void SetMinValue(PixelType& target)
377     {
378       // std::numeric_limits<float>::lowest is not supported on
379       // all compilers (for instance, Visual Studio 9.0 2008)
380       target = -std::numeric_limits<float>::max();
381     }
382 
383     ORTHANC_FORCE_INLINE
384     static void SetMaxValue(PixelType& target)
385     {
386       target = std::numeric_limits<float>::max();
387     }
388 
389     ORTHANC_FORCE_INLINE
390     static void FloatToPixel(PixelType& target,
391                              float value)
392     {
393       target = value;
394     }
395 
396     ORTHANC_FORCE_INLINE
397     static float PixelToFloat(const PixelType& source)
398     {
399       return source;
400     }
401   };
402 }
403