gBitmap.h

Engine/source/gfx/bitmap/gBitmap.h

More...

Classes:

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef _GBITMAP_H_
 25#define _GBITMAP_H_
 26
 27#ifndef __RESOURCE_H__
 28#include "core/resource.h"
 29#endif
 30
 31#ifndef _SWIZZLE_H_
 32#include "core/util/swizzle.h"
 33#endif
 34
 35#ifndef _TVECTOR_H_
 36#include "core/util/tVector.h"
 37#endif
 38
 39#ifndef _GFXENUMS_H_
 40#include "gfx/gfxEnums.h" // For the format
 41#endif
 42
 43#ifndef _PROFILER_H_
 44#include "platform/profiler.h"
 45#endif
 46//-------------------------------------- Forward decls.
 47class Stream;
 48class RectI;
 49class Point2I;
 50class ColorI;
 51class LinearColorF;
 52
 53//------------------------------------------------------------------------------
 54//-------------------------------------- GBitmap
 55
 56class GBitmap
 57{
 58public:
 59   enum Constants
 60   {
 61      /// The maximum mipmap levels we support.  The current
 62      /// value lets us support up to 4096 x 4096 images.
 63      c_maxMipLevels = 13 
 64   };
 65
 66   enum TextureOp
 67   {
 68      Add,
 69      Subtract
 70   };
 71
 72   struct Registration
 73   {
 74      /// The read function prototype.
 75      typedef bool(*ReadFunc)(Stream &stream, GBitmap *bitmap);
 76
 77      /// The write function prototype.  Compression levels are image-specific - see their registration declaration for details.
 78      typedef bool(*WriteFunc)(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
 79
 80      /// Used to sort the registrations so that 
 81      /// lookups occur in a fixed order.
 82      U32 priority;
 83
 84      Vector<String>   extensions;     ///< the list of file extensions for this bitmap type [these should be lower case]
 85      
 86      ReadFunc    readFunc;            ///< the read function to call for this bitmap type
 87      WriteFunc   writeFunc;           ///< the write function to call for this bitmap type
 88      U32         defaultCompression;  ///< the default compression level [levels are image-specific - see their registration declaration for details]
 89
 90      Registration()
 91      {
 92         readFunc = NULL;
 93         writeFunc = NULL;
 94         defaultCompression = 0;
 95         priority = 0;
 96         VECTOR_SET_ASSOCIATION( extensions );
 97      }
 98   };
 99
100   /// Load the given bitmap file.  It will try known file
101   /// extensions if one is not specified.  If all else fails
102   /// it will look up the folder hierarchy for a match.
103   ///
104   /// Important: Don't do something like this...
105   ///
106   /// @code
107   ///    GBitmap* bitmap; // WRONG TYPE!
108   ///    bitmap = GBitmap::load( filename );
109   /// @endcode
110   ///
111   /// Resources are reference-counted and the smart pointer conversion will
112   /// release the bitmap and thus render the resulting bitmap pointer invalid!
113   /// The right way is like this:
114   ///
115   /// @code
116   ///    Resource<GBitmap> bitmap; // Correct!
117   ///    bitmap = GBitmap::load( filename );
118   /// @endcode
119   ///
120   static Resource<GBitmap> load(const Torque::Path &path);
121
122protected:
123
124   static Resource<GBitmap> _load(const Torque::Path &path);
125   static Resource<GBitmap> _search(const Torque::Path &path);
126
127public:
128   GBitmap();
129   GBitmap(const GBitmap&);
130
131   GBitmap(const U32  in_width,
132           const U32  in_height,
133           const bool in_extrudeMipLevels = false,
134           const GFXFormat in_format = GFXFormatR8G8B8 );
135
136   // This builds a GBitmap with the R8G8B8A8 format using the passed in
137   // data (assumes that there is width * height * 4 U8's in data)
138   GBitmap(const U32  in_width,
139           const U32  in_height,
140           const U8*  data );
141
142   virtual ~GBitmap();
143
144
145   static void sRegisterFormat( const Registration &reg );
146   static const Registration* sFindRegInfo( const String &extension );   
147   
148   /// Find the first file matching the registered extensions 
149   /// skipping the original.
150   static bool sFindFile( const Torque::Path &path, Torque::Path *outPath );
151
152   /// Given a path to a file, try all known extensions.  If the file exists on disk, fill in path
153   /// with the correct extension and return true.  Otherwise, return false.
154   static bool sFindFiles( const Torque::Path &path, Vector<Torque::Path> *outFoundPaths );
155
156   /// Returns a space separated string of all registered extensions.
157   static String sGetExtensionList();
158
159   void allocateBitmap(const U32  in_width,
160                       const U32  in_height,
161                       const bool in_extrudeMipLevels = false,
162                       const GFXFormat in_format = GFXFormatR8G8B8 );
163
164   void allocateBitmapWithMips(const U32  in_width,
165      const U32  in_height,
166      const U32  in_numMips,
167      const GFXFormat in_format = GFXFormatR8G8B8);
168
169   void extrudeMipLevels(bool clearBorders = false);
170   void chopTopMips(U32 mipsToChop);
171   void extrudeMipLevelsDetail();
172
173   U32   getNumMipLevels() const { return mNumMipLevels; }
174
175   GBitmap *createPaddedBitmap() const;
176   GBitmap *createPow2Bitmap() const;
177
178   /// Copies a color channel by index into the first channel 
179   /// of the output bitmap.  The output bitmap must be the same
180   /// dimensions as the source.
181   void copyChannel( U32 index, GBitmap *outBitmap ) const;
182   
183   void copyRect(const GBitmap *in, const RectI &srcRect, const Point2I &dstPoint, const U32 srcMipLevel = 0, const U32 dstMipLevel = 0);
184
185   GFXFormat   getFormat() const { return mInternalFormat; }
186   bool        setFormat(GFXFormat fmt);
187
188   U32         getWidth(const U32 in_mipLevel  = 0) const;
189   U32         getHeight(const U32 in_mipLevel = 0) const;
190   U32         getDepth(const U32 in_mipLevel = 0) const;
191
192   U8*         getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel = 0);
193   const U8*   getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel = 0) const;
194
195   const U8*   getBits(const U32 in_mipLevel = 0) const;
196   U8*         getWritableBits(const U32 in_mipLevel = 0);
197
198   U32         getByteSize() const { return mByteSize; }
199   U32         getBytesPerPixel() const { return mBytesPerPixel; }
200
201   U32         getSurfaceSize(const U32 mipLevel) const;
202
203   /// Use these functions to set and get the mHasTransparency value
204   /// This is used to indicate that this bitmap has pixels that have
205   /// an alpha value less than 255 (used by the auto-Material mapper)
206   bool        getHasTransparency() const { return mHasTransparency; }
207   void        setHasTransparency(bool hasTransparency) { mHasTransparency = hasTransparency; }
208   
209   /// In general you will want to use this function if there is not a
210   /// good spot in the bitmap loader(s) to check the alpha value of
211   /// the pixels. This function uses the texture format to loop over
212   /// the bitmap bits and to check for alpha values less than 255
213   bool        checkForTransparency();
214
215   LinearColorF      sampleTexel(F32 u, F32 v, bool retAlpha = false) const;
216   bool        getColor(const U32 x, const U32 y, ColorI& rColor) const;
217   bool        setColor(const U32 x, const U32 y, const ColorI& rColor);
218   U8          getChanelValueAt(U32 x, U32 y, U32 chan);
219
220   /// This method will combine bitmapA and bitmapB using the operation specified
221   /// by combineOp. The result will be stored in the bitmap that this method is
222   /// called on. The size of the resulting bitmap will be the larger of A and B.
223   /// The format of the resulting bitmap will be the format of A or B, whichever
224   /// has a larger byte size.
225   ///
226   /// @note There are some restrictions on ops and formats that will probably change
227   /// based on how we use this function.
228   bool combine( const GBitmap *bitmapA, const GBitmap *bitmapB, const TextureOp combineOp );
229
230   /// Fills the first mip level of the bitmap with the specified color.
231   void fill( const ColorI &rColor );
232
233   /// An optimized version of fill().
234   void fillWhite();
235
236   //-------------------------------------- Internal data/operators
237
238   void deleteImage();
239
240   //-------------------------------------- Input/Output interface
241
242   /// Read a bitmap from a stream
243   /// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
244   /// @param ioStream The stream to read from
245   bool  readBitmap( const String &bmType, Stream &ioStream );
246
247   /// Write a bitmap to a stream
248   /// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
249   /// @param ioStream The stream to read from
250   /// @param compressionLevel Image format-specific compression level.  If set to U32_MAX, we use the default compression defined when the format was registered.
251   bool  writeBitmap( const String &bmType, Stream &ioStream, U32 compressionLevel = U32_MAX );
252
253   bool readMNG(Stream& io_rStream);               // located in bitmapMng.cc
254   bool writeMNG(Stream& io_rStream) const;
255
256   bool read(Stream& io_rStream);
257   bool write(Stream& io_rStream) const;
258
259   template<class T, dsize_t mapLength>
260   void swizzle(const Swizzle<T,mapLength> *s);
261
262   static Vector<Registration>   sRegistrations;
263
264private:
265   GFXFormat mInternalFormat;
266
267   U8* mBits; // Master bytes
268   U32 mByteSize;
269   U32 mWidth;
270   U32 mHeight;
271   U32 mBytesPerPixel;
272
273   U32 mNumMipLevels;
274   U32 mMipLevelOffsets[c_maxMipLevels];
275
276   bool mHasTransparency;
277
278   static const U32 csFileVersion;
279};
280
281//------------------------------------------------------------------------------
282//-------------------------------------- Inlines
283//
284
285inline U32 GBitmap::getWidth(const U32 in_mipLevel) const
286{
287   AssertFatal(in_mipLevel < mNumMipLevels,
288               avar("GBitmap::getWidth: mip level out of range: (%d, %d)",
289                    in_mipLevel, mNumMipLevels));
290
291   U32 retVal = mWidth >> in_mipLevel;
292
293   return (retVal != 0) ? retVal : 1;
294}
295
296inline U32 GBitmap::getHeight(const U32 in_mipLevel) const
297{
298   AssertFatal(in_mipLevel < mNumMipLevels,
299               avar("Bitmap::getHeight: mip level out of range: (%d, %d)",
300                    in_mipLevel, mNumMipLevels));
301
302   U32 retVal = mHeight >> in_mipLevel;
303
304   return (retVal != 0) ? retVal : 1;
305}
306
307inline const U8* GBitmap::getBits(const U32 in_mipLevel) const
308{
309   AssertFatal(in_mipLevel < mNumMipLevels,
310               avar("GBitmap::getBits: mip level out of range: (%d, %d)",
311                    in_mipLevel, mNumMipLevels));
312
313   return &mBits[mMipLevelOffsets[in_mipLevel]];
314}
315
316inline U8* GBitmap::getWritableBits(const U32 in_mipLevel)
317{
318   AssertFatal(in_mipLevel < mNumMipLevels,
319               avar("GBitmap::getWritableBits: mip level out of range: (%d, %d)",
320                    in_mipLevel, mNumMipLevels));
321
322   return &mBits[mMipLevelOffsets[in_mipLevel]];
323}
324
325inline U8* GBitmap::getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel)
326{
327   return (getWritableBits(mipLevel) + ((in_y * getWidth(mipLevel)) + in_x) * mBytesPerPixel);
328}
329
330inline const U8* GBitmap::getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel) const
331{
332   return (getBits(mipLevel) + ((in_y * getWidth(mipLevel)) + in_x) * mBytesPerPixel);
333}
334
335template<class T, dsize_t mapLength>
336void GBitmap::swizzle(const Swizzle<T,mapLength> *s )
337{
338   const U32 memSize = getWidth() * getHeight() * mBytesPerPixel;
339
340   void *b = dMalloc(memSize);
341
342   s->ToBuffer(b, getWritableBits(), memSize);
343
344   dMemcpy(getWritableBits(), b, memSize);
345
346   dFree(b);
347}
348
349#endif //_GBITMAP_H_
350