image.h

Go to the documentation of this file.
00001 //**************************************************************************/
00002 // Copyright (c) 2008 Autodesk, Inc.
00003 // All rights reserved.
00004 //
00005 // Use of this software is subject to the terms of the Autodesk license
00006 // agreement provided at the time of installation or download, or which
00007 // otherwise accompanies this software in either electronic or hard copy form.
00008 //
00009 //**************************************************************************/
00010 // DESCRIPTION:
00011 // CREATED: October 2008
00012 //**************************************************************************/
00013 
00014 #if !defined IMAGE_H_
00015 #define IMAGE_H_
00016 
00017 namespace mudbox {
00018 
00019 
00020 class Image;
00021 class SubdivisionLevel;
00022 class TexturePool;
00023 
00029 class MBDLL_DECL half_ {
00030 
00031 // These member fcns are inlined for a reason; THESE ARE EXTREMELY PERFORMANCE CRITICAL!
00032 // DO NOT change this file or "clean it up" by removing inlines. Unless you really know
00033 // what you are doing, you will make it significantly slower.
00034 //
00035 private:
00036     unsigned short m_bits;
00037     void setBits(unsigned short newbits) { m_bits = newbits; }
00038 
00039 public:
00040     half_ () {};
00041     half_ (float f)
00042     {
00043         unsigned int   x    = *(unsigned int *)&f;
00044         unsigned int   frac = (x >> 13) & 0x03ff;
00045         int            exp  = (int)((x >> 23) & 0xff) - 127;
00046 
00047         m_bits = (x >> 16) & 0x8000;  // extract the sign bit
00048 
00049         if (exp > 16) {      // handle overflows/underflows
00050             exp  = 16;
00051             frac = 0x03ff;
00052         } else if (exp <= -15) {
00053             frac = 0;
00054             exp  = -15;
00055         }
00056 
00057         m_bits |= ((exp + 15) << 10) | frac;
00058     }
00059 
00060 public:
00061     // Conversion to float ~ 15 cycles
00062     #define ExponentBiasDelta (127-15)
00063     operator float () const
00064     {
00065         int           exp  = (m_bits >> 10) & 0x1f;
00066         unsigned int  f    = (m_bits & 0x8000) << 16; // extract the sign bit
00067         unsigned int  frac = (m_bits & 0x03ff) << 13;
00068 
00069         if (exp == 0x1f) {      // convert 16-bit FP inf/NaN to 32-bit inf/NaN value
00070             exp =  0xff - ExponentBiasDelta;
00071         } else if (exp == 0) {
00072             exp = -ExponentBiasDelta;  // convert 16-bit FP zero/denorm to 32-bit zero/denorm value
00073         }
00074 
00075         f |= ((exp + ExponentBiasDelta) << 23) | frac;
00076         return *(float *)&f;
00077     }
00078 
00079     half_ &operator = (float f)
00080     {
00081         *this = half_ (f);
00082         return *this;
00083     }
00084 };
00085 
00086 //------------------------------------------------------------------------------
00087 typedef unsigned char  uInt8;
00088 typedef unsigned short uInt16;
00089 
00090 
00091 class uInt8Channel;
00092 class uInt16Channel;
00093 class float16Channel;
00094 class float32Channel;
00095 
00096 //------------------------------------------------------------------------------
00099 class uInt8Channel {
00100 private:
00101     uInt8 m_data;
00102 
00103 public:
00104     inline uInt8Channel(const float32Channel &d);
00105     inline uInt8Channel(const float16Channel &d);
00106     inline uInt8Channel(const uInt16Channel  &d);
00107     uInt8Channel(const uInt8Channel   &d) { m_data = uInt8(d); }
00108 
00109     uInt8Channel(uInt8 d)  { m_data = (d); }
00110     uInt8Channel() {}
00111 
00112     inline uInt8Channel & operator = (const float32Channel &d);
00113     inline uInt8Channel & operator = (const float16Channel &d);
00114     inline uInt8Channel & operator = (const uInt16Channel  &d);
00115     inline uInt8Channel & operator = (const uInt8Channel   &d)
00116     {
00117         m_data = uInt8(d);
00118         return *this;
00119     }
00120 
00121     inline uInt8Channel & operator = (uInt8 d)
00122     {
00123         m_data = uInt8(d);
00124         return *this;
00125     }
00126 
00127     operator float ()  const { return m_data * (1.0f/255.0f); }
00128     operator half_ ()  const { return half_(m_data * (1.0f/255.0f)); }
00129     operator uInt16 () const { return (m_data << 8) + m_data; }
00130     operator uInt8 ()  const { return m_data; }
00131 };
00132 
00133 
00134 //------------------------------------------------------------------------------
00136 class uInt16Channel {
00137 private:
00138     uInt16 m_data;
00139 
00140 public:
00141     inline uInt16Channel(const float32Channel &d);
00142     inline uInt16Channel(const float16Channel &d);
00143     uInt16Channel(const uInt16Channel  &d) { m_data = uInt16(d); }
00144     uInt16Channel(const uInt8Channel   &d) { m_data = uInt16(d); }
00145     uInt16Channel(uInt16 d)                { m_data = (d); }
00146     uInt16Channel() {}
00147 
00148     inline uInt16Channel & operator = (const float32Channel &d);
00149     inline uInt16Channel & operator = (const float16Channel &d);
00150 
00151     inline uInt16Channel & operator = (const uInt16Channel &d)
00152     {
00153         m_data = uInt16(d);
00154         return *this;
00155     }
00156 
00157     inline uInt16Channel & operator = (uInt16 d)
00158     {
00159         m_data = uInt16(d);
00160         return *this;
00161     }
00162 
00163     inline uInt16Channel & operator = (const uInt8Channel &d)
00164     {
00165         m_data = uInt16(d);
00166         return *this;
00167     }
00168 
00169     operator float ()  const { return m_data * (1.0f/65535.0f); }
00170     operator half_ ()  const { return half_(m_data * (1.0f/65535.0f)); }
00171     operator uInt16 () const { return m_data;               }
00172     operator uInt8 ()  const { return uInt8(m_data >> 8);   }
00173 };
00174 
00175 
00176 //------------------------------------------------------------------------------
00177 // The data type for a 32 bit float image channel.
00178 class float32Channel {
00179 private:
00180     float m_data;
00181 
00182 public:
00183     float32Channel(const float32Channel &d) { m_data = float(d); }
00184     inline float32Channel(const float16Channel &d);
00185     float32Channel(const uInt16Channel  &d) { m_data = float(d); }
00186     float32Channel(const uInt8Channel   &d) { m_data = float(d); }
00187     float32Channel(float                d)  { m_data = (d); }
00188     float32Channel() {}
00189 
00190     inline float32Channel & operator = (const float32Channel &d)
00191     {
00192         *(float *)this = *(float *)&d;
00193         return *this;
00194     }
00195 
00196     inline float32Channel & operator = (const float16Channel &d)
00197     {
00198         *this = float32Channel(d);
00199         return *this;
00200     }
00201 
00202     inline float32Channel & operator = (const uInt16Channel &d)
00203     {
00204         *this = float32Channel(d);
00205         return *this;
00206     }
00207 
00208     inline float32Channel & operator = (float d)
00209     {
00210         *this = float32Channel(d);
00211         return *this;
00212     }
00213 
00214     inline float32Channel & operator = (const uInt8Channel &d)
00215     {
00216         *this = float32Channel(d);
00217         return *this;
00218     }
00219 
00220     operator float ()  const { return m_data; }
00221     operator half_ ()  const { return half_(m_data); }
00222     operator uInt16 () const
00223         {
00224             if (m_data < 0.0f) return 0;
00225             if (m_data > 1.0f) return 65535;
00226             return uInt16(m_data * 65535.0f);
00227         }
00228     operator uInt8 ()  const
00229         {
00230             if (m_data < 0.0f) return 0;
00231             if (m_data > 1.0f) return 255;
00232             return uInt8(m_data * 255.0f);
00233         }
00234 };
00235 
00236 
00237 //------------------------------------------------------------------------------
00239 class float16Channel {
00240 private:
00241     half_ m_data;
00242 
00243 public:
00244     float16Channel(const float32Channel &d) { m_data = float(d); }
00245     float16Channel(const float16Channel &d) { m_data = float(d); }
00246     float16Channel(const uInt16Channel  &d) { m_data = float(d); }
00247     float16Channel(const uInt8Channel   &d) { m_data = float(d); }
00248     float16Channel(const half_          &d) { m_data = (d); }
00249     float16Channel() {}
00250 
00251     inline float16Channel & operator = (const float32Channel &d)
00252     {
00253         *this = float16Channel(d);
00254         return *this;
00255     }
00256 
00257     inline float16Channel & operator = (const float16Channel &d)
00258     {
00259         *(uInt16 *)this = *(uInt16 *)&d;
00260         return *this;
00261     }
00262 
00263     inline float16Channel & operator = (const uInt16Channel &d)
00264     {
00265         *this = float16Channel(d);
00266         return *this;
00267     }
00268 
00269     inline float16Channel & operator = (const half_ &d)
00270     {
00271         *this = float16Channel(d);
00272         return *this;
00273     }
00274 
00275     inline float16Channel & operator = (const uInt8Channel &d)
00276     {
00277         *this = float16Channel(d);
00278         return *this;
00279     }
00280 
00281     operator float ()  const { return float(m_data); }
00282     operator half_ ()  const { return m_data; }
00283 
00284     operator uInt16 () const
00285         {   float d = float(m_data);
00286             if (d < 0.0f) return 0;
00287             if (d > 1.0f) return 65535;
00288             return uInt16(d * 65535.0f);
00289         }
00290     operator uInt8 ()  const
00291         {   float d = float(m_data);
00292             if (d < 0.0f) return 0;
00293             if (d > 1.0f) return 255;
00294             return uInt8(d * 255.0f);
00295         }
00296 };
00297 
00298 
00299 //------------------------------------------------------------------------------
00300 inline uInt8Channel::uInt8Channel(const float32Channel &d) { m_data = uInt8(d); }
00301 inline uInt8Channel::uInt8Channel(const float16Channel &d) { m_data = uInt8(d); }
00302 inline uInt8Channel::uInt8Channel(const uInt16Channel  &d) { m_data = uInt8(d); }
00303 
00304 //------------------------------------------------------------------------------
00305 inline uInt8Channel & uInt8Channel::operator = (const float32Channel &d)
00306 {
00307     m_data = uInt8(d);
00308     return *this;
00309 }
00310 
00311 //------------------------------------------------------------------------------
00312 inline uInt8Channel & uInt8Channel::operator = (const float16Channel &d)
00313 {
00314     m_data = uInt8(d);
00315     return *this;
00316 }
00317 
00318 //------------------------------------------------------------------------------
00319 inline uInt8Channel & uInt8Channel::operator = (const uInt16Channel &d)
00320 {
00321     m_data = uInt8(d);
00322     return *this;
00323 }
00324 
00325 
00326 //------------------------------------------------------------------------------
00327 inline uInt16Channel::uInt16Channel(const float32Channel &d) { m_data = uInt16(d); }
00328 inline uInt16Channel::uInt16Channel(const float16Channel &d) { m_data = uInt16(d); }
00329 
00330 //------------------------------------------------------------------------------
00331 inline uInt16Channel & uInt16Channel::operator = (const float32Channel &d)
00332 {
00333     m_data = uInt16(d);
00334     return *this;
00335 }
00336 
00337 //------------------------------------------------------------------------------
00338 inline uInt16Channel & uInt16Channel::operator = (const float16Channel &d)
00339 {
00340     m_data = uInt16(d);
00341     return *this;
00342 }
00343 
00344 
00345 //------------------------------------------------------------------------------
00346 inline float32Channel::float32Channel(const float16Channel &d) { m_data = float(d); }
00347 
00348 //----------------------------------------------------------------------------------
00349 // Now we define the pixel types -- 1, 2, 3, and 4 channels. templated by
00350 // one of the above channel types -- the channel types handle converting between
00351 // each other, and the pixel types handle converting between them.
00352 // 1 -> 3  or 4 channel -- replicates the single channel through the target channels
00353 // 3 -> 4 channel copies the rgb, and sets the a to 1.0. 4 -> 3 channel copies the
00354 // RGB. 4 & 3 -> 1 channel takes the luminance of the rgb channels and stores it
00355 // in the single channel.
00356 //
00357 
00365 template <class ChanType, const unsigned char NumChans>
00366 class MBDLL_TEMPLATE_DECL PixelType {
00367 
00368     // allow the various instantiations of this class to
00369     // access each others private data members... Also has the
00370     // beneficial side effect of causing a compile error if
00371     // someone tries to instantiate one that is not listed here.
00372     friend class PixelType<uInt8Channel,   1>;
00373     friend class PixelType<uInt8Channel,   2>;
00374     friend class PixelType<uInt8Channel,   3>;
00375     friend class PixelType<uInt8Channel,   4>;
00376     friend class PixelType<uInt16Channel,  1>;
00377     friend class PixelType<uInt16Channel,  2>;
00378     friend class PixelType<uInt16Channel,  3>;
00379     friend class PixelType<uInt16Channel,  4>;
00380     friend class PixelType<float16Channel, 1>;
00381     friend class PixelType<float16Channel, 2>;
00382     friend class PixelType<float16Channel, 3>;
00383     friend class PixelType<float16Channel, 4>;
00384     friend class PixelType<float32Channel, 1>;
00385     friend class PixelType<float32Channel, 2>;
00386     friend class PixelType<float32Channel, 3>;
00387     friend class PixelType<float32Channel, 4>;
00388 
00389 private:
00390     ChanType m_pixel[NumChans];
00391 
00392 public:
00393 
00395     PixelType<ChanType, NumChans> &swapRB() {
00396         if (NumChans > 2) { // conditional will be resolved at compile time.
00397             ChanType t = m_pixel[0];
00398             m_pixel[0] = m_pixel[2];
00399             m_pixel[2] = t;
00400         }
00401         return *this;
00402     }
00403 
00405     PixelType<ChanType, NumChans>(const PixelType<uInt8Channel, 4> &p)
00406     {
00407         switch (NumChans) { // this switch gets resolved at compile time
00408         case 2: m_pixel[1] = p.m_pixel[3]; // intentional fall through.
00409         case 1: m_pixel[0] = ChanType(uInt16Channel((uInt8)p.m_pixel[0]*77  +
00410                                                     (uInt8)p.m_pixel[1]*150 +
00411                                                     (uInt8)p.m_pixel[2]*28));
00412         break;
00413         // cppcheck mistakenly warns about array bounds here -- ignore it.
00414         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00415                 m_pixel[2] = p.m_pixel[2];
00416         break;
00417         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00418                 m_pixel[2] = p.m_pixel[2]; m_pixel[3] = p.m_pixel[3];
00419         break;
00420         }
00421     }
00422 
00424     PixelType<ChanType, NumChans>(const PixelType<uInt8Channel, 3> &p)
00425     {
00426         switch (NumChans) { // this switch gets resolved at compile time
00427         case 2: m_pixel[1] = ChanType( float32Channel( 1.0f ) ); // intentional fall through.
00428         case 1: m_pixel[0] = ChanType(uInt16Channel((uInt8)p.m_pixel[0]*77  +
00429                                                     (uInt8)p.m_pixel[1]*150 +
00430                                                     (uInt8)p.m_pixel[2]*28));
00431         break;
00432         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00433                 m_pixel[2] = p.m_pixel[2];
00434         break;
00435         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00436                 m_pixel[2] = p.m_pixel[2];
00437                 m_pixel[3] = ChanType(float32Channel(1.0f));
00438         break;
00439         }
00440     }
00441 
00443     PixelType<ChanType, NumChans>(const PixelType<uInt8Channel, 2> &p)
00444     {
00445         switch (NumChans) { // this switch gets resolved at compile time
00446         case 1: m_pixel[0] = p.m_pixel[0];
00447         break;
00448         case 2: m_pixel[0] = p.m_pixel[0]; 
00449                 m_pixel[1] = p.m_pixel[1]; 
00450         break;
00451         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00452                 m_pixel[2] = p.m_pixel[0];
00453         break;
00454         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00455                 m_pixel[2] = p.m_pixel[0];
00456                 m_pixel[3] = p.m_pixel[1];
00457         break;
00458         }
00459     }
00460 
00462     PixelType<ChanType, NumChans>(const PixelType<uInt8Channel, 1> &p)
00463     {
00464         switch (NumChans) { // this switch gets resolved at compile time
00465         case 2: m_pixel[1] = ChanType( float32Channel( 1.0f ) ); // intentional fall through.
00466         case 1: m_pixel[0] = p.m_pixel[0];
00467         break;
00468         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00469                 m_pixel[2] = p.m_pixel[0];
00470         break;
00471         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00472                 m_pixel[2] = p.m_pixel[0]; m_pixel[3] = ChanType(float32Channel(1.0f)); ;
00473         break;
00474         }
00475     }
00476 
00477 
00479     PixelType<ChanType, NumChans>(const PixelType<uInt16Channel, 4> &p)
00480     {
00481         switch (NumChans) { // this switch gets resolved at compile time
00482 
00483         case 2: m_pixel[1] = p.m_pixel[3]; // intentional fallthrough.
00484         case 1: m_pixel[0] = ChanType(uInt16Channel((((uInt16)p.m_pixel[0]*19660)>>16) +
00485                                                     (((uInt16)p.m_pixel[1]*38666)>>16) +
00486                                                     (((uInt16)p.m_pixel[2]*7209 )>>16)));
00487         break;
00488         
00489         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00490                 m_pixel[2] = p.m_pixel[2];
00491         break;
00492         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00493                 m_pixel[2] = p.m_pixel[2]; m_pixel[3] = p.m_pixel[3];
00494         break;
00495         }
00496     }
00497 
00499     PixelType<ChanType, NumChans>(const PixelType<uInt16Channel, 3> &p)
00500     {
00501         switch (NumChans) { // this switch gets resolved at compile time
00502         case 2: m_pixel[1] = ChanType(float32Channel(1.0f)); // intentional fallthrough
00503         case 1: m_pixel[0] = ChanType(uInt16Channel((((uInt16)p.m_pixel[0]*19660)>>16) +
00504                                                     (((uInt16)p.m_pixel[1]*38666)>>16) +
00505                                                     (((uInt16)p.m_pixel[2]*7209 )>>16)));
00506         break;
00507         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00508                 m_pixel[2] = p.m_pixel[2];
00509         break;
00510         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00511                 m_pixel[2] = p.m_pixel[2];
00512                 m_pixel[3] = ChanType(float32Channel(1.0f));
00513         break;
00514         }
00515     }
00516 
00518     PixelType<ChanType, NumChans>(const PixelType<uInt16Channel, 2> &p)
00519     {
00520         switch (NumChans) { // this switch gets resolved at compile time
00521         case 1: m_pixel[0] = p.m_pixel[0];
00522         break;
00523         case 2: m_pixel[0] = p.m_pixel[0]; 
00524                 m_pixel[1] = p.m_pixel[1]; 
00525         break;
00526         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00527                 m_pixel[2] = p.m_pixel[0];
00528         break;
00529         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00530                 m_pixel[2] = p.m_pixel[0];
00531                 m_pixel[3] = p.m_pixel[1];
00532         break;
00533         }
00534     }
00535 
00537     PixelType<ChanType, NumChans>(const PixelType<uInt16Channel, 1> &p)
00538     {
00539         switch (NumChans) { // this switch gets resolved at compile time
00540         case 2: m_pixel[1] = ChanType(float32Channel(1.0f)); // intentional fallthrough
00541         case 1: m_pixel[0] = p.m_pixel[0];
00542         break;
00543         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00544                 m_pixel[2] = p.m_pixel[0];
00545         break;
00546         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00547                 m_pixel[2] = p.m_pixel[0]; m_pixel[3] = ChanType(float32Channel(1.0f));
00548         break;
00549         }
00550     }
00551 
00552 
00554     PixelType<ChanType, NumChans>(const PixelType<float16Channel, 4> &p)
00555     {
00556         switch (NumChans) { // this switch gets resolved at compile time
00557         case 2: m_pixel[1] = p.m_pixel[1];
00558         case 1: m_pixel[0] = ChanType(float32Channel(((float)p.m_pixel[0]*0.30f) +
00559                                                      ((float)p.m_pixel[1]*0.59f) +
00560                                                      ((float)p.m_pixel[2]*0.11f)));
00561         break;
00562         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00563                 m_pixel[2] = p.m_pixel[2];
00564         break;
00565         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00566                 m_pixel[2] = p.m_pixel[2]; m_pixel[3] = p.m_pixel[3];
00567         break;
00568         }
00569     }
00570 
00572     PixelType<ChanType, NumChans>(const PixelType<float16Channel, 3> &p)
00573     {
00574         switch (NumChans) { // this switch gets resolved at compile time
00575         case 2: m_pixel[1] = ChanType(float32Channel(1.0f));
00576         case 1: m_pixel[0] = ChanType(float32Channel(((float)p.m_pixel[0]*0.30f) +
00577                                                      ((float)p.m_pixel[1]*0.59f) +
00578                                                      ((float)p.m_pixel[2]*0.11f)));
00579         break;
00580         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00581                 m_pixel[2] = p.m_pixel[2];
00582         break;
00583         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00584                 m_pixel[2] = p.m_pixel[2];
00585                 m_pixel[3] = ChanType(float32Channel(1.0f));
00586         break;
00587         }
00588     }
00589 
00591     PixelType<ChanType, NumChans>(const PixelType<float16Channel, 2> &p)
00592     {
00593         switch (NumChans) { // this switch gets resolved at compile time
00594         case 1: m_pixel[0] = p.m_pixel[0];
00595         break;
00596         case 2: m_pixel[0] = p.m_pixel[0]; 
00597                 m_pixel[1] = p.m_pixel[1]; 
00598         break;
00599         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00600                 m_pixel[2] = p.m_pixel[0];
00601         break;
00602         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00603                 m_pixel[2] = p.m_pixel[0];
00604                 m_pixel[3] = p.m_pixel[1];
00605         break;
00606         }
00607     }
00608 
00610     PixelType<ChanType, NumChans>(const PixelType<float16Channel, 1> &p)
00611     {
00612         switch (NumChans) { // this switch gets resolved at compile time
00613         case 2: m_pixel[1] = ChanType(float32Channel(1.0f));
00614         case 1: m_pixel[0] = p.m_pixel[0];
00615         break;
00616         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00617                 m_pixel[2] = p.m_pixel[0];
00618         break;
00619         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00620                 m_pixel[2] = p.m_pixel[0]; m_pixel[3] = ChanType(float32Channel(1.0f));
00621         break;
00622         }
00623     }
00624 
00625 
00627     PixelType<ChanType, NumChans>(const PixelType<float32Channel, 4> &p)
00628     {
00629         switch (NumChans) { // this switch gets resolved at compile time
00630         case 2: m_pixel[1] = p.m_pixel[3];
00631         case 1: m_pixel[0] = ChanType(float32Channel(((float)p.m_pixel[0]*0.30f) +
00632                                                      ((float)p.m_pixel[1]*0.59f) +
00633                                                      ((float)p.m_pixel[2]*0.11f)));
00634         break;
00635         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00636                 m_pixel[2] = p.m_pixel[2];
00637         break;
00638         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00639                 m_pixel[2] = p.m_pixel[2]; m_pixel[3] = p.m_pixel[3];
00640         break;
00641         }
00642     }
00643 
00645     PixelType<ChanType, NumChans>(const PixelType<float32Channel, 3> &p)
00646     {
00647         switch (NumChans) { // this switch gets resolved at compile time
00648         case 2: m_pixel[1] = ChanType(float32Channel(1.0f));
00649         case 1: m_pixel[0] = ChanType(float32Channel(((float)p.m_pixel[0]*0.30f) +
00650                                                      ((float)p.m_pixel[1]*0.59f) +
00651                                                      ((float)p.m_pixel[2]*0.11f)));
00652         break;
00653         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00654                 m_pixel[2] = p.m_pixel[2];
00655         break;
00656         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[1];
00657                 m_pixel[2] = p.m_pixel[2];
00658                 m_pixel[3] = ChanType(float32Channel(1.0f));
00659         break;
00660         }
00661     }
00662 
00664     PixelType<ChanType, NumChans>(const PixelType<float32Channel, 2> &p)
00665     {
00666         switch (NumChans) { // this switch gets resolved at compile time
00667         case 1: m_pixel[0] = p.m_pixel[0];
00668         break;
00669         case 2: m_pixel[0] = p.m_pixel[0]; 
00670                 m_pixel[1] = p.m_pixel[1]; 
00671         break;
00672         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00673                 m_pixel[2] = p.m_pixel[0];
00674         break;
00675         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00676                 m_pixel[2] = p.m_pixel[0];
00677                 m_pixel[3] = p.m_pixel[1];
00678         break;
00679         }
00680     }
00681 
00683     PixelType<ChanType, NumChans>(const PixelType<float32Channel, 1> &p)
00684     {
00685         switch (NumChans) { // this switch gets resolved at compile time
00686         case 2: m_pixel[1] = ChanType(float32Channel(1.0f));
00687         case 1: m_pixel[0] = p.m_pixel[0];
00688         break;
00689         case 3: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00690                 m_pixel[2] = p.m_pixel[0];
00691         break;
00692         case 4: m_pixel[0] = p.m_pixel[0]; m_pixel[1] = p.m_pixel[0];
00693                 m_pixel[2] = p.m_pixel[0]; m_pixel[3] = ChanType(float32Channel(1.0f));
00694         break;
00695         }
00696     }
00697 
00699     void SetLuminance(const PixelType<uInt8Channel, 4> &p)
00700     {
00701         if (NumChans == 4) {
00702             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00703             m_pixel[3] = ChanType(uInt16Channel(((uInt8)p.m_pixel[0]*77  +
00704                                                  (uInt8)p.m_pixel[1]*150 +
00705                                                  (uInt8)p.m_pixel[2]*28)));
00706         }
00707     }
00708 
00710     void SetLuminance(const PixelType<uInt8Channel, 3> &p)
00711     {
00712         if (NumChans == 4) {
00713             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00714             m_pixel[3] = ChanType(uInt16Channel(((uInt8)p.m_pixel[0]*77  +
00715                                                  (uInt8)p.m_pixel[1]*150 +
00716                                                  (uInt8)p.m_pixel[2]*28)));
00717         }
00718     }
00719 
00721     void SetLuminance(const PixelType<uInt16Channel, 4> &p)
00722     {
00723         if (NumChans == 4) {
00724             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00725             m_pixel[3] = ChanType(uInt16Channel(((((uInt16)p.m_pixel[0]*19660)>>16) +
00726                                                  (((uInt16)p.m_pixel[1]*38666)>>16) +
00727                                                  (((uInt16)p.m_pixel[2]*7209 )>>16))));
00728         }
00729     }
00730 
00732     void SetLuminance(const PixelType<uInt16Channel, 3> &p)
00733     {
00734         if (NumChans == 4) {
00735             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00736             m_pixel[3] = ChanType(uInt16Channel(((((uInt16)p.m_pixel[0]*19660)>>16) +
00737                                                  (((uInt16)p.m_pixel[1]*38666)>>16) +
00738                                                  (((uInt16)p.m_pixel[2]*7209 )>>16))));
00739         }
00740     }
00741 
00742 
00744     void SetLuminance(const PixelType<float16Channel, 4> &p)
00745     {
00746         if (NumChans == 4) {
00747             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00748             m_pixel[3] = ChanType(float32Channel((((float)p.m_pixel[0]*0.30f) +
00749                                                   ((float)p.m_pixel[1]*0.59f) +
00750                                                   ((float)p.m_pixel[2]*0.11f))));
00751         }
00752     }
00753 
00755     void SetLuminance(const PixelType<float16Channel, 3> &p)
00756     {
00757         if (NumChans == 4) {
00758             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00759             m_pixel[3] = ChanType(float32Channel((((float)p.m_pixel[0]*0.30f) +
00760                                                   ((float)p.m_pixel[1]*0.59f) +
00761                                                   ((float)p.m_pixel[2]*0.11f))));
00762         }
00763     }
00764 
00766     void SetLuminance(const PixelType<float32Channel, 4> &p)
00767     {
00768         if (NumChans == 4) {
00769             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00770             m_pixel[3] = ChanType(float32Channel((((float)p.m_pixel[0]*0.30f) +
00771                                                   ((float)p.m_pixel[1]*0.59f) +
00772                                                   ((float)p.m_pixel[2]*0.11f))));
00773         }
00774     }
00775 
00777     void SetLuminance(const PixelType<float32Channel, 3> &p)
00778     {
00779         if (NumChans == 4) {
00780             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00781             m_pixel[3] = ChanType(float32Channel((((float)p.m_pixel[0]*0.30f) +
00782                                                   ((float)p.m_pixel[1]*0.59f) +
00783                                                   ((float)p.m_pixel[2]*0.11f))));
00784         }
00785     }
00786 
00788     void SetLuminance(const PixelType<float32Channel, 1> &p)
00789     {
00790         if (NumChans == 4) {
00791             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00792             m_pixel[3] = ChanType(float32Channel(1.0f - ((float)p.m_pixel[0])));
00793         }
00794     }
00795 
00797     void SetLuminance(const PixelType<float16Channel, 1> &p)
00798     {
00799         if (NumChans == 4) {
00800             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00801             m_pixel[3] = ChanType(float32Channel(((float)p.m_pixel[0])));
00802         }
00803     }
00804 
00806     void SetLuminance(const PixelType<uInt16Channel, 1> &p)
00807     {
00808         if (NumChans == 4) {
00809             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00810             m_pixel[3] = ChanType(uInt16Channel(((uInt16)p.m_pixel[0])));
00811         }
00812     }
00813 
00815     void SetLuminance(const PixelType<uInt8Channel, 1> &p)
00816     {
00817         if (NumChans == 4) {
00818             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00819             m_pixel[3] = ChanType(uInt8Channel(((uInt8)p.m_pixel[0])));
00820         }
00821     }
00822 
00823 
00825     void SetInvLuminance(const PixelType<uInt8Channel, 4> &p)
00826     {
00827         if (NumChans == 4) {
00828             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00829             m_pixel[3] = ChanType(uInt16Channel(65535 -
00830                                                 ((uInt8)p.m_pixel[0]*77  +
00831                                                  (uInt8)p.m_pixel[1]*150 +
00832                                                  (uInt8)p.m_pixel[2]*28)));
00833         }
00834     }
00835 
00837     void SetInvLuminance(const PixelType<uInt8Channel, 3> &p)
00838     {
00839         if (NumChans == 4) {
00840             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00841             m_pixel[3] = ChanType(uInt16Channel(65535 -
00842                                                 ((uInt8)p.m_pixel[0]*77  +
00843                                                  (uInt8)p.m_pixel[1]*150 +
00844                                                  (uInt8)p.m_pixel[2]*28)));
00845         }
00846     }
00847 
00849     void SetInvLuminance(const PixelType<uInt16Channel, 4> &p)
00850     {
00851         if (NumChans == 4) {
00852             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00853             m_pixel[3] = ChanType(uInt16Channel(65535 -
00854                                                 ((((uInt16)p.m_pixel[0]*19660)>>16) +
00855                                                  (((uInt16)p.m_pixel[1]*38666)>>16) +
00856                                                  (((uInt16)p.m_pixel[2]*7209 )>>16))));
00857         }
00858     }
00859 
00861     void SetInvLuminance(const PixelType<uInt16Channel, 3> &p)
00862     {
00863         if (NumChans == 4) {
00864             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00865             m_pixel[3] = ChanType(uInt16Channel(65535 -
00866                                                 ((((uInt16)p.m_pixel[0]*19660)>>16) +
00867                                                  (((uInt16)p.m_pixel[1]*38666)>>16) +
00868                                                  (((uInt16)p.m_pixel[2]*7209 )>>16))));
00869         }
00870     }
00871 
00872 
00874     void SetInvLuminance(const PixelType<float16Channel, 4> &p)
00875     {
00876         if (NumChans == 4) {
00877             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00878             m_pixel[3] = ChanType(float32Channel(1.0f -
00879                                                  (((float)p.m_pixel[0]*0.30f) +
00880                                                   ((float)p.m_pixel[1]*0.59f) +
00881                                                   ((float)p.m_pixel[2]*0.11f))));
00882         }
00883     }
00884 
00886     void SetInvLuminance(const PixelType<float16Channel, 3> &p)
00887     {
00888         if (NumChans == 4) {
00889             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00890             m_pixel[3] = ChanType(float32Channel(1.0f -
00891                                                  (((float)p.m_pixel[0]*0.30f) +
00892                                                   ((float)p.m_pixel[1]*0.59f) +
00893                                                   ((float)p.m_pixel[2]*0.11f))));
00894         }
00895     }
00896 
00898     void SetInvLuminance(const PixelType<float32Channel, 4> &p)
00899     {
00900         if (NumChans == 4) {
00901             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00902             m_pixel[3] = ChanType(float32Channel(1.0f -
00903                                                  (((float)p.m_pixel[0]*0.30f) +
00904                                                   ((float)p.m_pixel[1]*0.59f) +
00905                                                   ((float)p.m_pixel[2]*0.11f))));
00906         }
00907     }
00908 
00910     void SetInvLuminance(const PixelType<float32Channel, 3> &p)
00911     {
00912         if (NumChans == 4) {
00913             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00914             m_pixel[3] = ChanType(float32Channel(1.0f - (((float)p.m_pixel[0]*0.30f) +
00915                                                          ((float)p.m_pixel[1]*0.59f) +
00916                                                          ((float)p.m_pixel[2]*0.11f))));
00917         }
00918     }
00919 
00921     void SetInvLuminance(const PixelType<float32Channel, 1> &p)
00922     {
00923         if (NumChans == 4) {
00924             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00925             m_pixel[3] = ChanType(float32Channel(1.0f - ((float)p.m_pixel[0])));
00926         }
00927     }
00928 
00930     void SetInvLuminance(const PixelType<float16Channel, 1> &p)
00931     {
00932         if (NumChans == 4) {
00933             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00934             m_pixel[3] = ChanType(float32Channel(1.0f - ((float)p.m_pixel[0])));
00935         }
00936     }
00937 
00939     void SetInvLuminance(const PixelType<uInt16Channel, 1> &p)
00940     {
00941         if (NumChans == 4) {
00942             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00943             m_pixel[3] = ChanType(uInt16Channel(65535 - ((uInt16)p.m_pixel[0])));
00944         }
00945     }
00946 
00948     void SetInvLuminance(const PixelType<uInt8Channel, 1> &p)
00949     {
00950         if (NumChans == 4) {
00951             m_pixel[0] = m_pixel[1] = m_pixel[2] = 
00952             m_pixel[3] = ChanType(uInt8Channel(255 - ((uInt8)p.m_pixel[0])));
00953         }
00954     }
00955 };
00956 
00957 
00958 //------------------------------------------------------------------------------
00960 class MBDLL_DECL ImgTile
00961 {
00962 public:
00963     int  x;   
00964     int  y;   
00965     int  nx;  
00966     int  ny;  
00969     inline ImgTile() : x(0), y(0), nx(0), ny(0) {}
00970 
00978     inline ImgTile(int X, int Y, int NX, int NY) : x(X), y(Y), nx(NX), ny(NY) {}
00979 
00980     #if !defined MAX
00981     #define MAX(a_, b_) (((a_) > (b_)) ? (a_) : (b_))
00982     #endif
00983     #if !defined MIN
00984     #define MIN(a_, b_) (((a_) < (b_)) ? (a_) : (b_))
00985     #endif
00986 
00992     ImgTile(const ImgTile &a, const ImgTile &b)
00993     {
00994         x  = MAX(a.x, b.x);
00995         y  = MAX(a.y, b.y);
00996         nx = MIN(a.x+a.nx, b.x+b.nx) - x;
00997         ny = MIN(a.y+a.ny, b.y+b.ny) - y;
00998         if (nx <= 0 || ny <= 0) x = y = nx = ny = 0;
00999     }
01000 
01001     inline bool isEqualTile(const ImgTile &t) const
01002     { return x == t.x && y == t.y && nx == t.nx && ny == t.ny; }
01003 
01004     inline bool operator ==(const ImgTile &t) const
01005     { return x == t.x && y == t.y && nx == t.nx && ny == t.ny; }
01006 
01007     inline bool operator !=(const ImgTile &t) const
01008     { return !(t == *this); }
01009 
01011     inline bool isEmpty() const { return nx <= 0 || ny <= 0; }
01012 
01013     inline void setEmpty() { x = y = nx = ny = 0; }
01014 
01016     inline bool contains(const ImgTile &a) const
01017     { return x <= a.x && a.x+a.nx <= x+nx &&
01018              y <= a.y && a.y+a.ny <= y+ny;
01019     }
01020 
01022     inline bool contains(int x_, int y_) const
01023     { return x <= x_ && x_ < x+nx && y <= y_ && y_ < y+ny;
01024     }
01025 
01027     void clipPositive()
01028     {
01029         if (x < 0) {
01030             nx += x; x = 0;
01031             if (nx < 0) x = y = nx = ny = 0;
01032         }
01033         if (y < 0) {
01034             ny += y; y = 0;
01035             if (ny < 0) x = y = nx = ny = 0;
01036         }
01037     }
01038 
01040     void ExpandToInclude(int x_, int y_)
01041     {
01042         if (isEmpty()) {
01043             x = x_; y = y_; nx = 1; ny = 1;
01044         } else {
01045             if (x_ < x) { nx += (x - x_); x = x_; }
01046             if (y_ < y) { ny += (y - y_); y = y_; }
01047 
01048             if (x + nx < x_) nx = (x_ - x) + 1;
01049             if (y + ny < y_) ny = (y_ - y) + 1;
01050         }
01051     }
01052 
01054     void Expand(int numPixels = 1)
01055     {
01056         x  -= numPixels; y  -= numPixels;
01057         numPixels <<= 1;
01058         nx += numPixels; ny += numPixels;
01059     }
01060 
01062     int numPixels() const { return isEmpty() ? 0 : nx * ny; }
01063 };
01064 
01065 
01066 //------------------------------------------------------------------------------
01067 #define MAX_DIRTY_REGION          8192    // same as max texture size...
01068 #define DIRTY_REGION_GRANULARITY  128     // make this a power of 2.
01069 #define DIRTY_REGION_MASK         (DIRTY_REGION_GRANULARITY-1)
01070 #define DIRTY_REGION_SHIFT        7
01071 #define DIRTY_REGION_XY_SIZE      ( MAX_DIRTY_REGION / DIRTY_REGION_GRANULARITY )
01072 
01073 //------------------------------------------------------------------------------
01080 class MBDLL_DECL ImgDirtyRegion {  // should be 4K + 16 bytes when the max texture size is 8Kx8K texels
01081 private:
01082     // each char in this array represents a 128x128 pixel region of an image
01083     // using char as it is guaranteed to be 1 byte. bool is not.
01084     char     m_DirtyChunks[DIRTY_REGION_XY_SIZE * DIRTY_REGION_XY_SIZE];
01085     int      m_ChunksSet;
01086     int      m_NumTiles;
01087     ImgTile *m_DirtyTiles;
01088     ImgTile  m_DirtyTotalChunks;
01089     int      m_InTileCount;
01090 
01091     void     ComputeDirtyTiles();
01092 
01093     // this just clears the output tile list, not the bit-map.
01094     void     ClearDirtyTiles() 
01095     {
01096         if (m_DirtyTiles) delete [] m_DirtyTiles;
01097         m_NumTiles = 0; m_DirtyTiles = 0;
01098     }
01099 
01100     // compute the address of the byte for a chunk at the given chunk coordinates
01101     char *Index(int x, int y)
01102     {
01103         return &m_DirtyChunks[(y * DIRTY_REGION_XY_SIZE) + x];
01104     }
01105 
01106     // set the value at the specified image coordinates to 1, return the old value.
01107     char Set(int x, int y)  { char c = *Index(x, y); *Index(x, y) = 1; return c; }
01108 
01109     // return the value at the specified  chunk coordinates.
01110     char Get(int x, int y)  { return *Index(x, y); }
01111 
01112 public:
01113     ImgDirtyRegion()  { m_DirtyTiles = 0; ClearDirtyRegion(); }
01114     ~ImgDirtyRegion() { ClearDirtyTiles();  }
01115 
01118     void AddToDirtyRegion(const ImgTile &dirtyTile);
01119 
01121     void ClearDirtyRegion()
01122     {
01123         ClearDirtyTiles();
01124         memset(m_DirtyChunks, 0, DIRTY_REGION_XY_SIZE * DIRTY_REGION_XY_SIZE);
01125         m_ChunksSet = 0;
01126         m_DirtyTotalChunks.setEmpty();
01127         m_InTileCount = 0;
01128     }
01129 
01131     int numTiles() 
01132     {
01133         if (!m_DirtyTiles) ComputeDirtyTiles();
01134         return m_NumTiles;
01135     }
01136 
01138     ImgTile Tile(int i)
01139     {
01140         return m_DirtyTiles[i];
01141     }
01142 
01144     ImgTile GetTotalBounds() const
01145     {
01146         return m_DirtyTotalChunks; 
01147     }
01148 
01150     bool isEmpty() const { return m_DirtyTotalChunks.isEmpty(); }
01151 
01153     void Union(const ImgDirtyRegion &other);
01154 
01155     void DumpToLog();
01156 
01157     ImgDirtyRegion& operator= ( const ImgDirtyRegion& cOther );
01158 };
01159 
01160 
01161 //------------------------------------------------------------------------------
01164 class MBDLL_DECL ImgTile_AoutB_Iter : public ImgTile {
01165 private:
01166     int            ax1, ax2, bx1, bx2;
01167     int            ay1, ay2, by1, by2;
01168     signed char    state;
01169     bool           ad,  bd;
01170 
01171 public:
01172     ImgTile_AoutB_Iter(const ImgTile &A, const ImgTile &B) :
01173         ax1   (A.x), ax2 (A.x + A.nx - 1),
01174         bx1   (B.x), bx2 (B.x + B.nx - 1),
01175         ay1   (A.y), ay2 (A.y + A.ny - 1),
01176         by1   (B.y), by2 (B.y + B.ny - 1),
01177         state (0),
01178         ad    (A.nx <= 0 || A.ny <= 0),
01179         bd    (B.nx <= 0 || B.ny <= 0) {}
01180 
01181     virtual bool next();
01182 };
01183 
01184 
01185 //-----------------------------------------------------------------------------
01186 class MBDLL_DECL ImgTileUnion : public ImgTile {
01187 public:
01188     ImgTileUnion(const ImgTile &A, const ImgTile &B);
01189 };
01190 
01191 
01198 class MBDLL_DECL ImgPageIterator : public ImgTile {
01199 protected:
01200     void    *m_BlindData;
01201     Image   *m_Image;
01202     int      m_Type;
01203     void    *m_PixelData;
01204     ImgTile  m_SrcTile;
01205 
01206 
01207 public:
01216     ImgPageIterator(Image *img, const ImgTile *srcTile = 0, bool writing = false);
01217     virtual ~ImgPageIterator();
01218     virtual bool  next();
01219     void         *dataPtr() { return m_PixelData; }
01220 };
01221 
01222 
01223 //------------------------------------------------------------------------------
01225 class MBDLL_DECL ImgLockPageIterator : public ImgPageIterator {
01226 public:
01227     typedef enum {
01228         ReadOnly,   
01229         ReadWrite,  
01230         WriteOnly   
01231     } AccessMode;
01232 
01233 protected:
01234     bool        m_SmartImage;
01235     AccessMode  m_Mode;
01236 
01237 public:
01238     ImgLockPageIterator(Image *img, const ImgTile *srcTile = 0, AccessMode mode = ReadOnly);
01239     ~ImgLockPageIterator();
01240 
01241     virtual bool  next();
01242     void         *dataPtr();
01243 };
01244 
01245 //------------------------------------------------------------------------------
01255 class PixelDescriptor {
01256 public:
01258     typedef enum {
01259         uChar   = 0,  
01260         uShort  = 1,  
01261         sHalf   = 2,  
01262         sFloat  = 3,  
01264         sChar   = 4,  
01265         sShort  = 5,  
01266         uInt    = 6,  
01267         sInt    = 7,  
01268         sDouble = 8   
01269     } ChannelType;
01270 
01273     typedef enum {
01274         orderNONE = 0, 
01275         orderRGBA = 1, 
01276         orderABGR = 2, 
01277         orderBGRA = 3, 
01278         orderARGB = 4, 
01279         orderRGB  = 5, 
01280         orderBGR  = 6  
01281     } MemoryChannelOrder;
01282 
01283 protected:
01284     char                m_cCount;        
01285     ChannelType         m_channelType;   
01286     MemoryChannelOrder  m_channelOrder;  
01287     bool                m_PreMultiplied; 
01290 public:
01291 
01292     PixelDescriptor(char                cCount,
01293                     ChannelType         channelType,
01294                     MemoryChannelOrder  channelOrder,
01295                     bool                PreMultiplied)
01296         : m_cCount       (cCount)
01297         , m_channelType  (channelType)
01298         , m_channelOrder (channelOrder)
01299         , m_PreMultiplied(PreMultiplied) {}
01300 
01302     int channelSize() const {
01303         static const unsigned char s_channelByteCount[] = {1, 2, 2, 4, 1, 2, 4, 4, 8};
01304         return s_channelByteCount[m_channelType];
01305     }
01306 
01308     int channelBitSize() const {
01309         return channelSize() * 8;
01310     }
01311 
01313     int pixelSize() const {
01314         return channelSize() * m_cCount;
01315     }
01316 
01318     int pixelBitSize() const {
01319         return pixelSize() * 8;
01320     }
01321 
01323     ChannelType channelType() const { return m_channelType; }
01324 
01326     MemoryChannelOrder channelOrder() const { return m_channelOrder; }
01327 
01330     bool premultiplied() const { return m_PreMultiplied; }
01331 
01333     int channelCount() const   { return m_cCount; }
01334 
01336     void setChannelCount(int c) { m_cCount = c; }
01337 
01339     bool operator == (const PixelDescriptor &pd) const
01340     { return (m_cCount         == pd.m_cCount        &&
01341               m_channelType    == pd.m_channelType   &&
01342               m_channelOrder   == pd.m_channelOrder  &&
01343               m_PreMultiplied  == pd.m_PreMultiplied);
01344     }
01345 };
01346 
01347 
01348 
01349 //------------------------------------------------------------------------------
01353 class ImageDescriptor : public PixelDescriptor {
01354 
01355 public:
01357     enum ResUnit { k_PixelsPerInch       = 1, 
01358                    k_PixelsPerCentimeter = 2  
01359     };
01360 
01361 protected:
01362     ImgTile   m_Bounds; 
01364     float     m_xResolution;      
01365     float     m_yResolution;      
01366     ResUnit   m_ResolutionUnits;  
01368 public:
01369 
01382     ImageDescriptor(int x, int y, int nx, int ny,
01383                     MemoryChannelOrder order = orderRGBA,
01384                     bool premult = true,
01385                     char nc = 4, ChannelType ct = uChar) :
01386         PixelDescriptor(nc, ct, order, premult),
01387         m_Bounds(x, y, nx, ny),
01388         m_xResolution(100.0f), m_yResolution(100.0f),
01389         m_ResolutionUnits(k_PixelsPerInch) {}
01390 
01401     ImageDescriptor(int nx, int ny,
01402                     MemoryChannelOrder order = orderRGBA,
01403                     bool premult = true,
01404                     char nc = 4, ChannelType ct = uChar) :
01405         PixelDescriptor(nc, ct, order, premult),
01406         m_Bounds(0, 0, nx, ny) {}
01407 
01409     ImageDescriptor() :
01410         PixelDescriptor(4, uChar,  orderRGBA, true),
01411         m_Bounds(0,0,0,0) {}
01412 
01415     int numBytes() const    { return m_Bounds.nx * m_Bounds.ny * pixelSize(); }
01416 
01418     int strideBytes() const { return m_Bounds.nx * pixelSize(); }
01419 
01421     int xSize() const { return m_Bounds.nx;  }
01422 
01424     int ySize() const { return m_Bounds.ny;  }
01425 
01427     int cSize() const { return m_cCount; }
01428 
01432     bool sizeEqual(const ImageDescriptor &o) const
01433         { return ((xSize() == o.xSize()) && (ySize() == o.ySize())); }
01434 
01436     void setSize(int nx, int ny) { m_Bounds.nx = nx; m_Bounds.ny = ny; }
01437 
01439     const ImgTile &getBounds() const { return m_Bounds; }
01440 
01447     void getResolutionInfo(float &xRes, float &yRes, ResUnit &unit) const
01448     {
01449         xRes = m_xResolution; yRes = m_yResolution, unit = m_ResolutionUnits;
01450     }
01451 
01458     void setResolutionInfo(float xRes, float yRes, ResUnit unit)
01459     {
01460         m_xResolution = xRes; m_yResolution = yRes, m_ResolutionUnits = unit;
01461     }
01462 
01463     friend class Image;                                                                    
01464 };
01465 
01466 
01467 //------------------------------------------------------------------------------
01474 typedef bool (*ProxyInterruptFunction)(void);
01475 
01476 #define MAX_PROXY_LEVEL 4
01477 
01478 //------------------------------------------------------------------------------
01503 
01504 class MBDLL_DECL Image : public Node
01505 {
01506 
01507     DECLARE_CLASS;
01508 
01509     friend class ImgPageIterator;
01510     friend class ImgLockPageIterator;
01511 
01512 
01513 public:
01515     typedef enum {
01516         Type_Invalid = 0,
01517         Type_Memory,       
01518         Type_Virtual       
01519     } ImageType;
01520 
01522     enum Format
01523     {
01524         e8integer = 0,
01525         e16integer,
01526         e32integer,
01527         e16float,
01528         e32float,
01529         e16depth,
01530         e24depth,
01531         e32depth,
01532         eUnknown,
01533         eInvalid,
01534     };
01535 
01536     virtual ~Image( void );
01537 
01538 protected:
01539 
01540     Image( void );
01541 
01542     unsigned char    m_FillPixel[16]; // fill color -- largest supported pixel is 16 bytes.
01543     ImageDescriptor  m_Descriptor;    // how to interpret the pixel data
01544 
01545     ImageType        m_ImageType;
01546 
01547     unsigned char    m_ProxyLevel;
01548     Image           *m_pProxyImages[MAX_PROXY_LEVEL+1];
01549     bool             m_bDownsampleProxyTo8Bit;
01550 
01551     ProxyInterruptFunction  m_pProxyIntFcn;
01552 
01553     void             markProxyDirty() 
01554     { 
01555         for (int i = 0; i < MAX_PROXY_LEVEL+1; ++i) {
01556             if (m_pProxyImages[i]) {
01557                 delete m_pProxyImages[i]; m_pProxyImages[i] = 0;
01558             }
01559         }
01560     }
01561 
01562     virtual bool     regenerateProxy();
01563     bool             isProxyDirty() const 
01564         { return (m_ProxyLevel > 0) ? (m_pProxyImages[m_ProxyLevel] == 0) : false; }
01565 
01566 
01567     // Generate a downsampled proxy of this image. The targetImg is created,
01568     // and populated. Current levels supported are 1, 2, and 3.
01569     // (representing 1/2, 1/4, and 1/8 size proxies)
01570     // This function only works on tiled images.
01571     // Works on 1, 2, and 4 channel images. (not 3 channel)
01572     // uchar, ushort, half, and float images are supported on input. 
01573     // Output will be uchar by default, but if you set DownsampleTo8Bits 
01574     // to false, the output image will have the same channel datatype
01575     // as the input image. With float images, no clamping will take place
01576     // when not downsampling to 8 bit per channel.
01577 
01578     virtual bool GenerateProxy(Image *targetImg, int level, bool DownsampleTo8Bits = true);
01579 
01580 
01581 public:
01582 
01585     void UnitTest(int iterations);
01586 
01587     virtual bool isAllocated() const;
01588 
01589     // Return a list of all extensions from all of our descendent classes.
01590     //
01591     static QString  AllSupportedExtensions( bool bRGBAOnly = false, 
01592                                             bool bRead     = true, 
01593                                             bool bDesc     = false,
01594                                             bool bPSD      = true,
01595                                             QString sDelimiter = ";");
01596 
01598     ImageType getType() const { return m_ImageType; }
01599 
01601     const ImageDescriptor  &getDescriptor() const  { return m_Descriptor; }
01602 
01603 
01608     void   setProxyDownsampleTo8Bit(bool downsampleTo8Bit = true) 
01609     { 
01610         if (m_bDownsampleProxyTo8Bit != downsampleTo8Bit) {
01611             m_bDownsampleProxyTo8Bit = downsampleTo8Bit; 
01612             markProxyDirty();
01613         }
01614     }
01615 
01616     bool   getProxyDownsampleTo8Bit() const { return m_bDownsampleProxyTo8Bit; }
01617 
01619     void   clearProxyImages() { markProxyDirty(); }
01620 
01624     void SetProxyInterruptFunction(ProxyInterruptFunction fcnPtr = 0)
01625     { m_pProxyIntFcn = fcnPtr; }
01626 
01627 
01635     unsigned char   getProxyLevel() const { return m_ProxyLevel; }
01636 
01638     bool        setProxyLevel(unsigned char newLevel) { 
01639         if ( xSize()>>newLevel == 0 || ySize()>>newLevel == 0 )
01640             return false;
01641         if (newLevel > MAX_PROXY_LEVEL) newLevel = MAX_PROXY_LEVEL;
01642         if (newLevel != m_ProxyLevel) {
01643             m_ProxyLevel = newLevel;
01644         }
01645 
01646         return true;
01647     }
01648 
01654     Image         *getProxyImage() 
01655     {
01656         if (m_ProxyLevel == 0) return this;
01657         
01658         if ( m_pProxyImages[m_ProxyLevel] ) return m_pProxyImages[m_ProxyLevel];
01659         
01660         bool generated = regenerateProxy();
01661         if (!generated && m_pProxyImages[m_ProxyLevel] != 0) {
01662             delete m_pProxyImages[m_ProxyLevel];
01663             m_pProxyImages[m_ProxyLevel] = 0;
01664         }
01665         return m_pProxyImages[m_ProxyLevel];
01666     }
01667 
01669     int            xSize() const { return m_Descriptor.xSize(); }
01670 
01672     int            ySize() const { return m_Descriptor.ySize(); }
01673 
01675     int            cSize() const { return m_Descriptor.cSize(); }
01676 
01678     int            curWidth()  const { return Width() >> getProxyLevel(); }
01679 
01681     int            curHeight() const { return Height() >> getProxyLevel(); }
01682 
01684     ImageDescriptor::MemoryChannelOrder channelOrder() const { return m_Descriptor.m_channelOrder; }
01685 
01687     const ImgTile  &getBounds() const { return m_Descriptor.getBounds(); }
01688 
01689     //====================================================================
01700     void  getFillColor(void *fillPixel, const PixelDescriptor *pd = 0) const;
01701 
01702     //====================================================================
01713     void  setFillColor(const void *fillPixel, const PixelDescriptor *pd = 0);
01714 
01715     //====================================================================
01733     void  getTile(int x, int y, int nx, int ny, void *data,
01734                   const PixelDescriptor *pd = 0)
01735        { getTile(ImgTile(x, y, nx, ny), data, pd); }
01736 
01737 
01738     //====================================================================
01762     void  getSubTile(int x,  int y,  int nx,  int ny, void *data,
01763                      int dx, int dy, int dnx, int dny,
01764                      const PixelDescriptor *pd = 0)
01765        { getSubTile(ImgTile(x, y, nx, ny), data, ImgTile(dx, dy, dnx, dny), pd); }
01766 
01767 
01768     //====================================================================
01784     void getTile(const ImgTile &srcTile, void *data,
01785                  const PixelDescriptor *pd = 0)
01786        { getSubTile(srcTile, data, srcTile, pd); }
01787 
01788     //====================================================================
01807     virtual void getSubTile(const ImgTile &srcTile, void *data,
01808                             const ImgTile &targetBounds,
01809                             const PixelDescriptor *pd = 0);
01810 
01811 
01812     //====================================================================
01833     void setTile(int x, int y, int nx, int ny, void *data,
01834                  const PixelDescriptor *pd = 0)
01835        { setTile(ImgTile(x, y, nx, ny), data, pd); }
01836 
01837     //====================================================================
01864     void setSubTile(int x,  int y,  int nx,  int ny, const void *data,
01865                     int dx, int dy, int dnx, int dny,
01866                     const PixelDescriptor *pd = 0)
01867        { setSubTile(ImgTile(x, y, nx, ny), data, ImgTile(dx, dy, dnx, dny), pd); }
01868 
01869     //====================================================================
01885     void setTile(const ImgTile &dstTile, const void *data,
01886                  const PixelDescriptor *pd = 0)
01887        { setSubTile(dstTile, data, dstTile, pd); }
01888 
01889     //====================================================================
01908     virtual void setSubTile(const ImgTile &dstTile, const void *data,
01909                             const ImgTile &sourceBounds,
01910                             const PixelDescriptor *pd = 0);
01911 
01912     //====================================================================
01937     void copyTile(int x, int y, int nx, int ny, Image &fromImg,
01938                   int ox, int oy)
01939        { copyTile(ImgTile(x, y, nx, ny), fromImg, ox, oy); }
01940 
01941 
01942     //====================================================================
01964     virtual void copyTile(const ImgTile &dstTile, Image &fromImg,
01965                           int ox, int oy);
01966 
01967     //====================================================================
01981     virtual void copyAll(Image &fromImg)
01982     {
01983         ImgTile srcBounds(fromImg.getBounds());
01984         copyTile(srcBounds, fromImg, srcBounds.x, srcBounds.y);
01985     }
01986 
01988     virtual void Clear();
01989 
01990     //====================================================================
02015     void fillTile(int x, int y, int nx, int ny, void *pixelData,
02016                   const PixelDescriptor *pd       = 0,
02017                   const ImgTile         *maskTile = 0)
02018     { fillTile(ImgTile(x, y, nx, ny), pixelData, pd, maskTile); }
02019 
02020     //====================================================================
02040     void fillTile(const ImgTile &dstTile, const void *pixelData,
02041                   const PixelDescriptor *pd,
02042                   const ImgTile         *maskTile);
02043 
02044     //====================================================================
02063     virtual void fillTile(const ImgTile         &dstTile,
02064                           const void            *pixelData,
02065                           const PixelDescriptor *pd = 0);
02066 
02067     //====================================================================
02077     virtual void getPageSize(int &nx, int &ny);
02078 
02079     //====================================================================
02092     ImgPageIterator *getPageIterator(int x, int y, int nx, int ny)
02093     { return getPageIterator(ImgTile(x, y, nx, ny)); }
02094 
02095     //====================================================================
02105     virtual ImgPageIterator *getPageIterator(const ImgTile &srcTile);
02106 
02107     //====================================================================
02123     ImgLockPageIterator *lockPageSet(int x, int y, int nx, int ny,
02124                                      ImgLockPageIterator::AccessMode mode)
02125     { return lockPageSet(ImgTile(x, y, nx, ny), mode); }
02126 
02127     //====================================================================
02140     virtual ImgLockPageIterator *lockPageSet(const ImgTile &srcTile,
02141                                              ImgLockPageIterator::AccessMode mode);
02142 
02143     static ImageDescriptor::MemoryChannelOrder optimizedChannelOrder();
02144 
02145     static void ConvertPixels(void *dst, const void *src, int numPix,
02146                               const PixelDescriptor &dstDesc,
02147                               const PixelDescriptor *srcDesc = 0);
02148 
02150     void CopyInverseLuminance(const Image &srcImage);
02151 
02153     void CopyLuminance(const Image &srcImage);
02154 
02171     virtual QString SupportedExtensions( bool bRGBAOnly = false,
02172                                         bool bRead     = true,
02173                                         bool bDesc     = false,
02174                                         bool bPSD      = true,
02175                                         QString sDelimiter = ";") const;
02176 
02181     virtual void Create( unsigned int iWidth, unsigned int iHeight,
02182                          unsigned int iChannelCount, Format eFormat = e8integer,
02183                          bool Tiled = false,
02184                         ImageDescriptor::MemoryChannelOrder eOrder = ImageDescriptor::orderRGBA);
02185 
02189     virtual void Load( const QString &sFileName, int iLayerIndex = 0, bool tiled = false );
02190 
02191     virtual bool GetPSDLayerMeta ( void *pPSDFile, int iLayerIndex, 
02192                                    QString &layerName, int &blendMode,
02193                                    float &opacity, bool &locked, 
02194                                    bool &visible, bool &transLocked);
02195 
02203     virtual bool LoadPSDLayer ( void *pPSDFile,
02204                                 int   iLayerIndex,
02205                                 bool  Tiled = false,
02206                                 bool  premult = true );
02207 
02208 
02209     virtual Image *ComputeDifferenceMask(Image *otherImg, int expansionRadius,
02210                                          int AARadius, bool &anyDiffs);
02211 
02220     virtual bool SavePSDLayerMeta ( void         *pPSDFile,
02221                                     int           iLayerIndex,
02222                                     const QString&pLayerName,
02223                                     float         opacity = 1.0f,
02224                                     bool          visible = true,
02225                                     bool          locked  = false,
02226                                     int           xOff    = 0,
02227                                     int           yOff    = 0,
02228                                     int           blendMode = -1);
02229 
02239     virtual bool SavePSDLayer ( void         *pPSDFile,
02240                                 int           iLayerIndex,
02241                                 const QString&pLayerName,
02242                                 float         opacity = 1.0f,
02243                                 bool          visible = true,
02244                                 bool          locked  = false,
02245                                 bool          needs_unpremult = true,
02246                                 int           xOff    = 0,
02247                                 int           yOff    = 0);
02248 
02254     virtual void *OpenPSDFile(const QString &pFileName, bool writing = false);
02255 
02258     virtual bool  GetPSDFileInfo(void *psdFile, int *width, int *height, int *numChannels,
02259                                  int *bitDepth, int *numLayers, int *curLayer);
02260 
02263     virtual bool  SetPSDFileInfo(void *psdFile, int width, int height, int numChannels,
02264                                  int bitDepth, int numLayers, int curLayer);
02265 
02267     virtual bool ClosePSDFile(void *psdFile);
02268 
02269 
02277     virtual void Save( const QString &sFileName, bool bForce = true,
02278                        Material *pMaterial = NULL,
02279                        float uStart = 0.0f, float vStart = 0.0f,
02280                        bool force_1_Channel_To_4_Channel = false);
02281 
02283     virtual unsigned int Width( void ) const;
02284 
02286     virtual unsigned int Height( void ) const;
02287 
02289     virtual Format Format( void ) const;
02290 
02292     virtual unsigned int ChannelCount( void ) const;
02293 
02295     virtual unsigned int BytesPerPixel( void ) const;
02296 
02298     unsigned int         curBytesPerPixel() const { return (getProxyLevel() != 0) ? ChannelCount() : BytesPerPixel(); }
02299 
02301     virtual unsigned int TotalBytes( void ) const;
02302 
02304     unsigned int         curTotalBytes(void) const { return curWidth() * curHeight() * curBytesPerPixel(); }
02305 
02310     virtual void SetValueAt( unsigned int iXPos, unsigned int iYPos,
02311                              unsigned int iChannel, float fValue );
02312 
02316     virtual float ValueAt( unsigned int iXPos, unsigned int iYPos,
02317                            unsigned int iChannel ) const;
02318 
02322     virtual float ValueAt( float fXPos, float fYPos, unsigned int iChannel ) const;
02323 
02326     virtual void SetColorAt( unsigned int iXPos, unsigned int iYPos,
02327                              const Color &cColor );
02328 
02330     virtual Color ColorAt( unsigned int iXPos, unsigned int iYPos ) const;
02331 
02333     virtual Color ColorAt( float fXPos, float fYPos ) const;
02334 
02338     virtual QImage *ConvertToQImage( );
02339 
02341     virtual void ConvertFromQImage( QImage &qImg, bool tiled = false);
02342 
02346     virtual bool Fragmented() const;
02347 
02349     virtual bool Tiled() const;
02350 
02352     bool Versioned() const { return Tiled(); }
02353 
02356     virtual bool NewVersion();
02357 
02361     virtual bool PrevVersion();
02362 
02366     virtual bool NextVersion();
02367 
02369     virtual int  NumVersions();
02370 
02374     virtual bool MergeOldestVersions();
02375 
02380     virtual bool PurgeNewerVersions();
02381 
02384     virtual bool PurgeAllButCurrentVersion();
02385 
02391     virtual void *Data( int iRow = -1, bool writing = true );
02392     virtual const void *Data( int iRow = -1, bool writing = false ) const;
02393 
02394 
02400     virtual void DrawUVs(Material *pMaterial,
02401                          float uStart = 0.0f, float vStart = 0.0f,
02402                          bool baseLevel = true);
02403 
02404 
02407     virtual void scaleTileBilinear_4Chan_uchar(float x, float y, float nx, float ny, // src tile (from this image)
02408                                                unsigned int *data,                   // target buffer 
02409                                                int dx, int dy, int dnx, int dny,     // target location and size of target buffer
02410                                                float xScale, float yScale) const;    // scale factors
02411 
02412 
02413 
02420     virtual void GenerateUpscaled(Image *targetImg, int factor);
02421 
02422 
02425     static void MultiplyRGBByAlpha_uc4(unsigned char *buffer, int numPixels);
02426 
02428     virtual bool   isDirty() const;
02429 
02433     virtual void   setDirty();
02434 
02436     virtual void   setClean();
02437 
02439     virtual void   VerticalFlip(); 
02440 
02442     virtual void   AdjustImageCacheSize();
02443 
02445     virtual void   ConvertTo4Channel();
02446 
02447 };
02448 
02449 //------------------------------------------------------------------------------
02450 MBDLL_DECL AttributeWidget *CreateNewImageWidget( QWidget *pParent, int iWidth,
02451                                                   AttributePointer<Image> *pImage );
02452 template <> inline
02453 AttributeWidget *AttributePointer<Image>::CreateEditorWidget( QWidget *pParent, int iWidth )
02454 { return CreateNewImageWidget( pParent, iWidth, this ); };
02455 
02456 class MBDLL_DECL EnvironmentMap : public Node
02457 {
02458     DECLARE_CLASS;
02459 
02460 protected:
02461 
02462     EnvironmentMap( void );
02463 
02464 public:
02468     virtual bool Load( const QString &sFileName );
02471     virtual unsigned int ConvertToOpenGLTexture( void );
02472 };
02473 
02474 
02475 //------------------------------------------------------------------------------
02477 
02478 // these are just shorthand -- they're undefined later in this file
02479 #define cu_int  const unsigned int
02480 #define u_int   unsigned int
02481 #define u_short unsigned short
02482 #define u_char  unsigned char
02483 
02484 #define inline __forceinline
02485 
02489 template <class ChannelType, cu_int nch>
02490 class MBDLL_TEMPLATE_DECL ImageAccessorBase
02491 {
02492 private:
02493     u_int        m_Stride;
02494     u_int        m_Height;
02495     u_int        m_chans;
02496     Image       *m_Image;
02497     ChannelType *m_pData;
02498 
02499 public:
02500     ImageAccessorBase(Image *parent)
02501     {
02502         m_Stride = parent->Width();
02503         m_Height = parent->Height();
02504         m_chans  = parent->ChannelCount();
02505         m_Image  = parent;
02506         m_pData  = (ChannelType *)parent->Data();
02507     }
02508 
02509     u_int Width()        const { return m_Stride; }
02510     u_int Height()       const { return m_Height; }
02511     u_int ChannelCount() const { return m_chans;  }
02512 
02516     inline void  SetValueAt(u_int X, u_int Y, u_int Ch, float fVal);
02517 
02519     inline float ValueAt(u_int X, u_int Y, u_int Ch) const;
02520 
02524     inline void  SetColorAt( u_int X, u_int Y, const Color &cColor );
02525 
02526     inline void *AddrAt(u_int X, u_int Y, u_int Ch);
02527 };
02528 
02529 //------------------------------------------------------------------------------
02530 template <class ChannelType, cu_int nch>
02531 class MBDLL_TEMPLATE_DECL ImageAccessor : public ImageAccessorBase<ChannelType, nch>
02532 {
02533 public:
02534     ImageAccessor(Image *parent) : ImageAccessorBase<ChannelType, nch>(parent)
02535     {
02536     }
02537 
02539     inline Color ColorAt( u_int X, u_int Y ) const;
02540 };
02541 
02542 
02543 //------------------------------------------------------------------------------
02544 template <class ChannelType>
02545 class ImageAccessor<ChannelType, 3> : public ImageAccessorBase<ChannelType, 3>
02546 {
02547 public:
02548     ImageAccessor(Image *parent) : ImageAccessorBase<ChannelType, 3>(parent)
02549     {
02550     }
02551 
02553     inline Color ColorAt( u_int X, u_int Y ) const
02554     {
02555         return Color(
02556                 ImageAccessorBase<ChannelType, 3>::ValueAt(X,Y,0),
02557                 ImageAccessorBase<ChannelType, 3>::ValueAt(X,Y,1),
02558                 ImageAccessorBase<ChannelType, 3>::ValueAt(X,Y,2),
02559                 1);
02560     }
02561 };
02562 
02563 //------------------------------------------------------------------------------
02564 template <class ChannelType>
02565 class MBDLL_TEMPLATE_DECL ImageAccessor<ChannelType, 2> : public ImageAccessorBase<ChannelType, 2>
02566 {
02567 public:
02568     ImageAccessor(Image *parent) : ImageAccessorBase<ChannelType, 2>(parent)
02569     {
02570     }
02571 
02573     inline Color ColorAt( u_int X, u_int Y ) const
02574     {
02575         return Color(
02576                 ImageAccessorBase<ChannelType, 2>::ValueAt(X,Y,0),
02577                 ImageAccessorBase<ChannelType, 2>::ValueAt(X,Y,1),
02578                 0, 1);
02579     }
02580 };
02581 
02582 //------------------------------------------------------------------------------
02583 template <class ChannelType>
02584 class MBDLL_TEMPLATE_DECL ImageAccessor<ChannelType, 1> : public ImageAccessorBase<ChannelType, 1>
02585 {
02586 public:
02587     ImageAccessor(Image *parent) : ImageAccessorBase<ChannelType, 1>(parent)
02588     {
02589     }
02590 
02592     inline Color ColorAt( u_int X, u_int Y ) const
02593     {
02594         return Color(ImageAccessorBase<ChannelType, 1>::ValueAt(X,Y,0), 0, 0, 1);
02595     }
02596 };
02597 
02598 //------------------------------------------------------------------------------
02599 template <>
02600 inline void *ImageAccessorBase<u_char, 1>::AddrAt(u_int X, u_int Y, u_int Ch)
02601 { return (void *)&m_pData[Ch + ((X + m_Stride * Y)    )]; }
02602 template <>
02603 inline void *ImageAccessorBase<u_char, 2>::AddrAt(u_int X, u_int Y, u_int Ch)
02604 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 2)]; }
02605 template <>
02606 inline void *ImageAccessorBase<u_char, 3>::AddrAt(u_int X, u_int Y, u_int Ch)
02607 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 3)]; }
02608 template <>
02609 inline void *ImageAccessorBase<u_char, 4>::AddrAt(u_int X, u_int Y, u_int Ch)
02610 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 4)]; }
02611 
02612 template <>
02613 inline void *ImageAccessorBase<u_short, 1>::AddrAt(u_int X, u_int Y, u_int Ch)
02614 { return (void *)&m_pData[Ch + ((X + m_Stride * Y)    )]; }
02615 template <>
02616 inline void *ImageAccessorBase<u_short, 2>::AddrAt(u_int X, u_int Y, u_int Ch)
02617 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 2)]; }
02618 template <>
02619 inline void *ImageAccessorBase<u_short, 3>::AddrAt(u_int X, u_int Y, u_int Ch)
02620 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 3)]; }
02621 template <>
02622 inline void *ImageAccessorBase<u_short, 4>::AddrAt(u_int X, u_int Y, u_int Ch)
02623 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 4)]; }
02624 
02625 
02626 template <>
02627 inline void *ImageAccessorBase<float, 1>::AddrAt(u_int X, u_int Y, u_int Ch)
02628 { return (void *)&m_pData[Ch + ((X + m_Stride * Y)    )]; }
02629 template <>
02630 inline void *ImageAccessorBase<float, 2>::AddrAt(u_int X, u_int Y, u_int Ch)
02631 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 2)]; }
02632 template <>
02633 inline void *ImageAccessorBase<float, 3>::AddrAt(u_int X, u_int Y, u_int Ch)
02634 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 3)]; }
02635 template <>
02636 inline void *ImageAccessorBase<float, 4>::AddrAt(u_int X, u_int Y, u_int Ch)
02637 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 4)]; }
02638 
02639 template <>
02640 inline void *ImageAccessorBase<half_, 1>::AddrAt(u_int X, u_int Y, u_int Ch)
02641 { return (void *)&m_pData[Ch + ((X + m_Stride * Y)    )]; }
02642 template <>
02643 inline void *ImageAccessorBase<half_, 2>::AddrAt(u_int X, u_int Y, u_int Ch)
02644 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 2)]; }
02645 template <>
02646 inline void *ImageAccessorBase<half_, 3>::AddrAt(u_int X, u_int Y, u_int Ch)
02647 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 3)]; }
02648 template <>
02649 inline void *ImageAccessorBase<half_, 4>::AddrAt(u_int X, u_int Y, u_int Ch)
02650 { return (void *)&m_pData[Ch + ((X + m_Stride * Y) * 4)]; }
02651 
02652 // implement the inline member fcns with specialization...
02653 template <>
02654 inline void ImageAccessorBase<u_char, 1>::SetValueAt(u_int X, u_int Y, u_int Ch, float fVal)
02655 { m_pData[Ch + ((X + m_Stride * Y)    )] = (u_char)(255.0f * fVal); }
02656 template <>
02657 inline void ImageAccessorBase<u_char, 2>::SetValueAt(u_int X, u_int Y, u_int Ch, float fVal)
02658 { m_pData[Ch + ((X + m_Stride * Y) * 2)] = (u_char)(255.0f * fVal); }
02659 template <>
02660 inline void ImageAccessorBase<u_char, 3>::SetValueAt(u_int X, u_int Y, u_int Ch, float fVal)
02661 { m_pData[Ch + ((X + m_Stride * Y) * 3)] = (u_char)(255.0f * fVal); }
02662 template <>
02663 inline void ImageAccessorBase<u_char, 4>::SetValueAt(u_int X, u_int Y, u_int Ch, float fVal)
02664 { m_pData[Ch + ((X + m_Stride * Y) * 4)] = (u_char)(255.0f * fVal); }
02665 
02666 template <>
02667 inline void ImageAccessorBase<u_short, 1>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02668 { m_pData[Ch + ((X + m_Stride * Y)    )] = (u_short)(65535.0f * fVal); }
02669 template <>
02670 inline void ImageAccessorBase<u_short, 2>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02671 { m_pData[Ch + ((X + m_Stride * Y) * 2)] = (u_short)(65535.0f * fVal); }
02672 template <>
02673 inline void ImageAccessorBase<u_short, 3>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02674 { m_pData[Ch + ((X + m_Stride * Y) * 3)] = (u_short)(65535.0f * fVal); }
02675 template <>
02676 inline void ImageAccessorBase<u_short, 4>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02677 { m_pData[Ch + ((X + m_Stride * Y) * 4)] = (u_short)(65535.0f * fVal); }
02678 
02679 //template <class ChannelType, cu_int nch>
02680 template <>
02681 inline void ImageAccessorBase<u_int, 1>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02682 { m_pData[Ch + ((X + m_Stride * Y)    )] = (u_int)(0xffffffff * fVal); }
02683 template <>
02684 inline void ImageAccessorBase<u_int, 2>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02685 { m_pData[Ch + ((X + m_Stride * Y) * 2)] = (u_int)(0xffffffff * fVal); }
02686 template <>
02687 inline void ImageAccessorBase<u_int, 3>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02688 { m_pData[Ch + ((X + m_Stride * Y) * 3)] = (u_int)(0xffffffff * fVal); }
02689 template <>
02690 inline void ImageAccessorBase<u_int, 4>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02691 { m_pData[Ch + ((X + m_Stride * Y) * 4)] = (u_int)(0xffffffff * fVal); }
02692 
02693 template <>
02694 inline void ImageAccessorBase<float, 1>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02695 { m_pData[Ch + ((X + m_Stride * Y)    )] = fVal; }
02696 template <>
02697 inline void ImageAccessorBase<float, 2>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02698 { m_pData[Ch + ((X + m_Stride * Y) * 2)] = fVal; }
02699 template <>
02700 inline void ImageAccessorBase<float, 3>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02701 { m_pData[Ch + ((X + m_Stride * Y) * 3)] = fVal; }
02702 template <>
02703 inline void ImageAccessorBase<float, 4>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02704 { m_pData[Ch + ((X + m_Stride * Y) * 4)] = fVal; }
02705 
02706 template <>
02707 inline float ImageAccessorBase<u_char, 1>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02708 { return m_pData[Ch + ((X + m_Stride * Y)    )] * (1.0f/255.0f); }
02709 template <>
02710 inline float ImageAccessorBase<u_char, 2>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02711 { return m_pData[Ch + ((X + m_Stride * Y) * 2)] * (1.0f/255.0f); }
02712 template <>
02713 inline float ImageAccessorBase<u_char, 3>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02714 { return m_pData[Ch + ((X + m_Stride * Y) * 3)] * (1.0f/255.0f); }
02715 template <>
02716 inline float ImageAccessorBase<u_char, 4>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02717 { return m_pData[Ch + ((X + m_Stride * Y) * 4)] * (1.0f/255.0f); }
02718 
02719 template <>
02720 inline float ImageAccessorBase<u_short, 1>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02721 { return m_pData[Ch + ((X + m_Stride * Y)    )] * (1.0f/65535.0f); }
02722 template <>
02723 inline float ImageAccessorBase<u_short, 2>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02724 { return m_pData[Ch + ((X + m_Stride * Y) * 2)] * (1.0f/65535.0f); }
02725 template <>
02726 inline float ImageAccessorBase<u_short, 3>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02727 { return m_pData[Ch + ((X + m_Stride * Y) * 3)] * (1.0f/65535.0f); }
02728 template <>
02729 inline float ImageAccessorBase<u_short, 4>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02730 { return m_pData[Ch + ((X + m_Stride * Y) * 4)] * (1.0f/65535.0f); }
02731 
02732 template <>
02733 inline float ImageAccessorBase<u_int, 1>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02734 { return m_pData[Ch + ((X + m_Stride * Y)    )] * (1.0f/float(0xffffffff)); }
02735 template <>
02736 inline float ImageAccessorBase<u_int, 2>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02737 { return m_pData[Ch + ((X + m_Stride * Y) * 2)] * (1.0f/float(0xffffffff)); }
02738 template <>
02739 inline float ImageAccessorBase<u_int, 3>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02740 { return m_pData[Ch + ((X + m_Stride * Y) * 3)] * (1.0f/float(0xffffffff)); }
02741 template <>
02742 inline float ImageAccessorBase<u_int, 4>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02743 { return m_pData[Ch + ((X + m_Stride * Y) * 4)] * (1.0f/float(0xffffffff)); }
02744 
02745 template <>
02746 inline float ImageAccessorBase<float, 1>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02747 { return m_pData[Ch + ((X + m_Stride * Y)    )]; }
02748 template <>
02749 inline float ImageAccessorBase<float, 2>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02750 { return m_pData[Ch + ((X + m_Stride * Y) * 2)]; }
02751 template <>
02752 inline float ImageAccessorBase<float, 3>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02753 { return m_pData[Ch + ((X + m_Stride * Y) * 3)]; }
02754 template <>
02755 inline float ImageAccessorBase<float, 4>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02756 { return m_pData[Ch + ((X + m_Stride * Y) * 4)]; }
02757 
02758 
02759 
02760 //------------------------------------------------------------------------------
02761 template <>
02762 inline Color ImageAccessor<float, 4>::ColorAt(u_int X, u_int Y) const
02763 {
02764     return Color(ValueAt(X,Y,0), ValueAt(X,Y,1), ValueAt(X,Y,2), ValueAt(X,Y,3));
02765 };
02766 
02767 //------------------------------------------------------------------------------
02768 template <>
02769 inline Color ImageAccessor<u_char, 4>::ColorAt(u_int X, u_int Y) const
02770 {
02771     return Color(ValueAt(X,Y,0), ValueAt(X,Y,1), ValueAt(X,Y,2), ValueAt(X,Y,3));
02772 };
02773 
02774 //------------------------------------------------------------------------------
02775 template <>
02776 inline Color ImageAccessor<u_short, 4>::ColorAt(u_int X, u_int Y) const
02777 {
02778     return Color(ValueAt(X,Y,0), ValueAt(X,Y,1), ValueAt(X,Y,2), ValueAt(X,Y,3));
02779 };
02780 
02781 //------------------------------------------------------------------------------
02782 template <>
02783 inline Color ImageAccessor<u_short, 3>::ColorAt(u_int X, u_int Y) const
02784 {
02785     return Color(ValueAt(X,Y,0), ValueAt(X,Y,1), ValueAt(X,Y,2), 1.0f);
02786 };
02787 
02788 //------------------------------------------------------------------------------
02789 template <>
02790 inline Color ImageAccessor<float, 3>::ColorAt(u_int X, u_int Y) const
02791 {
02792     return Color(ValueAt(X,Y,0), ValueAt(X,Y,1), ValueAt(X,Y,2), 1.0f);
02793 };
02794 
02795 //------------------------------------------------------------------------------
02796 template <>
02797 inline Color ImageAccessor<u_char, 3>::ColorAt(u_int X, u_int Y) const
02798 {
02799     return Color(ValueAt(X,Y,0), ValueAt(X,Y,1), ValueAt(X,Y,2), 1.0f);
02800 };
02801 
02802 //------------------------------------------------------------------------------
02803 template <>
02804 inline float ImageAccessorBase<half_, 3>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02805 { return float(m_pData[Ch + ((X + m_Stride * Y) * 3)]); }
02806 
02807 //------------------------------------------------------------------------------
02808 template <>
02809 inline float ImageAccessorBase<half_, 4>::ValueAt( u_int X, u_int Y, u_int Ch ) const
02810 { return float(m_pData[Ch + ((X + m_Stride * Y) * 4)]); }
02811 
02812 //------------------------------------------------------------------------------
02813 template <>
02814 inline void ImageAccessorBase<half_, 3>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02815 { m_pData[Ch + ((X + m_Stride * Y) * 3)] = fVal; }
02816 
02817 //------------------------------------------------------------------------------
02818 template <>
02819 inline void ImageAccessorBase<half_, 4>::SetValueAt( u_int X, u_int Y, u_int Ch, float fVal )
02820 { m_pData[Ch + ((X + m_Stride * Y) * 4)] = fVal; }
02821 
02822 
02823 //------------------------------------------------------------------------------
02824 template <>
02825 inline Color ImageAccessor<half_, 4>::ColorAt(u_int X, u_int Y) const
02826 {
02827     return Color(ValueAt(X,Y,0), ValueAt(X,Y,1), ValueAt(X,Y,2), ValueAt(X,Y,3));
02828 };
02829 
02830 //------------------------------------------------------------------------------
02831 template <>
02832 inline Color ImageAccessor<half_, 3>::ColorAt(u_int X, u_int Y) const
02833 {
02834     return Color(ValueAt(X,Y,0), ValueAt(X,Y,1), ValueAt(X,Y,2), 1.0f);
02835 };
02836 
02837 
02838 //------------------------------------------------------------------------------
02839 template <>
02840 inline void ImageAccessorBase<float, 4>::SetColorAt(u_int X, u_int Y, const Color &c)
02841 {
02842     SetValueAt(X, Y, 0, c.r);
02843     SetValueAt(X, Y, 1, c.g);
02844     SetValueAt(X, Y, 2, c.b);
02845     SetValueAt(X, Y, 3, c.a);
02846 };
02847 
02848 //------------------------------------------------------------------------------
02849 template <>
02850 inline void ImageAccessorBase<float, 3>::SetColorAt(u_int X, u_int Y, const Color &c)
02851 {
02852     SetValueAt(X, Y, 0, c.r);
02853     SetValueAt(X, Y, 1, c.g);
02854     SetValueAt(X, Y, 2, c.b);
02855 };
02856 
02857 //------------------------------------------------------------------------------
02858 template <>
02859 inline void ImageAccessorBase<half_, 4>::SetColorAt(u_int X, u_int Y, const Color &c)
02860 {
02861     SetValueAt(X, Y, 0, c.r);
02862     SetValueAt(X, Y, 1, c.g);
02863     SetValueAt(X, Y, 2, c.b);
02864     SetValueAt(X, Y, 3, c.a);
02865 };
02866 
02867 //------------------------------------------------------------------------------
02868 template <>
02869 inline void ImageAccessorBase<half_, 3>::SetColorAt(u_int X, u_int Y, const Color &c)
02870 {
02871     SetValueAt(X, Y, 0, c.r);
02872     SetValueAt(X, Y, 1, c.g);
02873     SetValueAt(X, Y, 2, c.b);
02874 };
02875 
02876 //------------------------------------------------------------------------------
02877 template <>
02878 inline void ImageAccessorBase<u_short, 4>::SetColorAt(u_int X, u_int Y, const Color &c)
02879 {
02880     SetValueAt(X, Y, 0, c.r);
02881     SetValueAt(X, Y, 1, c.g);
02882     SetValueAt(X, Y, 2, c.b);
02883     SetValueAt(X, Y, 3, c.a);
02884 };
02885 
02886 //------------------------------------------------------------------------------
02887 template <>
02888 inline void ImageAccessorBase<u_short, 3>::SetColorAt(u_int X, u_int Y, const Color &c)
02889 {
02890     SetValueAt(X, Y, 0, c.r);
02891     SetValueAt(X, Y, 1, c.g);
02892     SetValueAt(X, Y, 2, c.b);
02893 };
02894 
02895 //------------------------------------------------------------------------------
02896 template <>
02897 inline void ImageAccessorBase<u_char, 4>::SetColorAt(u_int X, u_int Y, const Color &c)
02898 {
02899     SetValueAt(X, Y, 0, c.r);
02900     SetValueAt(X, Y, 1, c.g);
02901     SetValueAt(X, Y, 2, c.b);
02902     SetValueAt(X, Y, 3, c.a);
02903 };
02904 
02905 //------------------------------------------------------------------------------
02906 template <>
02907 inline void ImageAccessorBase<u_char, 3>::SetColorAt(u_int X, u_int Y, const Color &c)
02908 {
02909     SetValueAt(X, Y, 0, c.r);
02910     SetValueAt(X, Y, 1, c.g);
02911     SetValueAt(X, Y, 2, c.b);
02912 };
02913 
02914 
02915 
02916 //------------------------------------------------------------------------------
02918 static inline void SnapOutTile(ImgTile &t)
02919 {
02920     static const int TILE_SNAP  = (128-1); // must be ((2^i)-1). 
02921     t.nx  += t.x - 1;    t.ny  += t.y - 1;
02922     t.x   &= ~TILE_SNAP; t.y   &= ~TILE_SNAP;
02923     t.nx  +=  TILE_SNAP; t.ny  +=  TILE_SNAP;
02924     t.nx  &= ~TILE_SNAP; t.ny  &= ~TILE_SNAP;
02925     t.nx  -= t.x;        t.ny  -= t.y;
02926 }
02927 
02928 
02929 //------------------------------------------------------------------------------
02930 #undef cu_int
02931 #undef u_int
02932 #undef u_short
02933 #undef u_char
02934 #undef inline
02935 
02936 //------------------------------------------------------------------------------
02937 
02938 }; // end of namespace mudbox
02939 #endif