/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkLabelOverlayFunctor_h #define itkLabelOverlayFunctor_h #include "itkLabelToRGBFunctor.h" #include "itkMath.h" namespace itk { namespace Functor { /** * \class LabelOverlayFunctor * \brief Functor for applying a colormap to a label image and combine it * with a grayscale image * * This functor class used internally by LabelOverlayImageFilter * * This code was contributed in the Insight Journal paper: * "The watershed transform in ITK - discussion and new developments" * by Beare R., Lehmann G. * https://www.insight-journal.org/browse/publication/92 * * \author Gaetan Lehmann. Biologie du Developpement et de la Reproduction, * INRA de Jouy-en-Josas, France. * * \sa LabelOverlayImageFilter LabelToRGBFunctor * * \ingroup ITKImageFusion */ template class LabelOverlayFunctor { public: LabelOverlayFunctor() { // provide some default value for external use (outside // LabelOverlayFunctorImageFilter) Inside LabelOverlayFunctorImageFilter, // the values are always initialized m_Opacity = 1.0; m_BackgroundValue = TLabel{}; } inline TRGBPixel operator()(const TInputPixel & p1, const TLabel & p2) const { TRGBPixel rgbPixel; NumericTraits::SetLength(rgbPixel, 3); if (p2 == m_BackgroundValue) { // value is background // return a gray pixel with the same intensity than the input pixel auto p = static_cast(p1); rgbPixel[0] = p; rgbPixel[1] = p; rgbPixel[2] = p; return rgbPixel; } // taint the input pixel with the colored one returned by // the color functor. TRGBPixel opaque = m_RGBFunctor(p2); // the following has been unrolled due to a bug with apple's // llvm-gcc-4.2 build 5658 const double p1_blend = p1 * (1.0 - m_Opacity); rgbPixel[0] = static_cast(opaque[0] * m_Opacity + p1_blend); rgbPixel[1] = static_cast(opaque[1] * m_Opacity + p1_blend); rgbPixel[2] = static_cast(opaque[2] * m_Opacity + p1_blend); return rgbPixel; } bool operator==(const LabelOverlayFunctor & other) const { return Math::ExactlyEquals(m_Opacity, other.m_Opacity) && m_BackgroundValue == other.m_BackgroundValue && m_RGBFunctor == other.m_RGBFunctor; } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(LabelOverlayFunctor); ~LabelOverlayFunctor() = default; void SetOpacity(double opacity) { m_Opacity = opacity; } void SetBackgroundValue(TLabel v) { m_BackgroundValue = v; m_RGBFunctor.SetBackgroundValue(v); } void ResetColors() { m_RGBFunctor.ResetColors(); } unsigned int GetNumberOfColors() const { return m_RGBFunctor.GetNumberOfColors(); } /** type of the color component */ using ComponentType = typename TRGBPixel::ComponentType; void AddColor(unsigned char r, unsigned char g, unsigned char b) { m_RGBFunctor.AddColor(r, g, b); } protected: private: double m_Opacity; TLabel m_BackgroundValue; typename Functor::LabelToRGBFunctor m_RGBFunctor; }; } // end namespace Functor } // end namespace itk #endif