gBitmap.cc 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "io/stream.h"
  23. #include "io/fileStream.h"
  24. #include "graphics/gBitmap.h"
  25. #include "graphics/gPalette.h"
  26. #include "io/resource/resourceManager.h"
  27. #include "platform/platform.h"
  28. #include "memory/safeDelete.h"
  29. #include "math/mRect.h"
  30. #include "console/console.h"
  31. #ifndef _TORQUECONFIG_H_
  32. #include "torqueConfig.h"//for PNG loading setting
  33. #endif
  34. const U32 GBitmap::csFileVersion = 3;
  35. U32 GBitmap::sBitmapIdSource = 0;
  36. GBitmap::GBitmap()
  37. : internalFormat(RGB),
  38. pBits(NULL),
  39. byteSize(0),
  40. width(0),
  41. height(0),
  42. numMipLevels(0),
  43. bytesPerPixel(0),
  44. pPalette(NULL),
  45. mForce16Bit(false)
  46. {
  47. for (U32 i = 0; i < c_maxMipLevels; i++)
  48. mipLevelOffsets[i] = 0xffffffff;
  49. }
  50. GBitmap::GBitmap(const GBitmap& rCopy)
  51. {
  52. if (rCopy.pPalette)
  53. {
  54. pPalette = new GPalette;
  55. pPalette->setPaletteType(rCopy.pPalette->getPaletteType());
  56. dMemcpy(rCopy.pPalette->getColors(), pPalette->getColors(), sizeof(ColorI)*256);
  57. }
  58. else
  59. pPalette = NULL;
  60. internalFormat = rCopy.internalFormat;
  61. mForce16Bit = rCopy.mForce16Bit;
  62. byteSize = rCopy.byteSize;
  63. pBits = new U8[byteSize];
  64. dMemcpy(pBits, rCopy.pBits, byteSize);
  65. width = rCopy.width;
  66. height = rCopy.height;
  67. bytesPerPixel = rCopy.bytesPerPixel;
  68. numMipLevels = rCopy.numMipLevels;
  69. dMemcpy(mipLevelOffsets, rCopy.mipLevelOffsets, sizeof(mipLevelOffsets));
  70. }
  71. GBitmap::GBitmap(const U32 in_width,
  72. const U32 in_height,
  73. const bool in_extrudeMipLevels,
  74. const BitmapFormat in_format)
  75. : pBits(NULL),
  76. byteSize(0),
  77. pPalette(NULL),
  78. mForce16Bit(false)
  79. {
  80. for (U32 i = 0; i < c_maxMipLevels; i++)
  81. mipLevelOffsets[i] = 0xffffffff;
  82. allocateBitmap(in_width, in_height, in_extrudeMipLevels, in_format);
  83. }
  84. //--------------------------------------------------------------------------
  85. GBitmap::~GBitmap()
  86. {
  87. deleteImage();
  88. }
  89. //--------------------------------------------------------------------------
  90. void GBitmap::deleteImage()
  91. {
  92. delete [] pBits;
  93. pBits = NULL;
  94. byteSize = 0;
  95. width = 0;
  96. height = 0;
  97. numMipLevels = 0;
  98. SAFE_DELETE(pPalette);
  99. }
  100. void GBitmap::clearImage(const ColorF blendColor)
  101. {
  102. ColorI clearColor(blendColor.red, blendColor.green, blendColor.blue, 0);
  103. for (U32 h = 0; h < getHeight(); h++)
  104. {
  105. for (U32 w = 0; w < getWidth(); w++)
  106. {
  107. setColor(w, h, clearColor);
  108. }
  109. }
  110. }
  111. bool GBitmap::mergeLayer(const Point2I pos, const GBitmap* layer, const ColorF blendColor)
  112. {
  113. if (layer != nullptr && (getFormat() == BitmapFormat::RGBA || getFormat() == BitmapFormat::RGB) && (layer->getFormat() == BitmapFormat::RGBA || layer->getFormat() == BitmapFormat::RGB))
  114. {
  115. for (U32 h = getMax(0, pos.y); h < getHeight() && (h - pos.y) < layer->getHeight(); h++)
  116. {
  117. for (U32 w = getMax(0, pos.x); w < getWidth() && (w - pos.x) < layer->getWidth(); w++)
  118. {
  119. const U8* layerByte = layer->getAddress(w - pos.x, h - pos.y);
  120. U8* baseByte = getAddress(w, h);
  121. float layerAlpha = blendColor.alpha;
  122. if (layer->getFormat() == BitmapFormat::RGBA)
  123. {
  124. layerAlpha = (layerByte[3] / 255.0f) * blendColor.alpha;
  125. }
  126. if (layerAlpha <= 0.005f)
  127. {
  128. continue;
  129. }
  130. float baseAlpha = 1.0f;
  131. if (getFormat() == BitmapFormat::RGBA)
  132. {
  133. baseAlpha = (baseByte[3] / 255.0f);
  134. }
  135. float alpha = layerAlpha + baseAlpha * (1 - layerAlpha);
  136. float red = ((float)layerByte[0]/255.0f * layerAlpha * blendColor.red) + ((float)baseByte[0]/255.0f * baseAlpha * (1 - layerAlpha)) / alpha;
  137. float green = ((float)layerByte[1]/255.0f * layerAlpha * blendColor.green) + ((float)baseByte[1]/255.0f * baseAlpha * (1 - layerAlpha)) / alpha;
  138. float blue = ((float)layerByte[2]/255.0f * layerAlpha * blendColor.blue) + ((float)baseByte[2]/255.0f * baseAlpha * (1 - layerAlpha)) / alpha;
  139. baseByte[0] = (U8)mClamp(red * 255.0f, 0.0f, 255.0f);
  140. baseByte[1] = (U8)mClamp(green * 255.0f, 0.0f, 255.0f);
  141. baseByte[2] = (U8)mClamp(blue * 255.0f, 0.0f, 255.0f);
  142. if (getFormat() == BitmapFormat::RGBA)
  143. {
  144. baseByte[3] = (U8)mClamp(alpha * 255.0f, 0.0f, 255.0f);
  145. }
  146. }
  147. }
  148. return true;
  149. }
  150. return false;
  151. }
  152. //--------------------------------------------------------------------------
  153. void GBitmap::setPalette(GPalette* in_pPalette)
  154. {
  155. SAFE_DELETE(pPalette);
  156. pPalette = in_pPalette;
  157. }
  158. void GBitmap::copyRect(const GBitmap *src, const RectI &srcRect, const Point2I &dstPt)
  159. {
  160. if(src->getFormat() != getFormat())
  161. return;
  162. if(srcRect.extent.x + srcRect.point.x > (S32)src->getWidth() || srcRect.extent.y + srcRect.point.y > (S32)src->getHeight())
  163. return;
  164. if(srcRect.extent.x + dstPt.x > (S32)getWidth() || srcRect.extent.y + dstPt.y > (S32)getHeight())
  165. return;
  166. for(U32 i = 0; i < (U32)srcRect.extent.y; i++)
  167. {
  168. dMemcpy(getAddress(dstPt.x, dstPt.y + i),
  169. src->getAddress(srcRect.point.x, srcRect.point.y + i),
  170. bytesPerPixel * srcRect.extent.x);
  171. }
  172. }
  173. //--------------------------------------------------------------------------
  174. void GBitmap::allocateBitmap(const U32 in_width, const U32 in_height, const bool in_extrudeMipLevels, const BitmapFormat in_format)
  175. {
  176. //-------------------------------------- Some debug checks...
  177. U32 svByteSize = byteSize;
  178. U8 *svBits = pBits;
  179. AssertFatal(in_width != 0 && in_height != 0, "GBitmap::allocateBitmap: width or height is 0");
  180. if (in_extrudeMipLevels == true) {
  181. //AssertFatal(in_width <= 256 && in_height <= 256, "GBitmap::allocateBitmap: width or height is too large");
  182. AssertFatal(isPow2(in_width) == true && isPow2(in_height) == true, "GBitmap::GBitmap: in order to extrude miplevels, bitmap w/h must be pow2");
  183. }
  184. internalFormat = in_format;
  185. width = in_width;
  186. height = in_height;
  187. bytesPerPixel = 1;
  188. switch (internalFormat) {
  189. case Alpha:
  190. case Palettized:
  191. case Luminance:
  192. case Intensity: bytesPerPixel = 1;
  193. break;
  194. case RGB: bytesPerPixel = 3;
  195. break;
  196. case RGBA: bytesPerPixel = 4;
  197. break;
  198. case LuminanceAlpha:
  199. case RGB565:
  200. case RGB5551: bytesPerPixel = 2;
  201. break;
  202. #ifdef TORQUE_OS_IOS
  203. case PVR2:
  204. case PVR2A:
  205. case PVR4:
  206. case PVR4A:
  207. // compressed textures can't be allocated!
  208. return;
  209. #endif //-Mat
  210. default:
  211. AssertFatal(false, "GBitmap::GBitmap: misunderstood format specifier");
  212. break;
  213. }
  214. // Set up the mip levels, if necessary...
  215. numMipLevels = 1;
  216. U32 allocPixels = in_width * in_height * bytesPerPixel;
  217. mipLevelOffsets[0] = 0;
  218. if (in_extrudeMipLevels == true)
  219. {
  220. U32 currWidth = in_width;
  221. U32 currHeight = in_height;
  222. do
  223. {
  224. mipLevelOffsets[numMipLevels] = mipLevelOffsets[numMipLevels - 1] +
  225. (currWidth * currHeight * bytesPerPixel);
  226. currWidth >>= 1;
  227. currHeight >>= 1;
  228. if (currWidth == 0) currWidth = 1;
  229. if (currHeight == 0) currHeight = 1;
  230. numMipLevels++;
  231. allocPixels += currWidth * currHeight * bytesPerPixel;
  232. } while (currWidth != 1 || currHeight != 1);
  233. }
  234. AssertFatal(numMipLevels <= c_maxMipLevels, "GBitmap::allocateBitmap: too many miplevels");
  235. // Set up the memory...
  236. byteSize = allocPixels;
  237. pBits = new U8[byteSize];
  238. dMemset(pBits, 0xFF, byteSize);
  239. if(svBits != NULL)
  240. {
  241. dMemcpy(pBits, svBits, getMin(byteSize, svByteSize));
  242. delete[] svBits;
  243. }
  244. }
  245. //--------------------------------------------------------------------------
  246. void bitmapExtrude5551_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
  247. {
  248. const U16 *src = (const U16 *) srcMip;
  249. U16 *dst = (U16 *) mip;
  250. U32 stride = srcHeight != 1 ? srcWidth : 0;
  251. U32 width = srcWidth >> 1;
  252. U32 height = srcHeight >> 1;
  253. if (width == 0) width = 1;
  254. if (height == 0) height = 1;
  255. if (srcWidth != 1)
  256. {
  257. for(U32 y = 0; y < height; y++)
  258. {
  259. for(U32 x = 0; x < width; x++)
  260. {
  261. U32 a = src[0];
  262. U32 b = src[1];
  263. U32 c = src[stride];
  264. U32 d = src[stride+1];
  265. #if defined(TORQUE_BIG_ENDIAN)
  266. dst[x] = ((( (a >> 10) + (b >> 10) + (c >> 10) + (d >> 10)) >> 2) << 10) |
  267. ((( ((a >> 5) & 0x1F) + ((b >> 5) & 0x1F) + ((c >> 5) & 0x1F) + ((d >> 5) & 0x1F)) >> 2) << 5) |
  268. ((( ((a >> 0) & 0x1F) + ((b >> 0) & 0x1F) + ((c >> 0) & 0x1F) + ((d >> 0) & 0x1F)) >> 2) << 0);
  269. #else
  270. dst[x] = ((( (a >> 11) + (b >> 11) + (c >> 11) + (d >> 11)) >> 2) << 11) |
  271. ((( ((a >> 6) & 0x1F) + ((b >> 6) & 0x1F) + ((c >> 6) & 0x1F) + ((d >> 6) & 0x1F)) >> 2) << 6) |
  272. ((( ((a >> 1) & 0x1F) + ((b >> 1) & 0x1F) + ((c >> 1) & 0x1F) + ((d >> 1) & 0x1F)) >> 2) << 1);
  273. #endif
  274. src += 2;
  275. }
  276. src += stride;
  277. dst += width;
  278. }
  279. }
  280. else
  281. {
  282. for(U32 y = 0; y < height; y++)
  283. {
  284. U32 a = src[0];
  285. U32 c = src[stride];
  286. #if defined(TORQUE_BIG_ENDIAN)
  287. dst[y] = ((( (a >> 10) + (c >> 10)) >> 1) << 10) |
  288. ((( ((a >> 5) & 0x1F) + ((c >> 5) & 0x1f)) >> 1) << 5) |
  289. ((( ((a >> 0) & 0x1F) + ((c >> 0) & 0x1f)) >> 1) << 0);
  290. #else
  291. dst[y] = ((( (a >> 11) + (c >> 11)) >> 1) << 11) |
  292. ((( ((a >> 6) & 0x1f) + ((c >> 6) & 0x1f)) >> 1) << 6) |
  293. ((( ((a >> 1) & 0x1F) + ((c >> 1) & 0x1f)) >> 1) << 1);
  294. #endif
  295. src += 1 + stride;
  296. }
  297. }
  298. }
  299. //--------------------------------------------------------------------------
  300. void bitmapExtrudeRGB_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
  301. {
  302. const U8 *src = (const U8 *) srcMip;
  303. U8 *dst = (U8 *) mip;
  304. U32 stride = srcHeight != 1 ? (srcWidth) * 3 : 0;
  305. U32 width = srcWidth >> 1;
  306. U32 height = srcHeight >> 1;
  307. if (width == 0) width = 1;
  308. if (height == 0) height = 1;
  309. if (srcWidth != 1)
  310. {
  311. for(U32 y = 0; y < height; y++)
  312. {
  313. for(U32 x = 0; x < width; x++)
  314. {
  315. *dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3]) + 2) >> 2;
  316. src++;
  317. *dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3]) + 2) >> 2;
  318. src++;
  319. *dst++ = (U32(*src) + U32(src[3]) + U32(src[stride]) + U32(src[stride+3]) + 2) >> 2;
  320. src += 4;
  321. }
  322. src += stride; // skip
  323. }
  324. }
  325. else
  326. {
  327. for(U32 y = 0; y < height; y++)
  328. {
  329. *dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
  330. src++;
  331. *dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
  332. src++;
  333. *dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
  334. src += 4;
  335. src += stride; // skip
  336. }
  337. }
  338. }
  339. //--------------------------------------------------------------------------
  340. void bitmapExtrudePaletted_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
  341. {
  342. U32 width = srcWidth >> 1;
  343. U32 height = srcHeight >> 1;
  344. if (width == 0) width = 1;
  345. if (height == 0) height = 1;
  346. dMemset(mip, 0, width * height);
  347. }
  348. //--------------------------------------------------------------------------
  349. void bitmapExtrudeRGBA_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
  350. {
  351. const U8 *src = (const U8 *) srcMip;
  352. U8 *dst = (U8 *) mip;
  353. U32 stride = srcHeight != 1 ? (srcWidth) * 4 : 0;
  354. U32 width = srcWidth >> 1;
  355. U32 height = srcHeight >> 1;
  356. if (width == 0) width = 1;
  357. if (height == 0) height = 1;
  358. if (srcWidth != 1)
  359. {
  360. for(U32 y = 0; y < height; y++)
  361. {
  362. for(U32 x = 0; x < width; x++)
  363. {
  364. *dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4]) + 2) >> 2;
  365. src++;
  366. *dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4]) + 2) >> 2;
  367. src++;
  368. *dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4]) + 2) >> 2;
  369. src++;
  370. *dst++ = (U32(*src) + U32(src[4]) + U32(src[stride]) + U32(src[stride+4]) + 2) >> 2;
  371. src += 5;
  372. }
  373. src += stride; // skip
  374. }
  375. }
  376. else
  377. {
  378. for(U32 y = 0; y < height; y++)
  379. {
  380. *dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
  381. src++;
  382. *dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
  383. src++;
  384. *dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
  385. src++;
  386. *dst++ = (U32(*src) + U32(src[stride]) + 1) >> 1;
  387. src += 5;
  388. src += stride; // skip
  389. }
  390. }
  391. }
  392. void (*bitmapExtrude5551)(const void *srcMip, void *mip, U32 height, U32 width) = bitmapExtrude5551_c;
  393. void (*bitmapExtrudeRGB)(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth) = bitmapExtrudeRGB_c;
  394. void (*bitmapExtrudeRGBA)(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth) = bitmapExtrudeRGBA_c;
  395. void (*bitmapExtrudePaletted)(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth) = bitmapExtrudePaletted_c;
  396. //--------------------------------------------------------------------------
  397. void GBitmap::extrudeMipLevels(bool clearBorders)
  398. {
  399. if(numMipLevels == 1)
  400. allocateBitmap(getWidth(), getHeight(), true, getFormat());
  401. switch (getFormat())
  402. {
  403. case RGB5551:
  404. {
  405. for(U32 i = 1; i < numMipLevels; i++)
  406. bitmapExtrude5551(getBits(i - 1), getWritableBits(i), getHeight(i), getWidth(i));
  407. break;
  408. }
  409. case RGB:
  410. {
  411. for(U32 i = 1; i < numMipLevels; i++)
  412. bitmapExtrudeRGB(getBits(i - 1), getWritableBits(i), getHeight(i-1), getWidth(i-1));
  413. break;
  414. }
  415. case RGBA:
  416. {
  417. for(U32 i = 1; i < numMipLevels; i++)
  418. bitmapExtrudeRGBA(getBits(i - 1), getWritableBits(i), getHeight(i-1), getWidth(i-1));
  419. break;
  420. }
  421. case Palettized:
  422. {
  423. for(U32 i = 1; i < numMipLevels; i++)
  424. bitmapExtrudePaletted(getBits(i - 1), getWritableBits(i), getHeight(i-1), getWidth(i-1));
  425. break;
  426. }
  427. case Intensity:
  428. case Luminance:
  429. case LuminanceAlpha:
  430. case Alpha:
  431. case RGB565:
  432. #ifdef TORQUE_OS_IOS
  433. case PVR2:
  434. case PVR2A:
  435. case PVR4:
  436. case PVR4A:
  437. #endif
  438. break;
  439. }
  440. if (clearBorders)
  441. {
  442. for (U32 i = 1; i<numMipLevels; i++)
  443. {
  444. U32 width = getWidth(i);
  445. U32 height = getHeight(i);
  446. if (height<3 || width<3)
  447. // bmp is all borders at this mip level
  448. dMemset(getWritableBits(i),0,width*height*bytesPerPixel);
  449. else
  450. {
  451. width *= bytesPerPixel;
  452. U8 * bytes = getWritableBits(i);
  453. U8 * end = bytes + (height-1)*width - bytesPerPixel; // end = last row, 2nd column
  454. // clear first row sans the last pixel
  455. dMemset(bytes,0,width-bytesPerPixel);
  456. bytes -= bytesPerPixel;
  457. while (bytes<end)
  458. {
  459. // clear last pixel of row N-1 and first pixel of row N
  460. bytes += width;
  461. dMemset(bytes,0,bytesPerPixel*2);
  462. }
  463. // clear last row sans the first pixel
  464. dMemset(bytes+2*bytesPerPixel,0,width-bytesPerPixel);
  465. }
  466. }
  467. }
  468. }
  469. //--------------------------------------------------------------------------
  470. void GBitmap::extrudeMipLevelsDetail()
  471. {
  472. AssertFatal(getFormat() == GBitmap::RGB, "Error, only handles RGB for now...");
  473. U32 i,j;
  474. if(numMipLevels == 1)
  475. allocateBitmap(getWidth(), getHeight(), true, getFormat());
  476. for (i = 1; i < numMipLevels; i++) {
  477. bitmapExtrudeRGB(getBits(i - 1), getWritableBits(i), getHeight(i-1), getWidth(i-1));
  478. }
  479. // Ok, now that we have the levels extruded, we need to move the lower miplevels
  480. // closer to 0.5.
  481. for (i = 1; i < numMipLevels - 1; i++) {
  482. U8* pMipBits = (U8*)getWritableBits(i);
  483. U32 numBytes = getWidth(i) * getHeight(i) * 3;
  484. U32 shift = i;
  485. U32 start = ((1 << i) - 1) * 0x80;
  486. for (j = 0; j < numBytes; j++) {
  487. U32 newVal = (start + pMipBits[j]) >> shift;
  488. AssertFatal(newVal <= 255, "Error, oob");
  489. pMipBits[j] = U8(newVal);
  490. }
  491. }
  492. AssertFatal(getWidth(numMipLevels - 1) == 1 && getHeight(numMipLevels - 1) == 1,
  493. "Error, last miplevel should be 1x1!");
  494. ((U8*)getWritableBits(numMipLevels - 1))[0] = 0x80;
  495. ((U8*)getWritableBits(numMipLevels - 1))[1] = 0x80;
  496. ((U8*)getWritableBits(numMipLevels - 1))[2] = 0x80;
  497. }
  498. //--------------------------------------------------------------------------
  499. void bitmapConvertRGB_to_5551_c(U8 *src, U32 pixels)
  500. {
  501. U16 *dst = (U16 *)src;
  502. for(U32 j = 0; j < pixels; j++)
  503. {
  504. U32 r = src[0] >> 3;
  505. U32 g = src[1] >> 3;
  506. U32 b = src[2] >> 3;
  507. #if defined(TORQUE_BIG_ENDIAN)
  508. *dst++ = (1 << 15) | (b << 10) | (g << 5) | (r << 0);
  509. #else
  510. *dst++ = (b << 1) | (g << 6) | (r << 11) | 1;
  511. #endif
  512. src += 3;
  513. }
  514. }
  515. void (*bitmapConvertRGB_to_5551)(U8 *src, U32 pixels) = bitmapConvertRGB_to_5551_c;
  516. //--------------------------------------------------------------------------
  517. bool GBitmap::setFormat(BitmapFormat fmt)
  518. {
  519. if (getFormat() == fmt)
  520. return true;
  521. // this is a nasty pointer math hack
  522. // is there a quick way to calc pixels of a fully mipped bitmap?
  523. U32 pixels = 0;
  524. for (U32 i=0; i < numMipLevels; i++)
  525. pixels += getHeight(i) * getWidth(i);
  526. switch (getFormat())
  527. {
  528. case RGB:
  529. if ( fmt == RGB5551 )
  530. {
  531. bitmapConvertRGB_to_5551(pBits, pixels);
  532. internalFormat = RGB5551;
  533. bytesPerPixel = 2;
  534. }
  535. break;
  536. default:
  537. AssertWarn(0, "GBitmap::setFormat: unable to convert bitmap to requested format.");
  538. return false;
  539. }
  540. U32 offset = 0;
  541. for (U32 j=0; j < numMipLevels; j++)
  542. {
  543. mipLevelOffsets[j] = offset;
  544. offset += getHeight(j) * getWidth(j) * bytesPerPixel;
  545. }
  546. return true;
  547. }
  548. //--------------------------------------------------------------------------
  549. bool GBitmap::getColorBGRA(const U32 x, const U32 y, ColorI& rColor) const
  550. {
  551. if(!getColor(x, y, rColor))
  552. return false;
  553. //jk - swap red and blue...
  554. U8 r = rColor.red;
  555. rColor.red = rColor.blue;
  556. rColor.blue = r;
  557. return true;
  558. }
  559. bool GBitmap::setColorBGRA(const U32 x, const U32 y, ColorI& rColor)
  560. {
  561. //jk - copy then swap red and blue...
  562. //jk - using a copy so the color object provided by the caller isn't swapped...
  563. ColorI temp = rColor;
  564. U8 r = temp.red;
  565. temp.red = temp.blue;
  566. temp.blue = r;
  567. return setColor(x, y, temp);
  568. }
  569. bool GBitmap::getColor(const U32 x, const U32 y, ColorI& rColor) const
  570. {
  571. if (x >= width || y >= height)
  572. return false;
  573. if (internalFormat == Palettized && pPalette == NULL)
  574. return false;
  575. const U8* pLoc = getAddress(x, y);
  576. switch (internalFormat) {
  577. case Palettized:
  578. rColor = pPalette->getColor(*pLoc);
  579. break;
  580. case Alpha:
  581. case Intensity:
  582. case Luminance:
  583. rColor.set( *pLoc, *pLoc, *pLoc, *pLoc );
  584. break;
  585. case RGB:
  586. rColor.set( pLoc[0], pLoc[1], pLoc[2], 255 );
  587. break;
  588. case RGBA:
  589. rColor.set( pLoc[0], pLoc[1], pLoc[2], pLoc[3] );
  590. break;
  591. case LuminanceAlpha:
  592. rColor.set( pLoc[0], pLoc[0], pLoc[0], pLoc[1] );
  593. break;
  594. case RGB5551:
  595. #if defined(TORQUE_BIG_ENDIAN)
  596. rColor.red = (*((U16*)pLoc) >> 0) & 0x1F;
  597. rColor.green = (*((U16*)pLoc) >> 5) & 0x1F;
  598. rColor.blue = (*((U16*)pLoc) >> 10) & 0x1F;
  599. rColor.alpha = ((*((U16*)pLoc) >> 15) & 0x01) ? 255 : 0;
  600. #else
  601. rColor.red = *((U16*)pLoc) >> 11;
  602. rColor.green = (*((U16*)pLoc) >> 6) & 0x1f;
  603. rColor.blue = (*((U16*)pLoc) >> 1) & 0x1f;
  604. rColor.alpha = (*((U16*)pLoc) & 1) ? 255 : 0;
  605. #endif
  606. break;
  607. default:
  608. AssertFatal(false, "Bad internal format");
  609. return false;
  610. }
  611. return true;
  612. }
  613. //--------------------------------------------------------------------------
  614. bool GBitmap::setColor(const U32 x, const U32 y, ColorI& rColor)
  615. {
  616. if (x >= width || y >= height)
  617. return false;
  618. if (internalFormat == Palettized && pPalette == NULL)
  619. return false;
  620. U8* pLoc = getAddress(x, y);
  621. switch (internalFormat) {
  622. case Palettized:
  623. rColor = pPalette->getColor(*pLoc);
  624. break;
  625. case Alpha:
  626. case Intensity:
  627. case Luminance:
  628. *pLoc = rColor.alpha;
  629. break;
  630. case LuminanceAlpha:
  631. *pLoc = rColor.red;
  632. *(pLoc+1) = rColor.alpha;
  633. break;
  634. case RGB:
  635. dMemcpy( pLoc, &rColor, 3 * sizeof( U8 ) );
  636. break;
  637. case RGBA:
  638. dMemcpy( pLoc, &rColor, 4 * sizeof( U8 ) );
  639. break;
  640. case RGB5551:
  641. #if defined(TORQUE_BIG_ENDIAN)
  642. *((U16*)pLoc) = (((rColor.alpha>0) ? 1 : 0)<<15) | (rColor.blue << 10) | (rColor.green << 5) | (rColor.red << 0);
  643. #else
  644. *((U16*)pLoc) = (rColor.blue << 1) | (rColor.green << 6) | (rColor.red << 11) | ((rColor.alpha>0) ? 1 : 0);
  645. #endif
  646. break;
  647. default:
  648. AssertFatal(false, "Bad internal format");
  649. return false;
  650. }
  651. return true;
  652. }
  653. //-----------------------------------------------------------------------------
  654. GBitmap* GBitmap::createPowerOfTwoBitmap()
  655. {
  656. if (isPow2(getWidth()) && isPow2(getHeight()))
  657. return NULL;
  658. AssertFatal(getNumMipLevels() == 1,
  659. "Cannot have non-pow2 bitmap with miplevels");
  660. U32 width = getWidth();
  661. U32 height = getHeight();
  662. U32 newWidth = getNextPow2(getWidth());
  663. U32 newHeight = getNextPow2(getHeight());
  664. GBitmap* pReturn = new GBitmap(newWidth, newHeight, false, getFormat());
  665. for (U32 i = 0; i < height; i++)
  666. {
  667. U8* pDest = (U8*)pReturn->getAddress(0, i);
  668. const U8* pSrc = (const U8*)getAddress(0, i);
  669. dMemcpy(pDest, pSrc, width * bytesPerPixel);
  670. pDest += width * bytesPerPixel;
  671. // set the src pixel to the last pixel in the row
  672. const U8 *pSrcPixel = pDest - bytesPerPixel;
  673. for(U32 j = width; j < newWidth; j++)
  674. for(U32 k = 0; k < bytesPerPixel; k++)
  675. *pDest++ = pSrcPixel[k];
  676. }
  677. for(U32 i = height; i < newHeight; i++)
  678. {
  679. U8* pDest = (U8*)pReturn->getAddress(0, i);
  680. U8* pSrc = (U8*)pReturn->getAddress(0, height-1);
  681. dMemcpy(pDest, pSrc, newWidth * bytesPerPixel);
  682. }
  683. return pReturn;
  684. }
  685. //------------------------------------------------------------------------------
  686. //-------------------------------------- Persistent I/O
  687. //
  688. #ifdef TORQUE_OS_IOS
  689. #define EXT_ARRAY_SIZE 4
  690. static const char* extArray[EXT_ARRAY_SIZE] = { "", ".pvr", ".jpg", ".png"};
  691. #else
  692. #define EXT_ARRAY_SIZE 3
  693. static const char* extArray[EXT_ARRAY_SIZE] = { "", ".jpg", ".png"};
  694. #endif
  695. ResourceObject * GBitmap::findBmpResource(const char * path)
  696. {
  697. char fileNameBuffer[512];
  698. dStrcpy( fileNameBuffer, path );
  699. // Try some different possible filenames.
  700. U32 len = dStrlen( fileNameBuffer );
  701. for( U32 i = 0; i < EXT_ARRAY_SIZE; i++ )
  702. {
  703. dStrcpy( fileNameBuffer + len, extArray[i] );
  704. ResourceObject * ret = ResourceManager->find( fileNameBuffer );
  705. if (ret)
  706. return ret;
  707. }
  708. return NULL;
  709. }
  710. GBitmap *GBitmap::load(const char *path)
  711. {
  712. ResourceObject * ro = findBmpResource(path);
  713. if (ro)
  714. {
  715. GBitmap *bmp = (GBitmap*)ResourceManager->loadInstance(ro);
  716. return bmp;
  717. }
  718. // If unable to load texture in current directory
  719. // look in the parent directory. But never look in the root.
  720. char fileNameBuffer[512];
  721. dStrcpy( fileNameBuffer, path );
  722. char *name = dStrrchr( fileNameBuffer, '/' );
  723. if( name )
  724. {
  725. *name++ = 0;
  726. char *parent = dStrrchr( fileNameBuffer, '/' );
  727. if( parent )
  728. {
  729. parent[1] = 0;
  730. dStrcat( fileNameBuffer, name );
  731. return load( fileNameBuffer );
  732. }
  733. }
  734. return NULL;
  735. }
  736. bool GBitmap::read(Stream& io_rStream)
  737. {
  738. // Handle versioning
  739. U32 version;
  740. io_rStream.read(&version);
  741. AssertFatal(version == csFileVersion, "Bitmap::read: incorrect file version");
  742. //-------------------------------------- Read the object
  743. U32 fmt;
  744. io_rStream.read(&fmt);
  745. internalFormat = BitmapFormat(fmt);
  746. bytesPerPixel = 1;
  747. switch (internalFormat) {
  748. case Alpha:
  749. case Palettized:
  750. case Luminance:
  751. case Intensity: bytesPerPixel = 1;
  752. break;
  753. case RGB: bytesPerPixel = 3;
  754. break;
  755. case RGBA: bytesPerPixel = 4;
  756. break;
  757. case RGB565:
  758. case RGB5551: bytesPerPixel = 2;
  759. break;
  760. default:
  761. AssertFatal(false, "GBitmap::GBitmap: misunderstood format specifier");
  762. break;
  763. }
  764. io_rStream.read(&byteSize);
  765. pBits = new U8[byteSize];
  766. io_rStream.read(byteSize, pBits);
  767. io_rStream.read(&width);
  768. io_rStream.read(&height);
  769. io_rStream.read(&numMipLevels);
  770. for (U32 i = 0; i < c_maxMipLevels; i++)
  771. io_rStream.read(&mipLevelOffsets[i]);
  772. if (internalFormat == Palettized) {
  773. pPalette = new GPalette;
  774. pPalette->read(io_rStream);
  775. }
  776. return (io_rStream.getStatus() == Stream::Ok);
  777. }
  778. bool GBitmap::write(Stream& io_rStream) const
  779. {
  780. // Handle versioning
  781. io_rStream.write(csFileVersion);
  782. //-------------------------------------- Write the object
  783. io_rStream.write(U32(internalFormat));
  784. io_rStream.write(byteSize);
  785. io_rStream.write(byteSize, pBits);
  786. io_rStream.write(width);
  787. io_rStream.write(height);
  788. io_rStream.write(numMipLevels);
  789. for (U32 i = 0; i < c_maxMipLevels; i++)
  790. io_rStream.write(mipLevelOffsets[i]);
  791. if (internalFormat == Palettized) {
  792. AssertFatal(pPalette != NULL,
  793. "GBitmap::write: cannot write a palettized bitmap wo/ a palette");
  794. pPalette->write(io_rStream);
  795. }
  796. return true;
  797. }
  798. //-------------------------------------- GFXBitmap
  799. ResourceInstance* constructBitmapJPEG(Stream &stream)
  800. {
  801. GBitmap* bmp = new GBitmap;
  802. if (bmp->readJPEG(stream))
  803. return bmp;
  804. else
  805. {
  806. delete bmp;
  807. return NULL;
  808. }
  809. }
  810. ResourceInstance* constructBitmapPNG(Stream &stream)
  811. {
  812. GBitmap* bmp = new GBitmap;
  813. //PUAP -Mat uless you compile with a custom build step 'IPHONE_OPTIMIZE_OPTIONS' set to '-skip-PNGs', you're PNGs will be altered(optimized)
  814. //So either deal with that youself or define this so that we load it using apple iPhone functions to get the PNG data to Torque
  815. #ifdef USE_APPLE_OPTIMIZED_PNGS
  816. if (bmp->readPNGiPhone(stream)){
  817. #else
  818. if (bmp->readPNG(stream)){
  819. #endif
  820. return bmp;
  821. }
  822. else
  823. {
  824. delete bmp;
  825. return NULL;
  826. }
  827. }
  828. ResourceInstance* constructBitmapBMP(Stream &stream)
  829. {
  830. GBitmap *bmp = new GBitmap;
  831. if(bmp->readMSBmp(stream))
  832. return bmp;
  833. else
  834. {
  835. delete bmp;
  836. return NULL;
  837. }
  838. }
  839. #ifdef TORQUE_OS_IOS
  840. ResourceInstance* constructBitmapPVR(Stream &stream)
  841. {
  842. GBitmap *bmp = new GBitmap;
  843. if(bmp->readPvr(stream))
  844. return bmp;
  845. else
  846. {
  847. delete bmp;
  848. return NULL;
  849. }
  850. }
  851. #endif