/*========================================================================= * * 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 * * http://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 itkConvertPixelBuffer_hxx #define itkConvertPixelBuffer_hxx #include "itkConvertPixelBuffer.h" #include "itkRGBPixel.h" #include "itkDefaultConvertPixelTraits.h" #include namespace itk { template template typename DisableIfC::IsInteger, UComponentType>::Type ConvertPixelBuffer::DefaultAlphaValue() { return NumericTraits::One; } template template typename EnableIfC::IsInteger, UComponentType>::Type ConvertPixelBuffer::DefaultAlphaValue() { return NumericTraits::max(); } template void ConvertPixelBuffer::Convert(InputPixelType * inputData, int inputNumberOfComponents, OutputPixelType * outputData, size_t size) { switch (OutputConvertTraits::GetNumberOfComponents()) { // output number of components is 1 case 1: { switch (inputNumberOfComponents) { case 1: ConvertGrayToGray(inputData, outputData, size); break; case 3: ConvertRGBToGray(inputData, outputData, size); break; case 4: ConvertRGBAToGray(inputData, outputData, size); break; default: ConvertMultiComponentToGray(inputData, inputNumberOfComponents, outputData, size); break; } break; } // handle the complex case case 2: { switch (inputNumberOfComponents) { case 1: ConvertGrayToComplex(inputData, outputData, size); break; case 2: ConvertComplexToComplex(inputData, outputData, size); break; default: ConvertMultiComponentToComplex(inputData, inputNumberOfComponents, outputData, size); break; } break; } // output number of components is 3 RGB case 3: { switch (inputNumberOfComponents) { case 1: ConvertGrayToRGB(inputData, outputData, size); break; case 3: ConvertRGBToRGB(inputData, outputData, size); break; case 4: ConvertRGBAToRGB(inputData, outputData, size); break; default: ConvertMultiComponentToRGB(inputData, inputNumberOfComponents, outputData, size); } break; } // output number of components is 4 RGBA case 4: { switch (inputNumberOfComponents) { case 1: ConvertGrayToRGBA(inputData, outputData, size); break; case 3: ConvertRGBToRGBA(inputData, outputData, size); break; case 4: ConvertRGBAToRGBA(inputData, outputData, size); break; default: ConvertMultiComponentToRGBA(inputData, inputNumberOfComponents, outputData, size); } break; } // output number of components is 6 (SymmetricSecondRankTensor) case 6: { switch (inputNumberOfComponents) { case 6: ConvertTensor6ToTensor6(inputData, outputData, size); break; case 9: ConvertTensor9ToTensor6(inputData, outputData, size); break; default: itkGenericExceptionMacro("No conversion available from " << inputNumberOfComponents << " components to: 6 components"); break; } break; } default: itkGenericExceptionMacro("No conversion available from " << inputNumberOfComponents << " components to: " << OutputConvertTraits::GetNumberOfComponents() << " components"); break; } } template void ConvertPixelBuffer::ConvertGrayToGray( InputPixelType * inputData, OutputPixelType * outputData, size_t size) { InputPixelType * endInput = inputData + size; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData++, static_cast(*inputData)); inputData++; } } template void ConvertPixelBuffer::ConvertRGBToGray(InputPixelType * inputData, OutputPixelType * outputData, size_t size) { // Weights convert from linear RGB to CIE luminance assuming a // modern monitor. See Charles Pontyon's Colour FAQ // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html // NOTE: The scale factors are converted to whole numbers for precision InputPixelType * endInput = inputData + size * 3; while (inputData != endInput) { auto val = static_cast((2125.0 * static_cast(*inputData) + 7154.0 * static_cast(*(inputData + 1)) + 0721.0 * static_cast(*(inputData + 2))) / 10000.0); inputData += 3; OutputConvertTraits::SetNthComponent(0, *outputData++, val); } } template void ConvertPixelBuffer::ConvertRGBAToGray( InputPixelType * inputData, OutputPixelType * outputData, size_t size) { // Weights convert from linear RGB to CIE luminance assuming a // modern monitor. See Charles Pontyon's Colour FAQ // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html // NOTE: The scale factors are converted to whole numbers for // precision InputPixelType * endInput = inputData + size * 4; double maxAlpha(DefaultAlphaValue()); // // To be backwards campatible, if the output pixel type // isn't a short or char type, don't fix the problem. if (sizeof(*outputData) > 2) { maxAlpha = 1.0; } while (inputData != endInput) { // this is an ugly implementation of the simple equation // greval = (.2125 * red + .7154 * green + .0721 * blue) / alpha // double tempval = ((2125.0 * static_cast(*inputData) + 7154.0 * static_cast(*(inputData + 1)) + 0721.0 * static_cast(*(inputData + 2))) / 10000.0) * static_cast(*(inputData + 3)) / maxAlpha; inputData += 4; auto val = static_cast(tempval); OutputConvertTraits::SetNthComponent(0, *outputData++, val); } } template void ConvertPixelBuffer::ConvertMultiComponentToGray( InputPixelType * inputData, int inputNumberOfComponents, OutputPixelType * outputData, size_t size) { // // To be backwards campatible, if the output pixel type // isn't a short or char type, don't fix the problem. double maxAlpha(DefaultAlphaValue()); if (sizeof(*outputData) > 2) { maxAlpha = 1.0; } // 2 components assumed intensity and alpha if (inputNumberOfComponents == 2) { InputPixelType * endInput = inputData + size * 2; while (inputData != endInput) { OutputComponentType val = static_cast(*inputData) * static_cast(*(inputData + 1) / maxAlpha); inputData += 2; OutputConvertTraits::SetNthComponent(0, *outputData++, val); } } // just skip the rest of the data else { // Weights convert from linear RGB to CIE luminance assuming a // modern monitor. See Charles Pontyon's Colour FAQ // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html // NOTE: The scale factors are converted to whole numbers for // precision ptrdiff_t diff = inputNumberOfComponents - 4; InputPixelType * endInput = inputData + size * (size_t)inputNumberOfComponents; while (inputData != endInput) { double tempval = ((2125.0 * static_cast(*inputData) + 7154.0 * static_cast(*(inputData + 1)) + 0721.0 * static_cast(*(inputData + 2))) / 10000.0) * static_cast(*(inputData + 3)) / maxAlpha; inputData += 4; auto val = static_cast(tempval); OutputConvertTraits::SetNthComponent(0, *outputData++, val); inputData += diff; } } } template void ConvertPixelBuffer::ConvertGrayToRGB(InputPixelType * inputData, OutputPixelType * outputData, size_t size) { InputPixelType * endInput = inputData + size; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*inputData)); inputData++; outputData++; } } template void ConvertPixelBuffer::ConvertRGBToRGB(InputPixelType * inputData, OutputPixelType * outputData, size_t size) { InputPixelType * endInput = inputData + size * 3; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*(inputData + 2))); inputData += 3; outputData++; } } template void ConvertPixelBuffer::ConvertRGBAToRGB(InputPixelType * inputData, OutputPixelType * outputData, size_t size) { InputPixelType * endInput = inputData + size * 4; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*(inputData + 2))); inputData += 3; inputData++; // skip alpha outputData++; } } template void ConvertPixelBuffer::ConvertMultiComponentToRGB( InputPixelType * inputData, int inputNumberOfComponents, OutputPixelType * outputData, size_t size) { // assume intensity alpha if (inputNumberOfComponents == 2) { InputPixelType * endInput = inputData + size * 2; while (inputData != endInput) { OutputComponentType val = static_cast(*inputData) * static_cast(*(inputData + 1)); inputData += 2; OutputConvertTraits::SetNthComponent(0, *outputData, val); OutputConvertTraits::SetNthComponent(1, *outputData, val); OutputConvertTraits::SetNthComponent(2, *outputData, val); outputData++; } } // just skip the rest of the data else { ptrdiff_t diff = inputNumberOfComponents - 3; InputPixelType * endInput = inputData + size * (size_t)inputNumberOfComponents; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*(inputData + 2))); inputData += 3; inputData += diff; outputData++; } } } template void ConvertPixelBuffer::ConvertGrayToRGBA( InputPixelType * inputData, OutputPixelType * outputData, size_t size) { InputPixelType * endInput = inputData + size; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent( 3, *outputData, static_cast(DefaultAlphaValue())); inputData++; outputData++; } } template void ConvertPixelBuffer::ConvertRGBToRGBA(InputPixelType * inputData, OutputPixelType * outputData, size_t size) { using InputConvertTraits = itk::DefaultConvertPixelTraits; using InputComponentType = typename InputConvertTraits::ComponentType; InputPixelType * endInput = inputData + size * 3; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*(inputData + 2))); OutputConvertTraits::SetNthComponent( 3, *outputData, static_cast(DefaultAlphaValue())); inputData += 3; outputData++; } } template void ConvertPixelBuffer::ConvertRGBAToRGBA( InputPixelType * inputData, OutputPixelType * outputData, size_t size) { InputPixelType * endInput = inputData + size * 4; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*(inputData + 2))); OutputConvertTraits::SetNthComponent(3, *outputData, static_cast(*(inputData + 3))); inputData += 4; outputData++; } } template void ConvertPixelBuffer::ConvertMultiComponentToRGBA( InputPixelType * inputData, int inputNumberOfComponents, OutputPixelType * outputData, size_t size) { // equal weights for 2 components?? if (inputNumberOfComponents == 2) { InputPixelType * endInput = inputData + size * 2; while (inputData != endInput) { auto val = static_cast(*inputData); auto alpha = static_cast(*(inputData + 1)); inputData += 2; OutputConvertTraits::SetNthComponent(0, *outputData, val); OutputConvertTraits::SetNthComponent(1, *outputData, val); OutputConvertTraits::SetNthComponent(2, *outputData, val); OutputConvertTraits::SetNthComponent(3, *outputData, alpha); } } else { ptrdiff_t diff = inputNumberOfComponents - 4; InputPixelType * endInput = inputData + size * (size_t)inputNumberOfComponents; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*(inputData + 2))); OutputConvertTraits::SetNthComponent(3, *outputData, static_cast(*(inputData + 3))); inputData += 4; inputData += diff; outputData++; } } } template void ConvertPixelBuffer::ConvertTensor6ToTensor6( InputPixelType * inputData, OutputPixelType * outputData, size_t size) { for (size_t i = 0; i < size; i++) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*(inputData + 2))); OutputConvertTraits::SetNthComponent(3, *outputData, static_cast(*(inputData + 3))); OutputConvertTraits::SetNthComponent(4, *outputData, static_cast(*(inputData + 4))); OutputConvertTraits::SetNthComponent(5, *outputData, static_cast(*(inputData + 5))); ++outputData; inputData += 6; } } // Convert Grayscale to Complex template void ConvertPixelBuffer::ConvertGrayToComplex( InputPixelType * inputData, OutputPixelType * outputData, size_t size) { InputPixelType * endInput = inputData + size; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*inputData)); inputData++; outputData++; } } template void ConvertPixelBuffer::ConvertComplexToComplex( InputPixelType * inputData, OutputPixelType * outputData, size_t size) { InputPixelType * endInput = inputData + size * 2; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); inputData += 2; outputData++; } } template void ConvertPixelBuffer::ConvertTensor9ToTensor6( InputPixelType * inputData, OutputPixelType * outputData, size_t size) { for (size_t i = 0; i < size; i++) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); OutputConvertTraits::SetNthComponent(2, *outputData, static_cast(*(inputData + 2))); OutputConvertTraits::SetNthComponent(3, *outputData, static_cast(*(inputData + 4))); OutputConvertTraits::SetNthComponent(4, *outputData, static_cast(*(inputData + 5))); OutputConvertTraits::SetNthComponent(5, *outputData, static_cast(*(inputData + 8))); ++outputData; inputData += 9; } } template void ConvertPixelBuffer::ConvertMultiComponentToComplex( InputPixelType * inputData, int inputNumberOfComponents, OutputPixelType * outputData, size_t size) { ptrdiff_t diff = inputNumberOfComponents - 2; InputPixelType * endInput = inputData + size * (size_t)inputNumberOfComponents; while (inputData != endInput) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); OutputConvertTraits::SetNthComponent(1, *outputData, static_cast(*(inputData + 1))); inputData += 2; inputData += diff; outputData++; } } template void ConvertPixelBuffer::ConvertVectorImage( InputPixelType * inputData, int inputNumberOfComponents, OutputPixelType * outputData, size_t size) { size_t length = size * (size_t)inputNumberOfComponents; for (size_t i = 0; i < length; i++) { OutputConvertTraits::SetNthComponent(0, *outputData, static_cast(*inputData)); ++outputData; ++inputData; } } } // end namespace itk #endif