- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Directories
- Examples

- File List
- File Members

# 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