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//-------------------------------------- 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 ® ); 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
