# HG changeset patch # User Sebastien Jodogne # Date 1572019782 -7200 # Node ID 0f5f9a5eed25ed45626cc70a01bb192eb85e866d # Parent fab5777f4dd46c6741da1eb3e891fd261fdab6c8# Parent e1ce686920690335858369a12f327265635f836a merge diff -r fab5777f4dd4 -r 0f5f9a5eed25 Core/Images/ImageProcessing.cpp --- a/Core/Images/ImageProcessing.cpp Fri Oct 25 18:09:27 2019 +0200 +++ b/Core/Images/ImageProcessing.cpp Fri Oct 25 18:09:42 2019 +0200 @@ -474,6 +474,91 @@ } + void ImageProcessing::ApplyWindowing(ImageAccessor& target, + const ImageAccessor& source, + float windowCenter, + float windowWidth, + Orthanc::PhotometricInterpretation sourcePhotometricInterpretation) + { + if (source.GetFormat() != Orthanc::PixelFormat_Float32) + { + throw OrthancException(ErrorCode_NotImplemented); + } + + if (sourcePhotometricInterpretation != Orthanc::PhotometricInterpretation_Monochrome1 + && sourcePhotometricInterpretation != Orthanc::PhotometricInterpretation_Monochrome2) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + if (target.GetWidth() != source.GetWidth() || + target.GetHeight() != source.GetHeight()) + { + throw OrthancException(ErrorCode_IncompatibleImageSize); + } + + unsigned int targetBytesPerPixels = target.GetBytesPerPixel(); + unsigned int targetChannelsPerPixels = 0; + switch (target.GetFormat()) + { + case Orthanc::PixelFormat_Grayscale8: + targetChannelsPerPixels = 1; + break; + case Orthanc::PixelFormat_RGBA32: + case Orthanc::PixelFormat_BGRA32: + case Orthanc::PixelFormat_RGB24: + targetChannelsPerPixels = 3; + break; + default: + throw OrthancException(ErrorCode_NotImplemented); + } + + const float a = windowCenter - windowWidth / 2.0f; + const float slope = 256.0f / windowWidth; + bool isInverted = sourcePhotometricInterpretation == Orthanc::PhotometricInterpretation_Monochrome1; + + const unsigned int width = source.GetWidth(); + const unsigned int height = source.GetHeight(); + + assert(sizeof(float) == 4); + + for (unsigned int y = 0; y < height; y++) + { + const float* p = reinterpret_cast(source.GetConstRow(y)); + uint8_t* q = reinterpret_cast(target.GetRow(y)); + + for (unsigned int x = 0; x < width; x++) + { + float v = (*p - a) * slope; + if (v <= 0) + { + v = 0; + } + else if (v >= 255) + { + v = 255; + } + + uint8_t vv = static_cast(v); + + if (isInverted) + { + vv = 255 - vv; + } + + for (unsigned int c = 0; c < targetChannelsPerPixels; c++) + { + q[c] = vv; + } + + p++; + q += targetBytesPerPixels; + } + } + + } + + void ImageProcessing::Convert(ImageAccessor& target, const ImageAccessor& source) { @@ -968,10 +1053,10 @@ } void ImageProcessing::Set(ImageAccessor& image, - uint8_t red, - uint8_t green, - uint8_t blue, - ImageAccessor& alpha) + uint8_t red, + uint8_t green, + uint8_t blue, + ImageAccessor& alpha) { uint8_t p[4]; @@ -1850,13 +1935,17 @@ Copy(target, source); return; } - + switch (source.GetFormat()) { case PixelFormat_Grayscale8: ResizeInternal(target, source); break; + case PixelFormat_Float32: + ResizeInternal(target, source); + break; + case PixelFormat_RGB24: ResizeInternal(target, source); break; diff -r fab5777f4dd4 -r 0f5f9a5eed25 Core/Images/ImageProcessing.h --- a/Core/Images/ImageProcessing.h Fri Oct 25 18:09:27 2019 +0200 +++ b/Core/Images/ImageProcessing.h Fri Oct 25 18:09:42 2019 +0200 @@ -80,6 +80,12 @@ void Convert(ImageAccessor& target, const ImageAccessor& source); + void ApplyWindowing(ImageAccessor& target, + const ImageAccessor& source, + float windowCenter, + float windowWidth, + Orthanc::PhotometricInterpretation sourcePhotometricInterpretation); + void Set(ImageAccessor& image, int64_t value);