Mercurial > hg > orthanc
changeset 4065:d6362b2c4b61 framework
export dcmdata in shared library, rounding in convolution tests
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 11 Jun 2020 18:04:28 +0200 |
parents | e00f3d089991 |
children | 3a59a021b5de |
files | OrthancFramework/SharedLibrary/CMakeLists.txt OrthancFramework/Sources/Images/ImageProcessing.cpp OrthancFramework/Sources/Images/ImageProcessing.h OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp OrthancFramework/UnitTestsSources/ImageProcessingTests.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp |
diffstat | 6 files changed, 121 insertions(+), 73 deletions(-) [+] |
line wrap: on
line diff
--- 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()
--- 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<float>(*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<TargetType>(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 <typename RawPixel, unsigned int ChannelsCount> + template <typename RawPixel, unsigned int ChannelsCount, bool UseRound> static void SeparableConvolutionFloat(ImageAccessor& image /* inplace */, const std::vector<float>& horizontal, size_t horizontalAnchor, @@ -2335,7 +2337,15 @@ } else { - *p = static_cast<RawPixel>(accumulator); + if (UseRound) + { + assert(sizeof(RawPixel) < sizeof(int)); + *p = static_cast<RawPixel>(boost::math::iround(accumulator)); + } + else + { + *p = static_cast<RawPixel>(accumulator); + } } } } @@ -2347,7 +2357,8 @@ const std::vector<float>& horizontal, size_t horizontalAnchor, const std::vector<float>& 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<uint8_t, 1u> - (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + if (useRound) + { + SeparableConvolutionFloat<uint8_t, 1u, true> + (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + } + else + { + SeparableConvolutionFloat<uint8_t, 1u, false> + (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + } break; case PixelFormat_RGB24: - SeparableConvolutionFloat<uint8_t, 3u> - (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + if (useRound) + { + SeparableConvolutionFloat<uint8_t, 3u, true> + (image, horizontal, horizontalAnchor, vertical, verticalAnchor, normalization); + } + else + { + SeparableConvolutionFloat<uint8_t, 3u, false> + (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<float> 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<unsigned int>(boost::math::iround(cw * r)), target.GetWidth()); unsigned int sh = std::min(static_cast<unsigned int>(boost::math::iround(ch * r)), target.GetHeight()); + Image resized(target.GetFormat(), sw, sh, false); //ImageProcessing::SmoothGaussian5x5(source);
--- 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<float>& horizontal, size_t horizontalAnchor, const std::vector<float>& 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);
--- 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);
--- 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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<ImageAccessor> 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)); }
--- 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);