gBitmap.h
Engine/source/gfx/bitmap/gBitmap.h
Classes:
class
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 ® ); 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