# HG changeset patch # User Sebastien Jodogne # Date 1569424614 -7200 # Node ID 8c66c9c2257b03392ad6c61f56dec8189ddb0713 # Parent d96379a965dea008c844da70ad437af822967bb6 fix ImageProcessing::ShiftScale() on float images diff -r d96379a965de -r 8c66c9c2257b Core/DicomParsing/Internals/DicomImageDecoder.cpp --- a/Core/DicomParsing/Internals/DicomImageDecoder.cpp Tue Sep 24 18:06:56 2019 +0200 +++ b/Core/DicomParsing/Internals/DicomImageDecoder.cpp Wed Sep 25 17:16:54 2019 +0200 @@ -357,6 +357,8 @@ static void CopyPixels(ImageAccessor& target, const DicomIntegerPixelAccessor& source) { + // WARNING - "::min()" should be replaced by "::lowest()" if + // dealing with float or double (which is not the case so far) const PixelType minValue = std::numeric_limits::min(); const PixelType maxValue = std::numeric_limits::max(); diff -r d96379a965de -r 8c66c9c2257b Core/Images/ImageProcessing.cpp --- a/Core/Images/ImageProcessing.cpp Tue Sep 24 18:06:56 2019 +0200 +++ b/Core/Images/ImageProcessing.cpp Wed Sep 25 17:16:54 2019 +0200 @@ -60,6 +60,9 @@ static void ConvertInternal(ImageAccessor& target, const ImageAccessor& source) { + // WARNING - "::min()" should be replaced by "::lowest()" if + // dealing with float or double (which is not the case so far) + assert(sizeof(TargetType) <= 2); // Safeguard to remember about "float/double" const TargetType minValue = std::numeric_limits::min(); const TargetType maxValue = std::numeric_limits::max(); @@ -142,6 +145,9 @@ { assert(source.GetFormat() == PixelFormat_RGB24); + // WARNING - "::min()" should be replaced by "::lowest()" if + // dealing with float or double (which is not the case so far) + assert(sizeof(TargetType) <= 2); // Safeguard to remember about "float/double" const TargetType minValue = std::numeric_limits::min(); const TargetType maxValue = std::numeric_limits::max(); @@ -227,7 +233,8 @@ template static void GetMinMaxValueInternal(PixelType& minValue, PixelType& maxValue, - const ImageAccessor& source) + const ImageAccessor& source, + const PixelType LowestValue = std::numeric_limits::min()) { // Deal with the special case of empty image if (source.GetWidth() == 0 || @@ -239,7 +246,7 @@ } minValue = std::numeric_limits::max(); - maxValue = std::numeric_limits::min(); + maxValue = LowestValue; const unsigned int height = source.GetHeight(); const unsigned int width = source.GetWidth(); @@ -274,6 +281,9 @@ return; } + // WARNING - "::min()" should be replaced by "::lowest()" if + // dealing with float or double (which is not the case so far) + assert(sizeof(PixelType) <= 2); // Safeguard to remember about "float/double" const int64_t minValue = std::numeric_limits::min(); const int64_t maxValue = std::numeric_limits::max(); @@ -316,6 +326,9 @@ return; } + // WARNING - "::min()" should be replaced by "::lowest()" if + // dealing with float or double (which is not the case so far) + assert(sizeof(PixelType) <= 2); // Safeguard to remember about "float/double" const int64_t minValue = std::numeric_limits::min(); const int64_t maxValue = std::numeric_limits::max(); @@ -360,12 +373,13 @@ bool UseRound> static void ShiftScaleInternal(ImageAccessor& image, float offset, - float scaling) + float scaling, + const PixelType LowestValue = std::numeric_limits::min()) { - const float minFloatValue = static_cast(std::numeric_limits::min()); - const float maxFloatValue = static_cast(std::numeric_limits::max()); - const PixelType minPixelValue = std::numeric_limits::min(); + const PixelType minPixelValue = LowestValue; const PixelType maxPixelValue = std::numeric_limits::max(); + const float minFloatValue = static_cast(LowestValue); + const float maxFloatValue = static_cast(maxPixelValue); const unsigned int height = image.GetHeight(); const unsigned int width = image.GetWidth(); @@ -969,7 +983,14 @@ { assert(sizeof(float) == 4); float a, b; - GetMinMaxValueInternal(a, b, image); + + /** + * WARNING - On floating-point types, the minimal value is + * "-FLT_MAX" (as implemented by "::lowest()"), not "FLT_MIN" + * (as implemented by "::min()") + * https://en.cppreference.com/w/cpp/types/numeric_limits + **/ + GetMinMaxValueInternal(a, b, image, -std::numeric_limits::max()); minValue = a; maxValue = b; break; @@ -1093,11 +1114,11 @@ case PixelFormat_Float32: if (useRound) { - ShiftScaleInternal(image, offset, scaling); + ShiftScaleInternal(image, offset, scaling, -std::numeric_limits::max()); } else { - ShiftScaleInternal(image, offset, scaling); + ShiftScaleInternal(image, offset, scaling, -std::numeric_limits::max()); } return; @@ -1832,6 +1853,10 @@ size_t verticalAnchor, float normalization) { + // WARNING - "::min()" should be replaced by "::lowest()" if + // dealing with float or double (which is not the case so far) + assert(sizeof(RawPixel) <= 2); // Safeguard to remember about "float/double" + const unsigned int width = image.GetWidth(); const unsigned int height = image.GetHeight();