# HG changeset patch # User Sebastien Jodogne # Date 1591891468 -7200 # Node ID d6362b2c4b61b3acd7ac35e62e468f7e421f47fe # Parent e00f3d089991aa5804b175e0ce6ba79c0b90571c export dcmdata in shared library, rounding in convolution tests diff -r e00f3d089991 -r d6362b2c4b61 OrthancFramework/SharedLibrary/CMakeLists.txt --- a/OrthancFramework/SharedLibrary/CMakeLists.txt Thu Jun 11 16:40:34 2020 +0200 +++ b/OrthancFramework/SharedLibrary/CMakeLists.txt Thu Jun 11 18:04:28 2020 +0200 @@ -85,6 +85,12 @@ set(ORTHANC_STATIC_PUGIXML OFF) endif() +if (STATIC_BUILD OR NOT USE_SYSTEM_DCMTK) + set(ORTHANC_STATIC_DCMTK ON) +else() + set(ORTHANC_STATIC_DCMTK OFF) +endif() + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") @@ -141,6 +147,13 @@ ) endif() endif() + + # Control the visibility of DCMTK: We only export the "dcmdata" module + if (ORTHANC_STATIC_DCMTK) + set_source_files_properties(${DCMTK_SOURCES} + PROPERTIES COMPILE_DEFINITIONS "DCMTK_BUILD_IN_PROGRESS;DCMTK_BUILD_SINGLE_SHARED_LIBRARY;DCMTK_SHARED;HAVE_HIDDEN_VISIBILITY;dcmdata_EXPORTS" + ) + endif() endif() diff -r e00f3d089991 -r d6362b2c4b61 OrthancFramework/Sources/Images/ImageProcessing.cpp --- a/OrthancFramework/Sources/Images/ImageProcessing.cpp Thu Jun 11 16:40:34 2020 +0200 +++ b/OrthancFramework/Sources/Images/ImageProcessing.cpp Thu Jun 11 18:04:28 2020 +0200 @@ -366,6 +366,7 @@ int64_t v; if (UseRound) { + assert(sizeof(long long) == sizeof(int64_t)); // The "round" operation is very costly v = boost::math::llround(static_cast(*p) * factor); } @@ -442,8 +443,9 @@ *p = minPixelValue; } else if (UseRound) - { + { // The "round" operation is very costly + assert(sizeof(TargetType) < sizeof(int)); *p = static_cast(boost::math::iround(v)); } else @@ -2197,7 +2199,7 @@ // floating-point arithmetics, and an intermediate Float32 // image. The out-of-image values are taken as the border // value. Further optimization is possible. - template + template static void SeparableConvolutionFloat(ImageAccessor& image /* inplace */, const std::vector& horizontal, size_t horizontalAnchor, @@ -2335,7 +2337,15 @@ } else { - *p = static_cast(accumulator); + if (UseRound) + { + assert(sizeof(RawPixel) < sizeof(int)); + *p = static_cast(boost::math::iround(accumulator)); + } + else + { + *p = static_cast(accumulator); + } } } } @@ -2347,7 +2357,8 @@ const std::vector& horizontal, size_t horizontalAnchor, const std::vector& vertical, - size_t verticalAnchor) + size_t verticalAnchor, + bool useRound) { if (horizontal.size() == 0 || vertical.size() == 0 || @@ -2390,13 +2401,29 @@ switch (image.GetFormat()) { case PixelFormat_Grayscale8: - SeparableConvolutionFloat - (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + if (useRound) + { + SeparableConvolutionFloat + (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + } + else + { + SeparableConvolutionFloat + (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + } break; case PixelFormat_RGB24: - SeparableConvolutionFloat - (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + if (useRound) + { + SeparableConvolutionFloat + (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + } + else + { + SeparableConvolutionFloat + (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + } break; default: @@ -2405,7 +2432,8 @@ } - void ImageProcessing::SmoothGaussian5x5(ImageAccessor& image) + void ImageProcessing::SmoothGaussian5x5(ImageAccessor& image, + bool useRound) { std::vector kernel(5); kernel[0] = 1; @@ -2414,7 +2442,7 @@ kernel[3] = 4; kernel[4] = 1; - SeparableConvolution(image, kernel, 2, kernel, 2); + SeparableConvolution(image, kernel, 2, kernel, 2, useRound); } @@ -2445,6 +2473,7 @@ unsigned int sw = std::min(static_cast(boost::math::iround(cw * r)), target.GetWidth()); unsigned int sh = std::min(static_cast(boost::math::iround(ch * r)), target.GetHeight()); + Image resized(target.GetFormat(), sw, sh, false); //ImageProcessing::SmoothGaussian5x5(source); diff -r e00f3d089991 -r d6362b2c4b61 OrthancFramework/Sources/Images/ImageProcessing.h --- a/OrthancFramework/Sources/Images/ImageProcessing.h Thu Jun 11 16:40:34 2020 +0200 +++ b/OrthancFramework/Sources/Images/ImageProcessing.h Thu Jun 11 18:04:28 2020 +0200 @@ -184,9 +184,11 @@ const std::vector& horizontal, size_t horizontalAnchor, const std::vector& vertical, - size_t verticalAnchor); + size_t verticalAnchor, + bool useRound /* this is expensive */); - static void SmoothGaussian5x5(ImageAccessor& image); + static void SmoothGaussian5x5(ImageAccessor& image, + bool useRound /* this is expensive */); static void FitSize(ImageAccessor& target, const ImageAccessor& source); diff -r e00f3d089991 -r d6362b2c4b61 OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp --- a/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp Thu Jun 11 16:40:34 2020 +0200 +++ b/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp Thu Jun 11 18:04:28 2020 +0200 @@ -2179,7 +2179,7 @@ a == DicomTransferSyntax_JPEGProcess2_4 || a == DicomTransferSyntax_JPEGLSLossy); - printf("SIZE: %lu\n", t.size()); + printf("SIZE: %u\n", t.size()); if (sourceUid == IDicomTranscoder::GetSopInstanceUid(target.GetParsed())) { ASSERT_FALSE(lossy); diff -r e00f3d089991 -r d6362b2c4b61 OrthancFramework/UnitTestsSources/ImageProcessingTests.cpp --- a/OrthancFramework/UnitTestsSources/ImageProcessingTests.cpp Thu Jun 11 16:40:34 2020 +0200 +++ b/OrthancFramework/UnitTestsSources/ImageProcessingTests.cpp Thu Jun 11 18:04:28 2020 +0200 @@ -523,26 +523,26 @@ { Image image(PixelFormat_Grayscale8, 1, 1, false); SetGrayscale8Pixel(image, 0, 0, 100); - ImageProcessing::SeparableConvolution(image, k1, 2, k2, 0); + ImageProcessing::SeparableConvolution(image, k1, 2, k2, 0, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100)); - ImageProcessing::SeparableConvolution(image, k1, 2, k1, 2); + ImageProcessing::SeparableConvolution(image, k1, 2, k1, 2, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100)); - ImageProcessing::SeparableConvolution(image, k2, 0, k1, 2); + ImageProcessing::SeparableConvolution(image, k2, 0, k1, 2, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100)); - ImageProcessing::SeparableConvolution(image, k2, 0, k2, 0); + ImageProcessing::SeparableConvolution(image, k2, 0, k2, 0, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100)); } { Image image(PixelFormat_RGB24, 1, 1, false); SetRGB24Pixel(image, 0, 0, 10, 20, 30); - ImageProcessing::SeparableConvolution(image, k1, 2, k2, 0); + ImageProcessing::SeparableConvolution(image, k1, 2, k2, 0, true /* round */); ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30)); - ImageProcessing::SeparableConvolution(image, k1, 2, k1, 2); + ImageProcessing::SeparableConvolution(image, k1, 2, k1, 2, true /* round */); ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30)); - ImageProcessing::SeparableConvolution(image, k2, 0, k1, 2); + ImageProcessing::SeparableConvolution(image, k2, 0, k1, 2, true /* round */); ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30)); - ImageProcessing::SeparableConvolution(image, k2, 0, k2, 0); + ImageProcessing::SeparableConvolution(image, k2, 0, k2, 0, true /* round */); ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30)); } @@ -553,7 +553,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0); + ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 1, 0, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 2, 0, 20)); @@ -567,7 +567,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2); + ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 1, 0, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 2, 0, 0)); @@ -581,7 +581,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0); + ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 1, 0, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 2, 0, 0)); @@ -601,7 +601,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2); + ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 1, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 2, 20)); @@ -615,7 +615,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0); + ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 1, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 2, 0)); @@ -629,7 +629,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0); + ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0, true /* round */); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 1, 0)); ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 2, 0)); @@ -649,7 +649,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0); + ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0, true /* round */); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 1, 0, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 2, 0, 20, 24, 28)); @@ -663,7 +663,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2); + ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2, true /* round */); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 1, 0, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 2, 0, 0, 0, 0)); @@ -677,7 +677,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0); + ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0, true /* round */); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 1, 0, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 2, 0, 0, 0, 0)); @@ -697,7 +697,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2); + ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2, true /* round */); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 1, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 2, 20, 24, 28)); @@ -711,7 +711,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0); + ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0, true /* round */); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 1, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 2, 0, 0, 0)); @@ -725,7 +725,7 @@ { std::unique_ptr image(Image::Clone(dirac)); - ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0); + ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0, true /* round */); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 1, 0, 0, 0)); ASSERT_TRUE(TestRGB24Pixel(*image, 0, 2, 0, 0, 0)); @@ -755,32 +755,33 @@ Image image(PixelFormat_Grayscale8, 5, 5, false); ImageProcessing::Set(image, 0); SetGrayscale8Pixel(image, 2, 2, 100); - ImageProcessing::SmoothGaussian5x5(image); + ImageProcessing::SmoothGaussian5x5(image, true /* round */); + // In Octave: round(conv2([1 4 6 4 1],[1 4 6 4 1]')/256*100) ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 0)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 0, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 0, 2)); ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 0, 2)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 0, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 0, 2)); ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 0, 0)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 1, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 1, 2)); ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 1, 6)); ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 1, 9)); ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 1, 6)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 1, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 1, 2)); ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 2, 2)); ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 2, 9)); ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 2, 14)); ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 2, 9)); ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 2, 2)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 3, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 3, 2)); ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 3, 6)); ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 3, 9)); ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 3, 6)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 3, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 3, 2)); ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 4, 0)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 4, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 4, 2)); ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 4, 2)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 4, 1)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 4, 2)); ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 4, 0)); } @@ -788,33 +789,36 @@ Image image(PixelFormat_RGB24, 5, 5, false); ImageProcessing::Set(image, 0); SetRGB24Pixel(image, 2, 2, 100, 100, 200); - ImageProcessing::SmoothGaussian5x5(image); + ImageProcessing::SmoothGaussian5x5(image, true /* round */); - ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 0, 0, 0)); - ASSERT_TRUE(TestRGB24Pixel(image, 1, 0, 1, 1, 3)); - ASSERT_TRUE(TestRGB24Pixel(image, 2, 0, 2, 2, 4)); - ASSERT_TRUE(TestRGB24Pixel(image, 3, 0, 1, 1, 3)); - ASSERT_TRUE(TestRGB24Pixel(image, 4, 0, 0, 0, 0)); - ASSERT_TRUE(TestRGB24Pixel(image, 0, 1, 1, 1, 3)); - ASSERT_TRUE(TestRGB24Pixel(image, 1, 1, 6, 6, 12)); - ASSERT_TRUE(TestRGB24Pixel(image, 2, 1, 9, 9, 18)); - ASSERT_TRUE(TestRGB24Pixel(image, 3, 1, 6, 6, 12)); - ASSERT_TRUE(TestRGB24Pixel(image, 4, 1, 1, 1, 3)); - ASSERT_TRUE(TestRGB24Pixel(image, 0, 2, 2, 2, 4)); - ASSERT_TRUE(TestRGB24Pixel(image, 1, 2, 9, 9, 18)); + // In Octave: + // R,G = round(conv2([1 4 6 4 1],[1 4 6 4 1]')/256*100) + // B = round(conv2([1 4 6 4 1],[1 4 6 4 1]')/256*200) + ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 0, 0, 1)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 0, 2, 2, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 2, 0, 2, 2, 5)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 0, 2, 2, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 0, 0, 0, 1)); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 1, 2, 2, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 1, 6, 6, 13)); + ASSERT_TRUE(TestRGB24Pixel(image, 2, 1, 9, 9, 19)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 1, 6, 6, 13)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 1, 2, 2, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 2, 2, 2, 5)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 2, 9, 9, 19)); ASSERT_TRUE(TestRGB24Pixel(image, 2, 2, 14, 14, 28)); - ASSERT_TRUE(TestRGB24Pixel(image, 3, 2, 9, 9, 18)); - ASSERT_TRUE(TestRGB24Pixel(image, 4, 2, 2, 2, 4)); - ASSERT_TRUE(TestRGB24Pixel(image, 0, 3, 1, 1, 3)); - ASSERT_TRUE(TestRGB24Pixel(image, 1, 3, 6, 6, 12)); - ASSERT_TRUE(TestRGB24Pixel(image, 2, 3, 9, 9, 18)); - ASSERT_TRUE(TestRGB24Pixel(image, 3, 3, 6, 6, 12)); - ASSERT_TRUE(TestRGB24Pixel(image, 4, 3, 1, 1, 3)); - ASSERT_TRUE(TestRGB24Pixel(image, 0, 4, 0, 0, 0)); - ASSERT_TRUE(TestRGB24Pixel(image, 1, 4, 1, 1, 3)); - ASSERT_TRUE(TestRGB24Pixel(image, 2, 4, 2, 2, 4)); - ASSERT_TRUE(TestRGB24Pixel(image, 3, 4, 1, 1, 3)); - ASSERT_TRUE(TestRGB24Pixel(image, 4, 4, 0, 0, 0)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 2, 9, 9, 19)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 2, 2, 2, 5)); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 3, 2, 2, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 3, 6, 6, 13)); + ASSERT_TRUE(TestRGB24Pixel(image, 2, 3, 9, 9, 19)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 3, 6, 6, 13)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 3, 2, 2, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 0, 4, 0, 0, 1)); + ASSERT_TRUE(TestRGB24Pixel(image, 1, 4, 2, 2, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 2, 4, 2, 2, 5)); + ASSERT_TRUE(TestRGB24Pixel(image, 3, 4, 2, 2, 3)); + ASSERT_TRUE(TestRGB24Pixel(image, 4, 4, 0, 0, 1)); } } @@ -974,10 +978,10 @@ SetGrayscale8Pixel(image, 4, 0, 255); ImageProcessing::ShiftScale(image, -1.1f, 1.5f, true); - ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 0)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 0, 1)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 0, 6)); - ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 0, 13)); + ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 0)); // (0 - 1.1) * 1.5 = -1.65 ==> 0 + ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 0, 1)); // (2 - 1.1) * 1.5 = 1.35 => 1 + ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 0, 6)); // (5 - 1.1) * 1.5 = 5.85 => 6 + ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 0, 13)); // (10 - 1.1) * 1.5 = 13.35 => 13 ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 0, 255)); } diff -r e00f3d089991 -r d6362b2c4b61 OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Thu Jun 11 16:40:34 2020 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Thu Jun 11 18:04:28 2020 +0200 @@ -860,7 +860,7 @@ (targetWidth < decoded->GetWidth() || targetHeight < decoded->GetHeight())) { - ImageProcessing::SmoothGaussian5x5(*decoded); + ImageProcessing::SmoothGaussian5x5(*decoded, false /* be fast, don't round */); } ImageProcessing::Resize(*resized, *decoded); @@ -906,7 +906,7 @@ (targetWidth < decoded->GetWidth() || targetHeight < decoded->GetHeight())) { - ImageProcessing::SmoothGaussian5x5(*rescaled); + ImageProcessing::SmoothGaussian5x5(*rescaled, false /* be fast, don't round */); } ImageProcessing::Resize(*resized, *rescaled);