comparison Core/Images/ImageProcessing.cpp @ 2488:345725b9350c

back to rounding to fix integration tests
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 13 Mar 2018 17:02:30 +0100
parents be1dbb1dcdd6
children e91bab2d8c75
comparison
equal deleted inserted replaced
2487:be1dbb1dcdd6 2488:345725b9350c
225 } 225 }
226 } 226 }
227 227
228 228
229 229
230 template <typename PixelType> 230 template <typename PixelType,
231 bool UseRound>
231 void MultiplyConstantInternal(ImageAccessor& image, 232 void MultiplyConstantInternal(ImageAccessor& image,
232 float factor) 233 float factor)
233 { 234 {
234 if (std::abs(factor - 1.0f) <= std::numeric_limits<float>::epsilon()) 235 if (std::abs(factor - 1.0f) <= std::numeric_limits<float>::epsilon())
235 { 236 {
244 { 245 {
245 PixelType* p = reinterpret_cast<PixelType*>(image.GetRow(y)); 246 PixelType* p = reinterpret_cast<PixelType*>(image.GetRow(y));
246 247
247 for (unsigned int x = 0; x < width; x++, p++) 248 for (unsigned int x = 0; x < width; x++, p++)
248 { 249 {
249 // The "round" operation is extremely costly. We use 250 int64_t v;
250 // truncation instead since Orthanc 1.3.2. 251 if (UseRound)
251 252 {
252 //int64_t v = boost::math::llround(static_cast<float>(*p) * factor); 253 // The "round" operation is very costly
253 int64_t v = static_cast<int64_t>(static_cast<float>(*p) * factor); 254 v = boost::math::llround(static_cast<float>(*p) * factor);
255 }
256 else
257 {
258 v = static_cast<int64_t>(static_cast<float>(*p) * factor);
259 }
254 260
255 if (v > maxValue) 261 if (v > maxValue)
256 { 262 {
257 *p = std::numeric_limits<PixelType>::max(); 263 *p = std::numeric_limits<PixelType>::max();
258 } 264 }
267 } 273 }
268 } 274 }
269 } 275 }
270 276
271 277
272 template <typename PixelType> 278 template <typename PixelType,
279 bool UseRound>
273 void ShiftScaleInternal(ImageAccessor& image, 280 void ShiftScaleInternal(ImageAccessor& image,
274 float offset, 281 float offset,
275 float scaling) 282 float scaling)
276 { 283 {
277 const float minFloatValue = static_cast<float>(std::numeric_limits<PixelType>::min()); 284 const float minFloatValue = static_cast<float>(std::numeric_limits<PixelType>::min());
296 } 303 }
297 else if (v < minFloatValue) 304 else if (v < minFloatValue)
298 { 305 {
299 *p = minPixelValue; 306 *p = minPixelValue;
300 } 307 }
301 else 308 else if (UseRound)
302 { 309 {
303 // The "round" operation is extremely costly. We use 310 // The "round" operation is very costly
304 // truncation instead since Orthanc 1.3.2. 311 *p = static_cast<PixelType>(boost::math::iround(v));
305 312 }
306 //*p = static_cast<PixelType>(boost::math::iround(v)); 313 else
314 {
307 *p = static_cast<PixelType>(v); 315 *p = static_cast<PixelType>(v);
308 } 316 }
309 } 317 }
310 } 318 }
311 } 319 }
804 } 812 }
805 } 813 }
806 814
807 815
808 void ImageProcessing::MultiplyConstant(ImageAccessor& image, 816 void ImageProcessing::MultiplyConstant(ImageAccessor& image,
809 float factor) 817 float factor,
818 bool useRound)
810 { 819 {
811 switch (image.GetFormat()) 820 switch (image.GetFormat())
812 { 821 {
813 case PixelFormat_Grayscale8: 822 case PixelFormat_Grayscale8:
814 MultiplyConstantInternal<uint8_t>(image, factor); 823 if (useRound)
824 {
825 MultiplyConstantInternal<uint8_t, true>(image, factor);
826 }
827 else
828 {
829 MultiplyConstantInternal<uint8_t, false>(image, factor);
830 }
815 return; 831 return;
816 832
817 case PixelFormat_Grayscale16: 833 case PixelFormat_Grayscale16:
818 MultiplyConstantInternal<uint16_t>(image, factor); 834 if (useRound)
835 {
836 MultiplyConstantInternal<uint16_t, true>(image, factor);
837 }
838 else
839 {
840 MultiplyConstantInternal<uint16_t, false>(image, factor);
841 }
819 return; 842 return;
820 843
821 case PixelFormat_SignedGrayscale16: 844 case PixelFormat_SignedGrayscale16:
822 MultiplyConstantInternal<int16_t>(image, factor); 845 if (useRound)
846 {
847 MultiplyConstantInternal<int16_t, true>(image, factor);
848 }
849 else
850 {
851 MultiplyConstantInternal<int16_t, false>(image, factor);
852 }
823 return; 853 return;
824 854
825 default: 855 default:
826 throw OrthancException(ErrorCode_NotImplemented); 856 throw OrthancException(ErrorCode_NotImplemented);
827 } 857 }
828 } 858 }
829 859
830 860
831 void ImageProcessing::ShiftScale(ImageAccessor& image, 861 void ImageProcessing::ShiftScale(ImageAccessor& image,
832 float offset, 862 float offset,
833 float scaling) 863 float scaling,
864 bool useRound)
834 { 865 {
835 switch (image.GetFormat()) 866 switch (image.GetFormat())
836 { 867 {
837 case PixelFormat_Grayscale8: 868 case PixelFormat_Grayscale8:
838 ShiftScaleInternal<uint8_t>(image, offset, scaling); 869 if (useRound)
870 {
871 ShiftScaleInternal<uint8_t, true>(image, offset, scaling);
872 }
873 else
874 {
875 ShiftScaleInternal<uint8_t, false>(image, offset, scaling);
876 }
839 return; 877 return;
840 878
841 case PixelFormat_Grayscale16: 879 case PixelFormat_Grayscale16:
842 ShiftScaleInternal<uint16_t>(image, offset, scaling); 880 if (useRound)
881 {
882 ShiftScaleInternal<uint16_t, true>(image, offset, scaling);
883 }
884 else
885 {
886 ShiftScaleInternal<uint16_t, false>(image, offset, scaling);
887 }
843 return; 888 return;
844 889
845 case PixelFormat_SignedGrayscale16: 890 case PixelFormat_SignedGrayscale16:
846 ShiftScaleInternal<int16_t>(image, offset, scaling); 891 if (useRound)
892 {
893 ShiftScaleInternal<int16_t, true>(image, offset, scaling);
894 }
895 else
896 {
897 ShiftScaleInternal<int16_t, false>(image, offset, scaling);
898 }
847 return; 899 return;
848 900
849 default: 901 default:
850 throw OrthancException(ErrorCode_NotImplemented); 902 throw OrthancException(ErrorCode_NotImplemented);
851 } 903 }