ColorType.h

Go to the documentation of this file.
00001 /*
00002  * The information in this file is
00003  * Copyright(c) 2007 Ball Aerospace & Technologies Corporation
00004  * and is subject to the terms and conditions of the
00005  * GNU Lesser General Public License Version 2.1
00006  * The license text is available from   
00007  * http://www.gnu.org/licenses/lgpl.html
00008  */
00009 
00010 #ifndef COLOR_TYPE_H
00011 #define COLOR_TYPE_H
00012 
00013 #include <algorithm>
00014 #include <vector>
00015 
00016 #include "AppConfig.h"
00017 #include "DataVariantValidator.h"
00018 
00019 /**
00020  *  @relates ColorType
00021  *
00022  *  Converts a ColorType to a QColor.
00023  *
00024  *  @param   colorType
00025  *           The ColorType to convert to a QColor.  If an invalid ColorType is
00026  *           passed in, an invalid QColor will be created.
00027  *
00028  *  @see     ColorType::isValid()
00029  */
00030 #define COLORTYPE_TO_QCOLOR(colorType) \
00031    (colorType.isValid() ? QColor(colorType.mRed, colorType.mGreen, colorType.mBlue, colorType.mAlpha) : QColor())
00032 
00033 /**
00034  *  @relates ColorType
00035  *
00036  *  Converts a QColor to a ColorType.
00037  *
00038  *  @param   qcolor
00039  *           The QColor to convert to a ColorType.  If an invalid QColor is
00040  *           passed in, an invalid ColorType will be created.
00041  *
00042  *  @see     ColorType::isValid()
00043  */
00044 #define QCOLOR_TO_COLORTYPE(qcolor) \
00045    (qcolor.isValid() ? ColorType(qcolor.red(), qcolor.green(), qcolor.blue(), qcolor.alpha()) : ColorType())
00046 
00047 /**
00048  *  An RGB triplet.
00049  */
00050 class ColorType
00051 {
00052 public:
00053    /**
00054     *  Creates a ColorType object with given RGB values.
00055     *
00056     *  Valid RGB values range from 0 to 255.
00057     *
00058     *  @param   r
00059     *           The red value.
00060     *  @param   g
00061     *           The green value.
00062     *  @param   b
00063     *           The blue value.
00064     *  @param   a
00065     *           The alpha (opacity) value.
00066     */
00067    ColorType(unsigned int r,unsigned int g,unsigned int b, unsigned int a = 255){mRed = r;mGreen = g;mBlue = b; mAlpha = a;};
00068 
00069    /**
00070     *  Creates an invalid ColorType object.
00071     */
00072    ColorType() { mRed = -1; mGreen = -1; mBlue = -1; mAlpha = 255;};
00073 
00074    /**
00075     *  Destructor.
00076     */
00077    ~ColorType()
00078    {};
00079 
00080    /**
00081     *  Returns a unique color that is farthest away in color space from given colors.
00082     *
00083     *  @param   excludedColors
00084     *           The colors from which the unique color is calculated.
00085     *
00086     *  @return  A color that is as different as possible from the given exclusion
00087     *           color.
00088     */
00089    static ColorType getUniqueColor(const std::vector<ColorType>& excludedColors)
00090    {
00091       unsigned int i, j, k;
00092       ColorType uniqueColor(0, 0, 0);
00093 
00094       if (excludedColors.size() == 0)
00095       {
00096          return uniqueColor;  // No excluded colors, so any color will do
00097       }
00098 
00099       if (excludedColors.size() == 1)
00100       {
00101          int maxDist = -1;
00102          int red = excludedColors[0].mRed;
00103          int green = excludedColors[0].mGreen;
00104          int blue = excludedColors[0].mBlue;
00105 
00106          for (i = 0; i < 256; i += 255)
00107          {
00108             for (j = 0; j < 256; j += 255)
00109             {
00110                for (k = 0; k < 256; k += 255)
00111                {
00112                   int dist = (i - red) * (i - red) + (j - green) * (j - green) + (k - blue) * (k - blue);
00113                   if (dist > maxDist)
00114                   {
00115                      maxDist = dist;
00116                      uniqueColor.mRed = i;
00117                      uniqueColor.mGreen = j;
00118                      uniqueColor.mBlue = k;
00119                   }
00120                }
00121             }
00122          }
00123 
00124          return uniqueColor;
00125       }
00126 
00127       std::vector<unsigned int> badColors;
00128       badColors.reserve(excludedColors.size());
00129 
00130       std::vector<ColorType>::const_iterator iter;
00131       for (iter = excludedColors.begin(); iter !=  excludedColors.end(); iter++)
00132       {
00133          badColors.push_back((iter->mBlue << 16) + (iter->mGreen << 8) + iter->mRed);
00134       }
00135 
00136       std::sort(badColors.begin(), badColors.end());
00137 
00138       unsigned int duplicates = 0;
00139       unsigned int next;
00140       for (i = 0, next = 1; i < badColors.size() - duplicates; i++)
00141       {
00142          for (j = next; j < badColors.size(); j++)
00143          {
00144             if (badColors[i] != badColors[j])
00145             {
00146                badColors[i + 1] = badColors[j];
00147                next = j + 1;
00148                break;
00149             }
00150             else
00151             {
00152                duplicates++;
00153             }
00154          }
00155       }
00156 
00157       badColors.erase(badColors.begin() + (badColors.size() - duplicates), badColors.end());
00158 
00159       std::vector<unsigned int>::iterator ulit = badColors.begin();
00160       unsigned int testColor;
00161       for (testColor = 0; testColor < 0xffffff; testColor++)
00162       {
00163          if (testColor == *ulit)
00164          {
00165             ulit++;
00166          }
00167          else
00168          {
00169             break;
00170          }
00171       }
00172 
00173       if (testColor == 0x01000000)  // Searched all 16.7 million colors and didn't find a unique one
00174       {
00175          uniqueColor = ColorType();
00176       }
00177       else
00178       {
00179          uniqueColor.mBlue = (testColor&0xff0000)>>16;
00180          uniqueColor.mGreen = (testColor&0xff00)>>8;
00181          uniqueColor.mRed = testColor&0xff;
00182       }
00183 
00184       return uniqueColor;
00185    }
00186 
00187    /**
00188    *  Generates one or more colors that are unique to each other.
00189    *
00190    *  @param   count
00191    *           The requested number of colors to generate.
00192    *  @param   colors
00193    *           A vector that is populated with the generated colors.
00194    *  @param   excludeColors
00195    *           Colors that should not be included in the generated colors.
00196    *
00197    *  @return  The number of unique colors that were generated.
00198    */
00199    static unsigned int getUniqueColors(unsigned int count, std::vector<ColorType>& colors,
00200       const std::vector<ColorType>& excludeColors)
00201    {
00202       unsigned int i, j, k, l;
00203       unsigned int numUnique = 0;
00204       double slValues[] = {0.0, 1.0, 0.5, 0.8, 0.3, 0.6, 0.9, 0.2, 0.7, 0.4, 0.1};
00205       ColorType baseColors[] =
00206       {
00207          ColorType(0,0,255),
00208          ColorType(0,255,0),
00209          ColorType(255,0,0),
00210          ColorType(0,255,255),
00211          ColorType(255,255,0),
00212          ColorType(255,0,255),
00213          ColorType(255,255,255)
00214       };
00215 
00216       for (i = 0; i < sizeof(slValues) / sizeof(slValues[0]); i++)
00217       {
00218          for (j = 0; j < sizeof(slValues) / sizeof(slValues[0]); j++)
00219          {
00220             for (k = 0; k < sizeof(baseColors) / sizeof(baseColors[0]); k++)
00221             {
00222                int newColor[3];
00223                int maxValue;
00224 
00225                newColor[0] = (int) (baseColors[k].mRed * slValues[j] + 0.5);
00226                newColor[1] = (int) (baseColors[k].mGreen * slValues[j] + 0.5);
00227                newColor[2] = (int) (baseColors[k].mBlue * slValues[j] + 0.5);
00228 
00229                maxValue = 0;
00230                for (l = 0; l < 3; l++)
00231                {
00232                   if (newColor[l] > maxValue)
00233                   {
00234                      maxValue = newColor[l];
00235                   }
00236                }
00237 
00238                maxValue = (int) (maxValue * slValues[i] + 0.5);
00239                for (l = 0; l < 3; l++)
00240                {
00241                   if (newColor[l] < maxValue)
00242                   {
00243                      newColor[l] = maxValue;
00244                   }
00245                }
00246 
00247                ColorType colorToInsert;
00248                colorToInsert.mRed = newColor[0];
00249                colorToInsert.mGreen = newColor[1];
00250                colorToInsert.mBlue = newColor[2];
00251 
00252                for (l=0; l<excludeColors.size(); l++)
00253                {
00254                   if (excludeColors[l].mRed == colorToInsert.mRed &&
00255                      excludeColors[l].mGreen == colorToInsert.mGreen &&
00256                      excludeColors[l].mBlue == colorToInsert.mBlue)
00257                   {
00258                      break;
00259                   }
00260                }
00261                if (l == excludeColors.size())
00262                {
00263                   for (l = 0; l < colors.size(); l++)
00264                   {
00265                      if (colors[l].mRed == colorToInsert.mRed &&
00266                         colors[l].mGreen == colorToInsert.mGreen &&
00267                         colors[l].mBlue == colorToInsert.mBlue)
00268                      {
00269                         break;
00270                      }
00271                   }
00272                   if (l == colors.size())
00273                   {
00274                      colors.push_back (colorToInsert);
00275                      ++numUnique;
00276                      if (colors.size() == count)
00277                      {
00278                         return numUnique;
00279                      }
00280                   }
00281                }
00282             }
00283          }
00284       }
00285       return numUnique;
00286    }
00287 
00288    BROKEN_INLINE_HINT ColorType& operator=(const ColorType& color)
00289    {
00290       if (this != &color)
00291       {
00292          mRed = color.mRed;
00293          mGreen = color.mGreen;
00294          mBlue = color.mBlue;
00295          mAlpha = color.mAlpha;
00296       }
00297 
00298       return *this;
00299    }
00300 
00301    bool operator!=(const ColorType& color) const
00302    {
00303       if ((mRed != color.mRed) || (mGreen != color.mGreen) || (mBlue != color.mBlue) || (mAlpha != color.mAlpha))
00304       {
00305          return true;
00306       }
00307 
00308       return false;
00309    }
00310 
00311    bool operator==(const ColorType& color) const
00312    {
00313       if ((mRed == color.mRed) && (mGreen == color.mGreen) && (mBlue == color.mBlue) && (mAlpha == color.mAlpha))
00314       {
00315          return true;
00316       }
00317 
00318       return false;
00319    }
00320 
00321    /**
00322     *  Queries the color for its validity.
00323     *
00324     *  A valid color has RGB values ranging from 0 to 255.
00325     *
00326     *  @return  TRUE if the color is valid, otherwise FALSE.
00327     */
00328    bool isValid() const
00329    {
00330       if ((mRed > -1) && (mRed < 256) &&
00331          (mGreen > -1) && (mGreen < 256) &&
00332          (mBlue > -1) && (mBlue < 256) &&
00333          (mAlpha > -1) && (mAlpha < 256))
00334       {
00335          return true;
00336       }
00337 
00338       return false;
00339    }
00340 
00341    int mRed;
00342    int mGreen;
00343    int mBlue;
00344    int mAlpha;
00345 };
00346 
00347 /**
00348  * \cond INTERNAL
00349  * These template specializations are required to allow these types to be put into a DataVariant.
00350  */
00351 template <> class VariantTypeValidator<ColorType> {};
00352 /// \endcond
00353 
00354 #endif

Software Development Kit - Opticks 4.9.0 Build 16218