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