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//-------------------------------------- Forward decls.
 44class Stream;
 45class RectI;
 46class Point2I;
 47class ColorI;
 48class ColorF;
 49
 50//------------------------------------------------------------------------------
 51//-------------------------------------- GBitmap
 52
 53class GBitmap
 54{
 55public:
 56   enum Constants
 57   {
 58      /// The maximum mipmap levels we support.  The current
 59      /// value lets us support up to 4096 x 4096 images.
 60      c_maxMipLevels = 13 
 61   };
 62
 63   struct Registration
 64   {
 65      /// The read function prototype.
 66      typedef bool(*ReadFunc)(Stream &stream, GBitmap *bitmap);
 67
 68      /// The write function prototype.  Compression levels are image-specific - see their registration declaration for details.
 69      typedef bool(*WriteFunc)(GBitmap *bitmap, Stream &stream, U32 compressionLevel);
 70
 71      /// Used to sort the registrations so that 
 72      /// lookups occur in a fixed order.
 73      U32 priority;
 74
 75      Vector<String>   extensions;     ///< the list of file extensions for this bitmap type [these should be lower case]
 76      
 77      ReadFunc    readFunc;            ///< the read function to call for this bitmap type
 78      WriteFunc   writeFunc;           ///< the write function to call for this bitmap type
 79      U32         defaultCompression;  ///< the default compression level [levels are image-specific - see their registration declaration for details]
 80
 81      Registration()
 82      {
 83         priority = 0;
 84         VECTOR_SET_ASSOCIATION( extensions );
 85      }
 86   };
 87
 88   /// Load the given bitmap file.  It will try known file
 89   /// extensions if one is not specified.  If all else fails
 90   /// it will look up the folder hierarchy for a match.
 91   ///
 92   /// Important: Don't do something like this...
 93   ///
 94   /// @code
 95   ///    GBitmap* bitmap; // WRONG TYPE!
 96   ///    bitmap = GBitmap::load( filename );
 97   /// @endcode
 98   ///
 99   /// Resources are reference-counted and the smart pointer conversion will
100   /// release the bitmap and thus render the resulting bitmap pointer invalid!
101   /// The right way is like this:
102   ///
103   /// @code
104   ///    Resource<GBitmap> bitmap; // Correct!
105   ///    bitmap = GBitmap::load( filename );
106   /// @endcode
107   ///
108   static Resource<GBitmap> load(const Torque::Path &path);
109
110protected:
111
112   static Resource<GBitmap> _load(const Torque::Path &path);
113   static Resource<GBitmap> _search(const Torque::Path &path);
114
115public:
116   GBitmap();
117   GBitmap(const GBitmap&);
118
119   GBitmap(const U32  in_width,
120           const U32  in_height,
121           const bool in_extrudeMipLevels = false,
122           const GFXFormat in_format = GFXFormatR8G8B8 );
123
124   // This builds a GBitmap with the R8G8B8A8 format using the passed in
125   // data (assumes that there is width * height * 4 U8's in data)
126   GBitmap(const U32  in_width,
127           const U32  in_height,
128           const U8*  data );
129
130   virtual ~GBitmap();
131
132
133   static void sRegisterFormat( const Registration &reg );
134   static const Registration* sFindRegInfo( const String &extension );   
135   
136   /// Find the first file matching the registered extensions 
137   /// skipping the original.
138   static bool sFindFile( const Torque::Path &path, Torque::Path *outPath );
139
140   /// Given a path to a file, try all known extensions.  If the file exists on disk, fill in path
141   /// with the correct extension and return true.  Otherwise, return false.
142   static bool sFindFiles( const Torque::Path &path, Vector<Torque::Path> *outFoundPaths );
143
144   /// Returns a space separated string of all registered extensions.
145   static String sGetExtensionList();
146
147   void allocateBitmap(const U32  in_width,
148                       const U32  in_height,
149                       const bool in_extrudeMipLevels = false,
150                       const GFXFormat in_format = GFXFormatR8G8B8 );
151
152   void extrudeMipLevels(bool clearBorders = false);
153   void extrudeMipLevelsDetail();
154
155   U32   getNumMipLevels() const { return mNumMipLevels; }
156
157   GBitmap *createPaddedBitmap() const;
158   GBitmap *createPow2Bitmap() const;
159
160   /// Copies a color channel by index into the first channel 
161   /// of the output bitmap.  The output bitmap must be the same
162   /// dimensions as the source.
163   void copyChannel( U32 index, GBitmap *outBitmap ) const;
164   
165   void copyRect(const GBitmap *in, const RectI &srcRect, const Point2I &dstPoint, const U32 srcMipLevel = 0, const U32 dstMipLevel = 0);
166
167   GFXFormat   getFormat() const { return mInternalFormat; }
168   bool        setFormat(GFXFormat fmt);
169
170   U32         getWidth(const U32 in_mipLevel  = 0) const;
171   U32         getHeight(const U32 in_mipLevel = 0) const;
172   U32         getDepth(const U32 in_mipLevel = 0) const;
173
174   U8*         getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel = 0);
175   const U8*   getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel = 0) const;
176
177   const U8*   getBits(const U32 in_mipLevel = 0) const;
178   U8*         getWritableBits(const U32 in_mipLevel = 0);
179
180   U32         getByteSize() const { return mByteSize; }
181   U32         getBytesPerPixel() const { return mBytesPerPixel; }
182
183   /// Use these functions to set and get the mHasTransparency value
184   /// This is used to indicate that this bitmap has pixels that have
185   /// an alpha value less than 255 (used by the auto-Material mapper)
186   bool        getHasTransparency() const { return mHasTransparency; }
187   void        setHasTransparency(bool hasTransparency) { mHasTransparency = hasTransparency; }
188   
189   /// In general you will want to use this function if there is not a
190   /// good spot in the bitmap loader(s) to check the alpha value of
191   /// the pixels. This function uses the texture format to loop over
192   /// the bitmap bits and to check for alpha values less than 255
193   bool        checkForTransparency();
194
195   ColorF      sampleTexel(F32 u, F32 v) const;
196   bool        getColor(const U32 x, const U32 y, ColorI& rColor) const;
197   bool        setColor(const U32 x, const U32 y, const ColorI& rColor);
198
199   /// This method will combine bitmapA and bitmapB using the operation specified
200   /// by combineOp. The result will be stored in the bitmap that this method is
201   /// called on. The size of the resulting bitmap will be the larger of A and B.
202   /// The format of the resulting bitmap will be the format of A or B, whichever
203   /// has a larger byte size.
204   ///
205   /// @note There are some restrictions on ops and formats that will probably change
206   /// based on how we use this function.
207   bool combine( const GBitmap *bitmapA, const GBitmap *bitmapB, const GFXTextureOp combineOp );
208
209   /// Fills the first mip level of the bitmap with the specified color.
210   void fill( const ColorI &rColor );
211
212   /// An optimized version of fill().
213   void fillWhite();
214
215   //-------------------------------------- Internal data/operators
216
217   void deleteImage();
218
219   //-------------------------------------- Input/Output interface
220
221   /// Read a bitmap from a stream
222   /// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
223   /// @param ioStream The stream to read from
224   bool  readBitmap( const String &bmType, Stream &ioStream );
225
226   /// Write a bitmap to a stream
227   /// @param bmType This is a file extension to describe the type of the data [i.e. "png" for PNG file, etc]
228   /// @param ioStream The stream to read from
229   /// @param compressionLevel Image format-specific compression level.  If set to U32_MAX, we use the default compression defined when the format was registered.
230   bool  writeBitmap( const String &bmType, Stream &ioStream, U32 compressionLevel = U32_MAX );
231
232   bool readMNG(Stream& io_rStream);               // located in bitmapMng.cc
233   bool writeMNG(Stream& io_rStream) const;
234
235   bool read(Stream& io_rStream);
236   bool write(Stream& io_rStream) const;
237
238   template<class T, dsize_t mapLength>
239   void swizzle(const Swizzle<T,mapLength> *s);
240
241   static Vector<Registration>   sRegistrations;
242
243private:
244   GFXFormat mInternalFormat;
245
246   U8* mBits; // Master bytes
247   U32 mByteSize;
248   U32 mWidth;
249   U32 mHeight;
250   U32 mBytesPerPixel;
251
252   U32 mNumMipLevels;
253   U32 mMipLevelOffsets[c_maxMipLevels];
254
255   bool mHasTransparency;
256
257   static const U32 csFileVersion;
258};
259
260//------------------------------------------------------------------------------
261//-------------------------------------- Inlines
262//
263
264inline U32 GBitmap::getWidth(const U32 in_mipLevel) const
265{
266   AssertFatal(in_mipLevel < mNumMipLevels,
267               avar("GBitmap::getWidth: mip level out of range: (%d, %d)",
268                    in_mipLevel, mNumMipLevels));
269
270   U32 retVal = mWidth >> in_mipLevel;
271
272   return (retVal != 0) ? retVal : 1;
273}
274
275inline U32 GBitmap::getHeight(const U32 in_mipLevel) const
276{
277   AssertFatal(in_mipLevel < mNumMipLevels,
278               avar("Bitmap::getHeight: mip level out of range: (%d, %d)",
279                    in_mipLevel, mNumMipLevels));
280
281   U32 retVal = mHeight >> in_mipLevel;
282
283   return (retVal != 0) ? retVal : 1;
284}
285
286inline const U8* GBitmap::getBits(const U32 in_mipLevel) const
287{
288   AssertFatal(in_mipLevel < mNumMipLevels,
289               avar("GBitmap::getBits: mip level out of range: (%d, %d)",
290                    in_mipLevel, mNumMipLevels));
291
292   return &mBits[mMipLevelOffsets[in_mipLevel]];
293}
294
295inline U8* GBitmap::getWritableBits(const U32 in_mipLevel)
296{
297   AssertFatal(in_mipLevel < mNumMipLevels,
298               avar("GBitmap::getWritableBits: mip level out of range: (%d, %d)",
299                    in_mipLevel, mNumMipLevels));
300
301   return &mBits[mMipLevelOffsets[in_mipLevel]];
302}
303
304inline U8* GBitmap::getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel)
305{
306   return (getWritableBits(mipLevel) + ((in_y * getWidth(mipLevel)) + in_x) * mBytesPerPixel);
307}
308
309inline const U8* GBitmap::getAddress(const S32 in_x, const S32 in_y, const U32 mipLevel) const
310{
311   return (getBits(mipLevel) + ((in_y * getWidth(mipLevel)) + in_x) * mBytesPerPixel);
312}
313
314template<class T, dsize_t mapLength>
315void GBitmap::swizzle(const Swizzle<T,mapLength> *s )
316{
317   const U32 memSize = getWidth() * getHeight() * mBytesPerPixel;
318
319   void *b = dMalloc(memSize);
320
321   s->ToBuffer(b, getWritableBits(), memSize);
322
323   dMemcpy(getWritableBits(), b, memSize);
324
325   dFree(b);
326}
327
328#endif //_GBITMAP_H_
329