/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkPixelTraits.h,v $
  Language:  C++
  Date:      $Date: 2004/11/12 21:14:30 $
  Version:   $Revision: 1.27 $

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef __itkPixelTraits_h
#define __itkPixelTraits_h

namespace itk
{

/** \class PixelTraits
 * \brief Traits for a pixel that define the dimension and component type.
 *
 * PixelTraits determines the dimension and the component type
 * of a pixel.  The default implementation is suitable for all subclasses
 * of itk::Array. This (will) include RGBPixel and RGBAPixel. Specialized
 * versions of PixelTraits are defined for the standard scalar types.
 */
template<class TPixelType>
class PixelTraits
{
public:
  /** Dimension of the pixel (range). */
  itkStaticConstMacro(Dimension, unsigned int, TPixelType::Length);
  
  /** Type of a single component of a pixel. */
  typedef typename TPixelType::ValueType ValueType;
};

/** Specialization of PixelTraitss for scalar images. */
template <>
class PixelTraits<bool>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef bool ValueType;
};

template <>
class PixelTraits<char>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef char ValueType;
};

template <>
class PixelTraits<signed char>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef char ValueType;
};

template <>
class PixelTraits<unsigned char>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef unsigned char ValueType;
};

template <>
class PixelTraits<short>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef short ValueType;
};

template <>
class PixelTraits<unsigned short>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef unsigned short ValueType;
};

template <>
class PixelTraits<int>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef int ValueType;
};

template <>
class PixelTraits<unsigned int>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef unsigned int ValueType;
};

template <>
class PixelTraits<long>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef long ValueType;
};

template <>
class PixelTraits<unsigned long>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef unsigned long ValueType;
};

template <>
class PixelTraits<float>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef float ValueType;
};

template <>
class PixelTraits<double>
{
public:
  itkStaticConstMacro(Dimension, unsigned int, 1);
  typedef double ValueType;
};

/** \class JoinTraits
 * \brief Trait to determine what datatype is needed if the specified 
 * pixel types are "joined" into a single vector.
 *
 * JoinTraits defines the value type needed to combine the specified
 * pixel types into a single vector.  The data type selected is the
 * smallest data type that can represent the dynamic range of both
 * input pixel types.  For example, if a char and unsigned short are
 * "joined", the resulting data type must be a vector of int.  In
 * some cases, like joining a unsigned int and a char, the join
 * value type is promoted all the way to a float.  This provides
 * consistent behavior on both 32 and 64 bit systems (on 64 bit
 * systems, we could have promoted to a long which is distinct from
 * an int but this is not the case for 32 bit systems, so we promote
 * to float). There are several combinations similar to this.  Most
 * of the JoinTraits are specializations of the base template.
 */
template <class TValueType1, class TValueType2>
class JoinTraits
{
public:
  typedef TValueType1 ValueType;
};

/** Specializations for bool. */
template<>
class JoinTraits<bool, bool>
{
public:
  typedef bool ValueType;
};

template<>
class JoinTraits<bool, char>
{
public:
  typedef char ValueType;
};

template<>
class JoinTraits<bool, unsigned char>
{
public:
  typedef unsigned char ValueType;
};

template<>
class JoinTraits<bool, short>
{
public:
  typedef short ValueType;
};

template<>
class JoinTraits<bool, unsigned short>
{
public:
  typedef unsigned short ValueType;
};

template<>
class JoinTraits<bool, int>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<bool, unsigned int>
{
public:
  typedef unsigned int ValueType;
};

template<>
class JoinTraits<bool, long>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<bool, unsigned long>
{
public:
  typedef unsigned long ValueType;
};

template<>
class JoinTraits<bool, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<bool, double>
{
public:
  typedef double ValueType;
};

/** Specializations for char. */
template<>
class JoinTraits<char, bool>
{
public:
  typedef char ValueType;
};

template<>
class JoinTraits<char, char>
{
public:
  typedef char ValueType;
};

template<>
class JoinTraits<char, unsigned char>
{
public:
  typedef short ValueType;
};

template<>
class JoinTraits<char, short>
{
public:
  typedef short ValueType;
};

template<>
class JoinTraits<char, unsigned short>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<char, int>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<char, unsigned int>
{
public:
  // unsigned int & unsigned long may be the same size, so promote to float
  typedef float ValueType;
};

template<>
class JoinTraits<char, long>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<char, unsigned long>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<char, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<char, double>
{
public:
  typedef double ValueType;
};

/** Specializations for unsigned char. */
template<>
class JoinTraits<unsigned char, bool>
{
public:
  typedef unsigned char ValueType;
};

template<>
class JoinTraits<unsigned char, char>
{
public:
  typedef short ValueType;
};

template<>
class JoinTraits<unsigned char, unsigned char>
{
public:
  typedef unsigned char ValueType;
};

template<>
class JoinTraits<unsigned char, short>
{
public:
  typedef short ValueType;
};

template<>
class JoinTraits<unsigned char, unsigned short>
{
public:
  typedef unsigned short ValueType;
};

template<>
class JoinTraits<unsigned char, int>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<unsigned char, unsigned int>
{
public:
  typedef unsigned int ValueType;
};

