bitmapUtils.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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 "gfx/bitmap/bitmapUtils.h"
  23. #include "platform/platform.h"
  24. #ifndef STB_IMAGE_RESIZE2_IMPLEMENTATION
  25. #define STB_IMAGE_RESIZE2_IMPLEMENTATION
  26. #define STBIR_PROFILE
  27. #include "gfx/bitmap/loaders/stb/stb_image_resize2.h"
  28. #endif // !STB_IMAGE_RESIZE2_IMPLEMENTATION
  29. void bitmapExtrude5551_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
  30. {
  31. const U16 *src = (const U16 *) srcMip;
  32. U16 *dst = (U16 *) mip;
  33. U32 stride = srcHeight != 1 ? srcWidth : 0;
  34. U32 width = srcWidth >> 1;
  35. U32 height = srcHeight >> 1;
  36. if (width == 0) width = 1;
  37. if (height == 0) height = 1;
  38. if (srcWidth != 1)
  39. {
  40. for(U32 y = 0; y < height; y++)
  41. {
  42. for(U32 x = 0; x < width; x++)
  43. {
  44. U32 a = src[0];
  45. U32 b = src[1];
  46. U32 c = src[stride];
  47. U32 d = src[stride+1];
  48. #if defined(TORQUE_BIG_ENDIAN)
  49. dst[x] = ((( (a >> 10) + (b >> 10) + (c >> 10) + (d >> 10)) >> 2) << 10) |
  50. ((( ((a >> 5) & 0x1F) + ((b >> 5) & 0x1F) + ((c >> 5) & 0x1F) + ((d >> 5) & 0x1F)) >> 2) << 5) |
  51. ((( ((a >> 0) & 0x1F) + ((b >> 0) & 0x1F) + ((c >> 0) & 0x1F) + ((d >> 0) & 0x1F)) >> 2) << 0);
  52. #else
  53. dst[x] = ((( (a >> 11) + (b >> 11) + (c >> 11) + (d >> 11)) >> 2) << 11) |
  54. ((( ((a >> 6) & 0x1F) + ((b >> 6) & 0x1F) + ((c >> 6) & 0x1F) + ((d >> 6) & 0x1F)) >> 2) << 6) |
  55. ((( ((a >> 1) & 0x1F) + ((b >> 1) & 0x1F) + ((c >> 1) & 0x1F) + ((d >> 1) & 0x1F)) >> 2) << 1);
  56. #endif
  57. src += 2;
  58. }
  59. src += stride;
  60. dst += width;
  61. }
  62. }
  63. else
  64. {
  65. for(U32 y = 0; y < height; y++)
  66. {
  67. U32 a = src[0];
  68. U32 c = src[stride];
  69. #if defined(TORQUE_BIG_ENDIAN)
  70. dst[y] = ((( (a >> 10) + (c >> 10)) >> 1) << 10) |
  71. ((( ((a >> 5) & 0x1F) + ((c >> 5) & 0x1f)) >> 1) << 5) |
  72. ((( ((a >> 0) & 0x1F) + ((c >> 0) & 0x1f)) >> 1) << 0);
  73. #else
  74. dst[y] = ((( (a >> 11) + (c >> 11)) >> 1) << 11) |
  75. ((( ((a >> 6) & 0x1f) + ((c >> 6) & 0x1f)) >> 1) << 6) |
  76. ((( ((a >> 1) & 0x1F) + ((c >> 1) & 0x1f)) >> 1) << 1);
  77. #endif
  78. src += 1 + stride;
  79. }
  80. }
  81. }
  82. //--------------------------------------------------------------------------
  83. template <typename T>
  84. void bitmapExtrudeGeneric(
  85. const T* src, T* dst,
  86. U32 srcWidth, U32 srcHeight,
  87. U32 channels, U32 bpp)
  88. {
  89. U32 srcRowStride = srcHeight != 1 ? (srcWidth * bpp) / sizeof(T) : 0;
  90. U32 dstWidth = srcWidth > 1 ? srcWidth / 2 : 1;
  91. U32 dstHeight = srcHeight > 1 ? srcHeight / 2 : 1;
  92. U32 dstRowStride = dstHeight != 1 ? (dstWidth * bpp) / sizeof(T) : 0;
  93. for (U32 y = 0; y < dstHeight; ++y)
  94. {
  95. for (U32 x = 0; x < dstWidth; ++x)
  96. {
  97. for (U32 c = 0; c < channels; ++c)
  98. {
  99. U32 x0 = x * 2;
  100. U32 y0 = y * 2;
  101. U32 x1 = (x0 + 1 < srcWidth) ? x0 + 1 : x0;
  102. U32 y1 = (y0 + 1 < srcHeight) ? y0 + 1 : y0;
  103. if constexpr (std::is_floating_point_v<T>)
  104. {
  105. T sum = 0;
  106. sum += src[y0 * srcRowStride + x0 * channels + c];
  107. sum += src[y0 * srcRowStride + x1 * channels + c];
  108. sum += src[y1 * srcRowStride + x0 * channels + c];
  109. sum += src[y1 * srcRowStride + x1 * channels + c];
  110. dst[y * dstRowStride + x * channels + c] = sum * 0.25f;
  111. }
  112. else
  113. {
  114. U32 sum = 0;
  115. sum += src[y0 * srcRowStride + x0 * channels + c];
  116. sum += src[y0 * srcRowStride + x1 * channels + c];
  117. sum += src[y1 * srcRowStride + x0 * channels + c];
  118. sum += src[y1 * srcRowStride + x1 * channels + c];
  119. dst[y * dstRowStride + x * channels + c] = T((sum + 2) >> 2);
  120. }
  121. }
  122. }
  123. }
  124. }
  125. // 8-bit RGBA
  126. auto bitmapExtrudeU8_RGBA = [](const void* src, void* dst, U32 h, U32 w, U32 bpp) {
  127. bitmapExtrudeGeneric((const U8*)src, (U8*)dst, w, h, 4, bpp);
  128. };
  129. // 16-bit RGBA (U16 / F32 stored as U16)
  130. auto bitmapExtrudeU16_RGBA = [](const void* src, void* dst, U32 h, U32 w, U32 bpp) {
  131. bitmapExtrudeGeneric((const U16*)src, (U16*)dst, w, h, 4, bpp);
  132. };
  133. // 32-bit float RGBA
  134. auto bitmapExtrudeF32_RGBA = [](const void* src, void* dst, U32 h, U32 w, U32 bpp) {
  135. bitmapExtrudeGeneric((const F32*)src, (F32*)dst, w, h, 4, bpp);
  136. };
  137. // RGB U8
  138. auto bitmapExtrudeU8_RGB = [](const void* src, void* dst, U32 h, U32 w, U32 bpp) {
  139. bitmapExtrudeGeneric((const U8*)src, (U8*)dst, w, h, 3, bpp);
  140. };
  141. void (*bitmapExtrude5551)(const void* srcMip, void* mip, U32 height, U32 width) = bitmapExtrude5551_c;
  142. void (*bitmapExtrudeRGB)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeU8_RGB;
  143. void (*bitmapExtrudeRGBA)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeU8_RGBA;
  144. void (*bitmapExtrude16BitRGBA)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeU16_RGBA;
  145. void (*bitmapExtrudeFPRGBA)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeU16_RGBA;
  146. void (*bitmapExtrudeF32RGBA)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeF32_RGBA;
  147. struct StbResizeDesc
  148. {
  149. stbir_datatype datatype;
  150. stbir_pixel_layout layout;
  151. U32 bytesPerPixel;
  152. };
  153. inline bool getStbResizeDesc(GFXFormat fmt, StbResizeDesc& out)
  154. {
  155. switch (fmt)
  156. {
  157. // ---- 1 channel ----
  158. case GFXFormatA8:
  159. case GFXFormatL8:
  160. out = { STBIR_TYPE_UINT8, STBIR_1CHANNEL, 1 };
  161. return true;
  162. case GFXFormatL16:
  163. out = { STBIR_TYPE_UINT16, STBIR_1CHANNEL, 2 };
  164. return true;
  165. case GFXFormatR16F:
  166. out = { STBIR_TYPE_HALF_FLOAT, STBIR_1CHANNEL, 2 };
  167. return true;
  168. case GFXFormatR32F:
  169. out = { STBIR_TYPE_FLOAT, STBIR_1CHANNEL, 4 };
  170. return true;
  171. // ---- 2 channel ----
  172. case GFXFormatA8L8:
  173. out = { STBIR_TYPE_UINT8, STBIR_2CHANNEL, 2 };
  174. return true;
  175. case GFXFormatR16G16:
  176. out = { STBIR_TYPE_UINT16, STBIR_2CHANNEL, 4 };
  177. return true;
  178. case GFXFormatR16G16F:
  179. out = { STBIR_TYPE_HALF_FLOAT, STBIR_2CHANNEL, 4 };
  180. return true;
  181. // ---- RGB ----
  182. case GFXFormatR8G8B8:
  183. out = { STBIR_TYPE_UINT8, STBIR_RGB, 3 };
  184. return true;
  185. case GFXFormatR8G8B8_SRGB:
  186. out = { STBIR_TYPE_UINT8_SRGB, STBIR_RGB, 3 };
  187. return true;
  188. // ---- RGBA / RGBX ----
  189. case GFXFormatR8G8B8A8:
  190. case GFXFormatR8G8B8X8:
  191. out = { STBIR_TYPE_UINT8, STBIR_RGBA, 4 };
  192. return true;
  193. case GFXFormatR8G8B8A8_SRGB:
  194. out = { STBIR_TYPE_UINT8_SRGB_ALPHA, STBIR_RGBA, 4 };
  195. return true;
  196. case GFXFormatB8G8R8A8:
  197. out = { STBIR_TYPE_UINT8, STBIR_BGRA, 4 };
  198. return true;
  199. // ---- 16-bit RGBA ----
  200. case GFXFormatR16G16B16A16:
  201. out = { STBIR_TYPE_UINT16, STBIR_RGBA, 8 };
  202. return true;
  203. case GFXFormatR16G16B16A16F:
  204. out = { STBIR_TYPE_HALF_FLOAT, STBIR_RGBA, 8 };
  205. return true;
  206. // ---- 32-bit RGBA ----
  207. case GFXFormatR32G32B32A32F:
  208. out = { STBIR_TYPE_FLOAT, STBIR_RGBA, 16 };
  209. return true;
  210. default:
  211. return false;
  212. }
  213. }
  214. void bitmapStbResizeToOutput(const void* src, U32 srcHeight, U32 srcWidth, void* out, U32 outHeight, U32 outWidth, U32 bpp, GFXFormat format)
  215. {
  216. StbResizeDesc desc;
  217. if (!getStbResizeDesc(format, desc))
  218. {
  219. return;
  220. }
  221. const int srcStride = srcWidth * bpp;
  222. const int dstStride = outWidth * bpp;
  223. stbir_resize(
  224. src,
  225. srcWidth,
  226. srcHeight,
  227. srcStride,
  228. out,
  229. outWidth,
  230. outHeight,
  231. dstStride,
  232. desc.layout,
  233. desc.datatype,
  234. STBIR_EDGE_CLAMP,
  235. STBIR_FILTER_MITCHELL);
  236. }
  237. void(*bitmapResizeToOutput)(const void* src, U32 srcHeight, U32 srcWidth, void* out, U32 outHeight, U32 outWidth, U32 bpp, GFXFormat format) = bitmapStbResizeToOutput;
  238. //--------------------------------------------------------------------------------
  239. // Format description
  240. //--------------------------------------------------------------------------------
  241. // Channel semantics
  242. enum ChannelSemantic : U8
  243. {
  244. CH_NONE,
  245. CH_L,
  246. CH_A,
  247. CH_R,
  248. CH_G,
  249. CH_B
  250. };
  251. //--------------------------------------------------------------------------------
  252. // Bitmap format descriptor
  253. struct GBitmapFormatDesc
  254. {
  255. U8 channels;
  256. ChannelSemantic semantic[4]; // per-channel meaning
  257. stbir_datatype datatype;
  258. bool srgb;
  259. bool premultiplied;
  260. bool isFloat;
  261. U8 bytesPerChannel;
  262. bool is8() const { return !isFloat && bytesPerChannel == 1; }
  263. bool is16() const { return !isFloat && bytesPerChannel == 2; }
  264. };
  265. //--------------------------------------------------------------------------------
  266. // Table mapping GFXFormat -> descriptor
  267. GBitmapFormatDesc getFormatDesc(GFXFormat fmt)
  268. {
  269. switch (fmt)
  270. {
  271. // 8-bit formats
  272. case GFXFormatA8:
  273. return { 1, {CH_A, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
  274. case GFXFormatL8:
  275. return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
  276. case GFXFormatA4L4:
  277. return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
  278. // 16-bit formats
  279. case GFXFormatR5G6B5:
  280. return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
  281. case GFXFormatR5G5B5A1:
  282. return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8, false, false, false, 1 };
  283. case GFXFormatR5G5B5X1:
  284. return { 4, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
  285. case GFXFormatA8L8:
  286. return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
  287. case GFXFormatL16:
  288. return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT16, false, false, false, 2 };
  289. case GFXFormatR16F:
  290. return { 1, {CH_R, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_HALF_FLOAT, false, false, true, 2 };
  291. case GFXFormatD16:
  292. return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT16, false, false, false, 2 };
  293. // 24-bit formats
  294. case GFXFormatR8G8B8:
  295. return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
  296. case GFXFormatR8G8B8_SRGB:
  297. return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8_SRGB, true, false, false, 1 };
  298. // 32-bit formats
  299. case GFXFormatR8G8B8A8:
  300. case GFXFormatR8G8B8X8:
  301. return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8, false, false, false, 1 };
  302. case GFXFormatB8G8R8A8:
  303. return { 4, {CH_B, CH_G, CH_R, CH_A}, STBIR_TYPE_UINT8, false, false, false, 1 };
  304. case GFXFormatR8G8B8A8_SRGB:
  305. return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8_SRGB_ALPHA, true, false, false, 1 };
  306. case GFXFormatR16G16:
  307. return { 2, {CH_R, CH_G, CH_NONE, CH_NONE}, STBIR_TYPE_UINT16, false, false, false, 2 };
  308. case GFXFormatR16G16F:
  309. return { 2, {CH_R, CH_G, CH_NONE, CH_NONE}, STBIR_TYPE_HALF_FLOAT, false, false, true, 2 };
  310. // 64-bit formats
  311. case GFXFormatR16G16B16A16:
  312. return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT16, false, false, false, 2 };
  313. case GFXFormatR16G16B16A16F:
  314. return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_HALF_FLOAT, false, false, true, 2 };
  315. // 128-bit formats
  316. case GFXFormatR32G32B32A32F:
  317. return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_FLOAT, false, false, true, 4 };
  318. default: // fallback
  319. return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
  320. }
  321. }
  322. //--------------------------------------------------------------------------------
  323. // Conversion plan
  324. struct ConversionPlan
  325. {
  326. bool bitDepthChange;
  327. bool channelRepack;
  328. bool colorspaceChange;
  329. };
  330. ConversionPlan decideConversion(const GBitmapFormatDesc& src, const GBitmapFormatDesc& dst)
  331. {
  332. ConversionPlan plan = {};
  333. plan.bitDepthChange = src.bytesPerChannel != dst.bytesPerChannel || src.isFloat != dst.isFloat;
  334. plan.channelRepack = src.channels != dst.channels || dMemcmp(src.semantic, dst.semantic, sizeof(src.semantic)) != 0;
  335. plan.colorspaceChange = src.srgb != dst.srgb;
  336. return plan;
  337. }
  338. //--------------------------------------------------------------------------------
  339. // Linear representation
  340. struct LinearPixel
  341. {
  342. float r = 0.f, g = 0.f, b = 0.f, a = 1.f;
  343. };
  344. inline float srgbToLinear(float c)
  345. {
  346. return (c <= 0.04045f) ? c / 12.92f : powf((c + 0.055f) / 1.055f, 2.4f);
  347. }
  348. inline float linearToSrgb(float c)
  349. {
  350. return (c <= 0.0031308f) ? c * 12.92f : 1.055f * powf(c, 1.f / 2.4f) - 0.055f;
  351. }
  352. //--------------------------------------------------------------------------------
  353. // Load a pixel from src format into LinearPixel
  354. static inline LinearPixel loadPixel(const void* src, const GBitmapFormatDesc& fmt, U32 index)
  355. {
  356. LinearPixel p;
  357. const U8* base = (const U8*)src + index * fmt.channels * fmt.bytesPerChannel;
  358. for (U32 c = 0; c < fmt.channels; ++c)
  359. {
  360. float v = 0.f;
  361. if (fmt.is8())
  362. v = float(base[c]) / 255.f;
  363. else if (fmt.is16())
  364. v = float(convert16To8(*(const U16*)(base + c * 2))) / 255.f;
  365. else if (fmt.isFloat)
  366. {
  367. if (fmt.bytesPerChannel == 2) // half float
  368. v = convertHalfToFloat(*(const U16*)(base + c * 2));
  369. else // full float
  370. v = *(const float*)(base + c * 4);
  371. }
  372. if (fmt.srgb && fmt.semantic[c] != CH_A)
  373. v = srgbToLinear(v);
  374. switch (fmt.semantic[c])
  375. {
  376. case CH_R: p.r = v; break;
  377. case CH_G: p.g = v; break;
  378. case CH_B: p.b = v; break;
  379. case CH_A: p.a = v; break;
  380. case CH_L: p.r = p.g = p.b = v; break;
  381. default: break;
  382. }
  383. }
  384. return p;
  385. }
  386. //--------------------------------------------------------------------------------
  387. // Store a LinearPixel into dst format
  388. static inline void storePixel(void* dst, const GBitmapFormatDesc& fmt, U32 index, const LinearPixel& p)
  389. {
  390. U8* base = (U8*)dst + index * fmt.channels * fmt.bytesPerChannel;
  391. for (U32 c = 0; c < fmt.channels; ++c)
  392. {
  393. float v = 0.f;
  394. switch (fmt.semantic[c])
  395. {
  396. case CH_R: v = p.r; break;
  397. case CH_G: v = p.g; break;
  398. case CH_B: v = p.b; break;
  399. case CH_A: v = p.a; break;
  400. case CH_L: v = (p.r + p.g + p.b) / 3.f; break;
  401. default: break;
  402. }
  403. if (fmt.srgb && fmt.semantic[c] != CH_A)
  404. v = linearToSrgb(v);
  405. if (fmt.is8())
  406. base[c] = uint8_t(mClamp(v * 255.f, 0.f, 255.f));
  407. else if (fmt.is16())
  408. *(U16*)(base + c * 2) = convert8To16(uint8_t(mClamp(v * 255.f, 0.f, 255.f)));
  409. else if (fmt.isFloat)
  410. {
  411. if (fmt.bytesPerChannel == 2) // half float
  412. *(U16*)(base + c * 2) = convertFloatToHalf(v);
  413. else
  414. *(float*)(base + c * 4) = v;
  415. }
  416. }
  417. }
  418. //--------------------------------------------------------------------------------
  419. // Main generalized converter
  420. bool bitmapConvertFormat(U8** srcBuffer, U32 pixels, const GBitmapFormatDesc& srcFmt, const GBitmapFormatDesc& dstFmt)
  421. {
  422. ConversionPlan plan = decideConversion(srcFmt, dstFmt);
  423. if (!plan.bitDepthChange && !plan.channelRepack && !plan.colorspaceChange)
  424. return true; // nothing to do
  425. void* dstBuffer = *srcBuffer;
  426. if (plan.bitDepthChange || plan.channelRepack)
  427. dstBuffer = new U8[pixels * dstFmt.channels * dstFmt.bytesPerChannel];
  428. for (U32 i = 0; i < pixels; ++i)
  429. {
  430. LinearPixel p = loadPixel(*srcBuffer, srcFmt, i);
  431. storePixel(dstBuffer, dstFmt, i, p);
  432. }
  433. if (dstBuffer != *srcBuffer)
  434. {
  435. delete[](U8*)* srcBuffer;
  436. *srcBuffer = (U8*)dstBuffer;
  437. }
  438. return true;
  439. }
  440. //--------------------------------------------------------------------------------
  441. // Entry point for GBitmap::setFormat
  442. bool bitmapALLConvertToOutput(U8** src, U32 pixels, GFXFormat srcFormat, GFXFormat dstFormat)
  443. {
  444. const GBitmapFormatDesc& srcFmt = getFormatDesc(srcFormat);
  445. const GBitmapFormatDesc& dstFmt = getFormatDesc(dstFormat);
  446. return bitmapConvertFormat(src, pixels, srcFmt, dstFmt);
  447. }
  448. bool(*bitmapConvertToOutput)(U8** src, U32 pixels, GFXFormat srcFormat, GFXFormat dstFormat) = bitmapALLConvertToOutput;
  449. //--------------------------------------------------------------------------
  450. void bitmapConvertRGB_to_1555_c(U8 *src, U32 pixels)
  451. {
  452. U16 *dst = (U16 *)src;
  453. for(U32 j = 0; j < pixels; j++)
  454. {
  455. U32 r = src[0] >> 3;
  456. U32 g = src[1] >> 3;
  457. U32 b = src[2] >> 3;
  458. #if defined(TORQUE_BIG_ENDIAN)
  459. *dst++ = 0x8000 | (b << 10) | (g << 5) | (r << 0);
  460. #else
  461. *dst++ = b | (g << 5) | (r << 10) | 0x8000;
  462. #endif
  463. src += 3;
  464. }
  465. }
  466. void (*bitmapConvertRGB_to_1555)(U8 *src, U32 pixels) = bitmapConvertRGB_to_1555_c;
  467. //------------------------------------------------------------------------------
  468. void bitmapConvertRGB_to_5551_c(U8 *src, U32 pixels)
  469. {
  470. U16 *dst = (U16 *)src;
  471. for(U32 j = 0; j < pixels; j++)
  472. {
  473. U32 r = src[0] >> 3;
  474. U32 g = src[1] >> 3;
  475. U32 b = src[2] >> 3;
  476. #if defined(TORQUE_BIG_ENDIAN)
  477. *dst++ = (1 << 15) | (b << 10) | (g << 5) | (r << 0);
  478. #else
  479. *dst++ = (b << 1) | (g << 6) | (r << 11) | 1;
  480. #endif
  481. src += 3;
  482. }
  483. }
  484. void (*bitmapConvertRGB_to_5551)(U8 *src, U32 pixels) = bitmapConvertRGB_to_5551_c;
  485. //------------------------------------------------------------------------------
  486. void bitmapConvertRGB_to_RGBX_c( U8 **src, U32 pixels )
  487. {
  488. const U8 *oldBits = *src;
  489. U8 *newBits = new U8[pixels * 4];
  490. dMemset( newBits, 0xFF, pixels * 4 ); // This is done to set alpha values -patw
  491. // Copy the bits over to the new memory
  492. for( U32 i = 0; i < pixels; i++ )
  493. dMemcpy( &newBits[i * 4], &oldBits[i * 3], sizeof(U8) * 3 );
  494. // Now hose the old bits
  495. delete [] *src;
  496. *src = newBits;
  497. }
  498. void (*bitmapConvertRGB_to_RGBX)( U8 **src, U32 pixels ) = bitmapConvertRGB_to_RGBX_c;
  499. //------------------------------------------------------------------------------
  500. void bitmapConvertRGBX_to_RGB_c( U8 **src, U32 pixels )
  501. {
  502. const U8 *oldBits = *src;
  503. U8 *newBits = new U8[pixels * 3];
  504. // Copy the bits over to the new memory
  505. for( U32 i = 0; i < pixels; i++ )
  506. dMemcpy( &newBits[i * 3], &oldBits[i * 4], sizeof(U8) * 3 );
  507. // Now hose the old bits
  508. delete [] *src;
  509. *src = newBits;
  510. }
  511. void (*bitmapConvertRGBX_to_RGB)( U8 **src, U32 pixels ) = bitmapConvertRGBX_to_RGB_c;
  512. //------------------------------------------------------------------------------
  513. void bitmapConvertA8_to_RGBA_c( U8 **src, U32 pixels )
  514. {
  515. const U8 *oldBits = *src;
  516. U8 *newBits = new U8[pixels * 4];
  517. // Zero new bits
  518. dMemset( newBits, 0, pixels * 4 );
  519. // Copy Alpha values
  520. for( U32 i = 0; i < pixels; i++ )
  521. newBits[i * 4 + 3] = oldBits[i];
  522. // Now hose the old bits
  523. delete [] *src;
  524. *src = newBits;
  525. }
  526. void (*bitmapConvertA8_to_RGBA)( U8 **src, U32 pixels ) = bitmapConvertA8_to_RGBA_c;