comparison Core/Images/ImageProcessing.cpp @ 3525:8c66c9c2257b

fix ImageProcessing::ShiftScale() on float images
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 25 Sep 2019 17:16:54 +0200
parents b2d4dd16dae8
children 551945086617
comparison
equal deleted inserted replaced
3524:d96379a965de 3525:8c66c9c2257b
58 58
59 template <typename TargetType, typename SourceType> 59 template <typename TargetType, typename SourceType>
60 static void ConvertInternal(ImageAccessor& target, 60 static void ConvertInternal(ImageAccessor& target,
61 const ImageAccessor& source) 61 const ImageAccessor& source)
62 { 62 {
63 // WARNING - "::min()" should be replaced by "::lowest()" if
64 // dealing with float or double (which is not the case so far)
65 assert(sizeof(TargetType) <= 2); // Safeguard to remember about "float/double"
63 const TargetType minValue = std::numeric_limits<TargetType>::min(); 66 const TargetType minValue = std::numeric_limits<TargetType>::min();
64 const TargetType maxValue = std::numeric_limits<TargetType>::max(); 67 const TargetType maxValue = std::numeric_limits<TargetType>::max();
65 68
66 const unsigned int width = source.GetWidth(); 69 const unsigned int width = source.GetWidth();
67 const unsigned int height = source.GetHeight(); 70 const unsigned int height = source.GetHeight();
140 static void ConvertColorToGrayscale(ImageAccessor& target, 143 static void ConvertColorToGrayscale(ImageAccessor& target,
141 const ImageAccessor& source) 144 const ImageAccessor& source)
142 { 145 {
143 assert(source.GetFormat() == PixelFormat_RGB24); 146 assert(source.GetFormat() == PixelFormat_RGB24);
144 147
148 // WARNING - "::min()" should be replaced by "::lowest()" if
149 // dealing with float or double (which is not the case so far)
150 assert(sizeof(TargetType) <= 2); // Safeguard to remember about "float/double"
145 const TargetType minValue = std::numeric_limits<TargetType>::min(); 151 const TargetType minValue = std::numeric_limits<TargetType>::min();
146 const TargetType maxValue = std::numeric_limits<TargetType>::max(); 152 const TargetType maxValue = std::numeric_limits<TargetType>::max();
147 153
148 const unsigned int width = source.GetWidth(); 154 const unsigned int width = source.GetWidth();
149 const unsigned int height = source.GetHeight(); 155 const unsigned int height = source.GetHeight();
225 231
226 232
227 template <typename PixelType> 233 template <typename PixelType>
228 static void GetMinMaxValueInternal(PixelType& minValue, 234 static void GetMinMaxValueInternal(PixelType& minValue,
229 PixelType& maxValue, 235 PixelType& maxValue,
230 const ImageAccessor& source) 236 const ImageAccessor& source,
237 const PixelType LowestValue = std::numeric_limits<PixelType>::min())
231 { 238 {
232 // Deal with the special case of empty image 239 // Deal with the special case of empty image
233 if (source.GetWidth() == 0 || 240 if (source.GetWidth() == 0 ||
234 source.GetHeight() == 0) 241 source.GetHeight() == 0)
235 { 242 {
237 maxValue = 0; 244 maxValue = 0;
238 return; 245 return;
239 } 246 }
240 247
241 minValue = std::numeric_limits<PixelType>::max(); 248 minValue = std::numeric_limits<PixelType>::max();
242 maxValue = std::numeric_limits<PixelType>::min(); 249 maxValue = LowestValue;
243 250
244 const unsigned int height = source.GetHeight(); 251 const unsigned int height = source.GetHeight();
245 const unsigned int width = source.GetWidth(); 252 const unsigned int width = source.GetWidth();
246 253
247 for (unsigned int y = 0; y < height; y++) 254 for (unsigned int y = 0; y < height; y++)
272 if (constant == 0) 279 if (constant == 0)
273 { 280 {
274 return; 281 return;
275 } 282 }
276 283
284 // WARNING - "::min()" should be replaced by "::lowest()" if
285 // dealing with float or double (which is not the case so far)
286 assert(sizeof(PixelType) <= 2); // Safeguard to remember about "float/double"
277 const int64_t minValue = std::numeric_limits<PixelType>::min(); 287 const int64_t minValue = std::numeric_limits<PixelType>::min();
278 const int64_t maxValue = std::numeric_limits<PixelType>::max(); 288 const int64_t maxValue = std::numeric_limits<PixelType>::max();
279 289
280 const unsigned int width = image.GetWidth(); 290 const unsigned int width = image.GetWidth();
281 const unsigned int height = image.GetHeight(); 291 const unsigned int height = image.GetHeight();
314 if (std::abs(factor - 1.0f) <= std::numeric_limits<float>::epsilon()) 324 if (std::abs(factor - 1.0f) <= std::numeric_limits<float>::epsilon())
315 { 325 {
316 return; 326 return;
317 } 327 }
318 328
329 // WARNING - "::min()" should be replaced by "::lowest()" if
330 // dealing with float or double (which is not the case so far)
331 assert(sizeof(PixelType) <= 2); // Safeguard to remember about "float/double"
319 const int64_t minValue = std::numeric_limits<PixelType>::min(); 332 const int64_t minValue = std::numeric_limits<PixelType>::min();
320 const int64_t maxValue = std::numeric_limits<PixelType>::max(); 333 const int64_t maxValue = std::numeric_limits<PixelType>::max();
321 334
322 const unsigned int width = image.GetWidth(); 335 const unsigned int width = image.GetWidth();
323 const unsigned int height = image.GetHeight(); 336 const unsigned int height = image.GetHeight();
358 371
359 template <typename PixelType, 372 template <typename PixelType,
360 bool UseRound> 373 bool UseRound>
361 static void ShiftScaleInternal(ImageAccessor& image, 374 static void ShiftScaleInternal(ImageAccessor& image,
362 float offset, 375 float offset,
363 float scaling) 376 float scaling,
364 { 377 const PixelType LowestValue = std::numeric_limits<PixelType>::min())
365 const float minFloatValue = static_cast<float>(std::numeric_limits<PixelType>::min()); 378 {
366 const float maxFloatValue = static_cast<float>(std::numeric_limits<PixelType>::max()); 379 const PixelType minPixelValue = LowestValue;
367 const PixelType minPixelValue = std::numeric_limits<PixelType>::min();
368 const PixelType maxPixelValue = std::numeric_limits<PixelType>::max(); 380 const PixelType maxPixelValue = std::numeric_limits<PixelType>::max();
381 const float minFloatValue = static_cast<float>(LowestValue);
382 const float maxFloatValue = static_cast<float>(maxPixelValue);
369 383
370 const unsigned int height = image.GetHeight(); 384 const unsigned int height = image.GetHeight();
371 const unsigned int width = image.GetWidth(); 385 const unsigned int width = image.GetWidth();
372 386
373 for (unsigned int y = 0; y < height; y++) 387 for (unsigned int y = 0; y < height; y++)
967 { 981 {
968 case PixelFormat_Float32: 982 case PixelFormat_Float32:
969 { 983 {
970 assert(sizeof(float) == 4); 984 assert(sizeof(float) == 4);
971 float a, b; 985 float a, b;
972 GetMinMaxValueInternal<float>(a, b, image); 986
987 /**
988 * WARNING - On floating-point types, the minimal value is
989 * "-FLT_MAX" (as implemented by "::lowest()"), not "FLT_MIN"
990 * (as implemented by "::min()")
991 * https://en.cppreference.com/w/cpp/types/numeric_limits
992 **/
993 GetMinMaxValueInternal<float>(a, b, image, -std::numeric_limits<float>::max());
973 minValue = a; 994 minValue = a;
974 maxValue = b; 995 maxValue = b;
975 break; 996 break;
976 } 997 }
977 998
1091 return; 1112 return;
1092 1113
1093 case PixelFormat_Float32: 1114 case PixelFormat_Float32:
1094 if (useRound) 1115 if (useRound)
1095 { 1116 {
1096 ShiftScaleInternal<float, true>(image, offset, scaling); 1117 ShiftScaleInternal<float, true>(image, offset, scaling, -std::numeric_limits<float>::max());
1097 } 1118 }
1098 else 1119 else
1099 { 1120 {
1100 ShiftScaleInternal<float, false>(image, offset, scaling); 1121 ShiftScaleInternal<float, false>(image, offset, scaling, -std::numeric_limits<float>::max());
1101 } 1122 }
1102 return; 1123 return;
1103 1124
1104 default: 1125 default:
1105 throw OrthancException(ErrorCode_NotImplemented); 1126 throw OrthancException(ErrorCode_NotImplemented);
1830 size_t horizontalAnchor, 1851 size_t horizontalAnchor,
1831 const std::vector<float>& vertical, 1852 const std::vector<float>& vertical,
1832 size_t verticalAnchor, 1853 size_t verticalAnchor,
1833 float normalization) 1854 float normalization)
1834 { 1855 {
1856 // WARNING - "::min()" should be replaced by "::lowest()" if
1857 // dealing with float or double (which is not the case so far)
1858 assert(sizeof(RawPixel) <= 2); // Safeguard to remember about "float/double"
1859
1835 const unsigned int width = image.GetWidth(); 1860 const unsigned int width = image.GetWidth();
1836 const unsigned int height = image.GetHeight(); 1861 const unsigned int height = image.GetHeight();
1837 1862
1838 1863
1839 /** 1864 /**