template<>
class JoinTraits<unsigned char, long>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<unsigned char, unsigned long>
{
public:
  typedef unsigned long ValueType;
};

template<>
class JoinTraits<unsigned char, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned char, double>
{
public:
  typedef double ValueType;
};
  
/** Specializations for short. */
template<>
class JoinTraits<short, bool>
{
public:
  typedef short ValueType;
};

template<>
class JoinTraits<short, char>
{
public:
  typedef short ValueType;
};

template<>
class JoinTraits<short, unsigned char>
{
public:
  typedef short ValueType;
};

template<>
class JoinTraits<short, short>
{
public:
  typedef short ValueType;
};

template<>
class JoinTraits<short, unsigned short>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<short, int>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<short, unsigned int>
{
public:
  // unsigned int & unsigned long may be the same size, so promote to float
  typedef float ValueType;
};

template<>
class JoinTraits<short, long>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<short, unsigned long>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<short, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<short, double>
{
public:
  typedef double ValueType;
};
  
/** Specializations for unsigned short. */
template<>
class JoinTraits<unsigned short, bool>
{
public:
  typedef unsigned short ValueType;
};

template<>
class JoinTraits<unsigned short, char>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<unsigned short, unsigned char>
{
public:
  typedef unsigned short ValueType;
};

template<>
class JoinTraits<unsigned short, short>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<unsigned short, unsigned short>
{
public:
  typedef unsigned short ValueType;
};

template<>
class JoinTraits<unsigned short, int>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<unsigned short, unsigned int>
{
public:
  typedef unsigned int ValueType;
};

template<>
class JoinTraits<unsigned short, long>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<unsigned short, unsigned long>
{
public:
  typedef unsigned long ValueType;
};

template<>
class JoinTraits<unsigned short, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned short, double>
{
public:
  typedef double ValueType;
};
  
/** Specializations for int. */
template<>
class JoinTraits<int, bool>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<int, char>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<int, unsigned char>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<int, short>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<int, unsigned short>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<int, int>
{
public:
  typedef int ValueType;
};

template<>
class JoinTraits<int, unsigned int>
{
public:
  // unsigned int & unsigned long may be the same size, so promote to float
  typedef float ValueType;
};

template<>
class JoinTraits<int, long>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<int, unsigned long>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<int, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<int, double>
{
public:
  typedef double ValueType;
};
  
/** Specializations for unsigned int. */
template<>
class JoinTraits<unsigned int, bool>
{
public:
  typedef unsigned int ValueType;
};

template<>
class JoinTraits<unsigned int, char>
{
public:
  // unsigned int & unsigned long may be the same size, so promote to float
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned int, unsigned char>
{
public:
  typedef unsigned int ValueType;
};

template<>
class JoinTraits<unsigned int, short>
{
public:
  // unsigned int & unsigned long may be the same size, so promote to float
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned int, unsigned short>
{
public:
  typedef unsigned int ValueType;
};

template<>
class JoinTraits<unsigned int, int>
{
public:
  // unsigned int & unsigned long may be the same size, so promote to float
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned int, unsigned int>
{
public:
  typedef unsigned int ValueType;
};

template<>
class JoinTraits<unsigned int, long>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned int, unsigned long>
{
public:
  typedef unsigned long ValueType;
};

template<>
class JoinTraits<unsigned int, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned int, double>
{
public:
  typedef double ValueType;
};
  
/** Specializations for long. */
template<>
class JoinTraits<long, bool>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<long, char>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<long, unsigned char>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<long, short>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<long, unsigned short>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<long, int>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<long, unsigned int>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<long, long>
{
public:
  typedef long ValueType;
};

template<>
class JoinTraits<long, unsigned long>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<long, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<long, double>
{
public:
  typedef double ValueType;
};
  
/** Specializations for unsigned long. */
template<>
class JoinTraits<unsigned long, bool>
{
public:
  typedef unsigned long ValueType;
};

template<>
class JoinTraits<unsigned long, char>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned long, unsigned char>
{
public:
  typedef unsigned long ValueType;
};

template<>
class JoinTraits<unsigned long, short>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned long, unsigned short>
{
public:
  typedef unsigned long ValueType;
};

template<>
class JoinTraits<unsigned long, int>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned long, unsigned int>
{
public:
  typedef unsigned long ValueType;
};

template<>
class JoinTraits<unsigned long, long>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned long, unsigned long>
{
public:
  typedef unsigned long ValueType;
};

template<>
class JoinTraits<unsigned long, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<unsigned long, double>
{
public:
  typedef double ValueType;
};
  
/** Specializations for float. */
template<>
class JoinTraits<float, bool>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, char>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, unsigned char>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, short>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, unsigned short>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, int>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, unsigned int>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, long>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, unsigned long>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, float>
{
public:
  typedef float ValueType;
};

template<>
class JoinTraits<float, double>
{
public:
  typedef double ValueType;
};
  
/** Specializations for double. */
template<>
class JoinTraits<double, bool>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, char>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, unsigned char>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, short>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, unsigned short>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, int>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, unsigned int>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, long>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, unsigned long>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, float>
{
public:
  typedef double ValueType;
};

template<>
class JoinTraits<double, double>
{
public:
  typedef double ValueType;
};
  
} // end namespace itk

#endif // __itkPixelTraits_h
