image_decode.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. /*
  2. * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "bimg_p.h"
  6. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-function")
  7. BX_PRAGMA_DIAGNOSTIC_PUSH()
  8. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wtype-limits")
  9. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-parameter")
  10. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-value")
  11. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wdeprecated-declarations")
  12. BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4100) // error C4100: '' : unreferenced formal parameter
  13. BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4505) // warning C4505: 'tinyexr::miniz::def_realloc_func': unreferenced local function has been removed
  14. #if BX_PLATFORM_EMSCRIPTEN
  15. # include <compat/ctype.h>
  16. #endif // BX_PLATFORM_EMSCRIPTEN
  17. #define MINIZ_NO_ARCHIVE_APIS
  18. #define MINIZ_NO_STDIO
  19. #define TINYEXR_IMPLEMENTATION
  20. #include <tinyexr/tinyexr.h>
  21. BX_PRAGMA_DIAGNOSTIC_POP()
  22. BX_PRAGMA_DIAGNOSTIC_PUSH();
  23. BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4127) // warning C4127: conditional expression is constant
  24. #define LODEPNG_NO_COMPILE_ENCODER
  25. #define LODEPNG_NO_COMPILE_DISK
  26. #define LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
  27. #define LODEPNG_NO_COMPILE_ERROR_TEXT
  28. #define LODEPNG_NO_COMPILE_ALLOCATORS
  29. #define LODEPNG_NO_COMPILE_CPP
  30. #include <lodepng/lodepng.cpp>
  31. BX_PRAGMA_DIAGNOSTIC_POP();
  32. void* lodepng_malloc(size_t _size)
  33. {
  34. return ::malloc(_size);
  35. }
  36. void* lodepng_realloc(void* _ptr, size_t _size)
  37. {
  38. return ::realloc(_ptr, _size);
  39. }
  40. void lodepng_free(void* _ptr)
  41. {
  42. ::free(_ptr);
  43. }
  44. BX_PRAGMA_DIAGNOSTIC_PUSH();
  45. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wmissing-field-initializers");
  46. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow");
  47. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wint-to-pointer-cast")
  48. BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Warray-bounds");
  49. #if BX_COMPILER_GCC >= 60000
  50. BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wmisleading-indentation");
  51. BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wshift-negative-value");
  52. #elif BX_COMPILER_GCC >= 70000
  53. BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wimplicit-fallthrough");
  54. #endif // BX_COMPILER_GCC >= 60000_
  55. #define STBI_MALLOC(_size) lodepng_malloc(_size)
  56. #define STBI_REALLOC(_ptr, _size) lodepng_realloc(_ptr, _size)
  57. #define STBI_FREE(_ptr) lodepng_free(_ptr)
  58. #define STB_IMAGE_IMPLEMENTATION
  59. #include <stb/stb_image.h>
  60. BX_PRAGMA_DIAGNOSTIC_POP();
  61. namespace bimg
  62. {
  63. static ImageContainer* imageParseLodePng(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err)
  64. {
  65. BX_ERROR_SCOPE(_err);
  66. static uint8_t pngMagic[] = { 0x89, 0x50, 0x4E, 0x47, 0x0d, 0x0a };
  67. if (0 != bx::memCmp(_data, pngMagic, sizeof(pngMagic) ) )
  68. {
  69. return NULL;
  70. }
  71. ImageContainer* output = NULL;
  72. bimg::TextureFormat::Enum format = bimg::TextureFormat::RGBA8;
  73. uint32_t width = 0;
  74. uint32_t height = 0;
  75. unsigned error;
  76. LodePNGState state;
  77. lodepng_state_init(&state);
  78. state.decoder.color_convert = 0;
  79. uint8_t* data = NULL;
  80. error = lodepng_decode(&data, &width, &height, &state, (uint8_t*)_data, _size);
  81. if (0 == error)
  82. {
  83. bool palette = false;
  84. bool supported = false;
  85. switch (state.info_raw.bitdepth)
  86. {
  87. case 1:
  88. format = bimg::TextureFormat::R1;
  89. palette = false;
  90. supported = true;
  91. break;
  92. case 8:
  93. switch (state.info_raw.colortype)
  94. {
  95. case LCT_GREY:
  96. format = bimg::TextureFormat::R8;
  97. supported = true;
  98. break;
  99. case LCT_GREY_ALPHA:
  100. format = bimg::TextureFormat::RG8;
  101. supported = true;
  102. break;
  103. case LCT_RGB:
  104. format = bimg::TextureFormat::RGB8;
  105. supported = true;
  106. break;
  107. case LCT_RGBA:
  108. format = bimg::TextureFormat::RGBA8;
  109. supported = true;
  110. break;
  111. case LCT_PALETTE:
  112. format = bimg::TextureFormat::RGBA8;
  113. palette = true;
  114. supported = true;
  115. break;
  116. }
  117. break;
  118. case 16:
  119. switch (state.info_raw.colortype)
  120. {
  121. case LCT_GREY:
  122. for (uint32_t ii = 0, num = width*height; ii < num; ++ii)
  123. {
  124. uint16_t* rgba = (uint16_t*)data + ii;
  125. rgba[0] = bx::toHostEndian(rgba[0], false);
  126. }
  127. format = bimg::TextureFormat::R16;
  128. supported = true;
  129. break;
  130. case LCT_GREY_ALPHA:
  131. for (uint32_t ii = 0, num = width*height; ii < num; ++ii)
  132. {
  133. uint16_t* rgba = (uint16_t*)data + ii*2;
  134. rgba[0] = bx::toHostEndian(rgba[0], false);
  135. rgba[1] = bx::toHostEndian(rgba[1], false);
  136. }
  137. format = bimg::TextureFormat::RG16;
  138. supported = true;
  139. break;
  140. case LCT_RGB:
  141. for (uint32_t ii = 0, num = width*height; ii < num; ++ii)
  142. {
  143. uint16_t* rgba = (uint16_t*)data + ii*3;
  144. rgba[0] = bx::toHostEndian(rgba[0], false);
  145. rgba[1] = bx::toHostEndian(rgba[1], false);
  146. rgba[2] = bx::toHostEndian(rgba[2], false);
  147. }
  148. format = bimg::TextureFormat::RGBA16;
  149. supported = true;
  150. break;
  151. case LCT_RGBA:
  152. for (uint32_t ii = 0, num = width*height; ii < num; ++ii)
  153. {
  154. uint16_t* rgba = (uint16_t*)data + ii*4;
  155. rgba[0] = bx::toHostEndian(rgba[0], false);
  156. rgba[1] = bx::toHostEndian(rgba[1], false);
  157. rgba[2] = bx::toHostEndian(rgba[2], false);
  158. rgba[3] = bx::toHostEndian(rgba[3], false);
  159. }
  160. format = bimg::TextureFormat::RGBA16;
  161. supported = true;
  162. break;
  163. case LCT_PALETTE:
  164. break;
  165. }
  166. break;
  167. default:
  168. break;
  169. }
  170. if (supported)
  171. {
  172. const uint8_t* copyData = data;
  173. TextureFormat::Enum dstFormat = format;
  174. if (1 == state.info_raw.bitdepth)
  175. {
  176. dstFormat = bimg::TextureFormat::R8;
  177. copyData = NULL;
  178. }
  179. else if (16 == state.info_raw.bitdepth
  180. && LCT_RGB == state.info_raw.colortype)
  181. {
  182. dstFormat = bimg::TextureFormat::RGBA16;
  183. copyData = NULL;
  184. }
  185. else if (palette)
  186. {
  187. copyData = NULL;
  188. }
  189. output = imageAlloc(_allocator
  190. , dstFormat
  191. , uint16_t(width)
  192. , uint16_t(height)
  193. , 0
  194. , 1
  195. , false
  196. , false
  197. , copyData
  198. );
  199. if (1 == state.info_raw.bitdepth)
  200. {
  201. for (uint32_t ii = 0, num = width*height/8; ii < num; ++ii)
  202. {
  203. uint8_t value = data[ii];
  204. uint8_t* dst = (uint8_t*)output->m_data + ii * 8;
  205. dst[0] = value & 0x01 ? 255 : 0;
  206. dst[1] = value & 0x02 ? 255 : 0;
  207. dst[2] = value & 0x04 ? 255 : 0;
  208. dst[3] = value & 0x08 ? 255 : 0;
  209. dst[4] = value & 0x10 ? 255 : 0;
  210. dst[5] = value & 0x20 ? 255 : 0;
  211. dst[6] = value & 0x40 ? 255 : 0;
  212. dst[7] = value & 0x80 ? 255 : 0;
  213. }
  214. }
  215. else if (16 == state.info_raw.bitdepth
  216. && LCT_RGB == state.info_raw.colortype)
  217. {
  218. for (uint32_t ii = 0, num = width*height; ii < num; ++ii)
  219. {
  220. const uint16_t* src = (uint16_t*)data + ii*3;
  221. uint16_t* dst = (uint16_t*)output->m_data + ii*4;
  222. dst[0] = src[0];
  223. dst[1] = src[1];
  224. dst[2] = src[2];
  225. dst[3] = UINT16_MAX;
  226. }
  227. }
  228. else if (palette)
  229. {
  230. for (uint32_t ii = 0, num = width*height; ii < num; ++ii)
  231. {
  232. bx::memCopy( (uint8_t*)output->m_data + ii*4, state.info_raw.palette + data[ii]*4, 4);
  233. }
  234. }
  235. }
  236. else
  237. {
  238. BX_ERROR_SET(_err, BIMG_ERROR, "PNG: Unsupported format.");
  239. }
  240. }
  241. lodepng_state_cleanup(&state);
  242. lodepng_free(data);
  243. return output;
  244. }
  245. static ImageContainer* imageParseTinyExr(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err)
  246. {
  247. BX_ERROR_SCOPE(_err);
  248. EXRVersion exrVersion;
  249. int result = ParseEXRVersionFromMemory(&exrVersion, (uint8_t*)_data, _size);
  250. if (TINYEXR_SUCCESS != result)
  251. {
  252. return NULL;
  253. }
  254. bimg::TextureFormat::Enum format = bimg::TextureFormat::RGBA8;
  255. uint32_t width = 0;
  256. uint32_t height = 0;
  257. uint8_t* data = NULL;
  258. const char* err = NULL;
  259. EXRHeader exrHeader;
  260. result = ParseEXRHeaderFromMemory(&exrHeader, &exrVersion, (uint8_t*)_data, _size, &err);
  261. if (TINYEXR_SUCCESS == result)
  262. {
  263. EXRImage exrImage;
  264. InitEXRImage(&exrImage);
  265. result = LoadEXRImageFromMemory(&exrImage, &exrHeader, (uint8_t*)_data, _size, &err);
  266. if (TINYEXR_SUCCESS == result)
  267. {
  268. uint8_t idxR = UINT8_MAX;
  269. uint8_t idxG = UINT8_MAX;
  270. uint8_t idxB = UINT8_MAX;
  271. uint8_t idxA = UINT8_MAX;
  272. for (uint8_t ii = 0, num = uint8_t(exrHeader.num_channels); ii < num; ++ii)
  273. {
  274. const EXRChannelInfo& channel = exrHeader.channels[ii];
  275. if (UINT8_MAX == idxR
  276. && 0 == bx::strCmp(channel.name, "R") )
  277. {
  278. idxR = ii;
  279. }
  280. else if (UINT8_MAX == idxG
  281. && 0 == bx::strCmp(channel.name, "G") )
  282. {
  283. idxG = ii;
  284. }
  285. else if (UINT8_MAX == idxB
  286. && 0 == bx::strCmp(channel.name, "B") )
  287. {
  288. idxB = ii;
  289. }
  290. else if (UINT8_MAX == idxA
  291. && 0 == bx::strCmp(channel.name, "A") )
  292. {
  293. idxA = ii;
  294. }
  295. }
  296. if (UINT8_MAX != idxR)
  297. {
  298. const bool asFloat = exrHeader.pixel_types[idxR] == TINYEXR_PIXELTYPE_FLOAT;
  299. uint32_t srcBpp = 32;
  300. uint32_t dstBpp = asFloat ? 32 : 16;
  301. format = asFloat ? TextureFormat::R32F : TextureFormat::R16F;
  302. uint32_t stepR = 1;
  303. uint32_t stepG = 0;
  304. uint32_t stepB = 0;
  305. uint32_t stepA = 0;
  306. if (UINT8_MAX != idxG)
  307. {
  308. srcBpp += 32;
  309. dstBpp = asFloat ? 64 : 32;
  310. format = asFloat ? TextureFormat::RG32F : TextureFormat::RG16F;
  311. stepG = 1;
  312. }
  313. if (UINT8_MAX != idxB)
  314. {
  315. srcBpp += 32;
  316. dstBpp = asFloat ? 128 : 64;
  317. format = asFloat ? TextureFormat::RGBA32F : TextureFormat::RGBA16F;
  318. stepB = 1;
  319. }
  320. if (UINT8_MAX != idxA)
  321. {
  322. srcBpp += 32;
  323. dstBpp = asFloat ? 128 : 64;
  324. format = asFloat ? TextureFormat::RGBA32F : TextureFormat::RGBA16F;
  325. stepA = 1;
  326. }
  327. data = (uint8_t*)BX_ALLOC(_allocator, exrImage.width * exrImage.height * dstBpp/8);
  328. width = exrImage.width;
  329. height = exrImage.height;
  330. if (asFloat)
  331. {
  332. const float zero = 0.0f;
  333. const float* srcR = UINT8_MAX == idxR ? &zero : (const float*)(exrImage.images)[idxR];
  334. const float* srcG = UINT8_MAX == idxG ? &zero : (const float*)(exrImage.images)[idxG];
  335. const float* srcB = UINT8_MAX == idxB ? &zero : (const float*)(exrImage.images)[idxB];
  336. const float* srcA = UINT8_MAX == idxA ? &zero : (const float*)(exrImage.images)[idxA];
  337. const uint32_t bytesPerPixel = dstBpp/8;
  338. for (uint32_t ii = 0, num = exrImage.width * exrImage.height; ii < num; ++ii)
  339. {
  340. float rgba[4] =
  341. {
  342. *srcR,
  343. *srcG,
  344. *srcB,
  345. *srcA,
  346. };
  347. bx::memCopy(&data[ii * bytesPerPixel], rgba, bytesPerPixel);
  348. srcR += stepR;
  349. srcG += stepG;
  350. srcB += stepB;
  351. srcA += stepA;
  352. }
  353. }
  354. else
  355. {
  356. const uint16_t zero = 0;
  357. const uint16_t* srcR = UINT8_MAX == idxR ? &zero : (const uint16_t*)(exrImage.images)[idxR];
  358. const uint16_t* srcG = UINT8_MAX == idxG ? &zero : (const uint16_t*)(exrImage.images)[idxG];
  359. const uint16_t* srcB = UINT8_MAX == idxB ? &zero : (const uint16_t*)(exrImage.images)[idxB];
  360. const uint16_t* srcA = UINT8_MAX == idxA ? &zero : (const uint16_t*)(exrImage.images)[idxA];
  361. const uint32_t bytesPerPixel = dstBpp/8;
  362. for (uint32_t ii = 0, num = exrImage.width * exrImage.height; ii < num; ++ii)
  363. {
  364. uint16_t rgba[4] =
  365. {
  366. *srcR,
  367. *srcG,
  368. *srcB,
  369. *srcA,
  370. };
  371. bx::memCopy(&data[ii * bytesPerPixel], rgba, bytesPerPixel);
  372. srcR += stepR;
  373. srcG += stepG;
  374. srcB += stepB;
  375. srcA += stepA;
  376. }
  377. }
  378. }
  379. else
  380. {
  381. BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Couldn't find R channel.");
  382. }
  383. FreeEXRImage(&exrImage);
  384. }
  385. else
  386. {
  387. BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image.");
  388. }
  389. FreeEXRHeader(&exrHeader);
  390. }
  391. else
  392. {
  393. BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse header.");
  394. }
  395. ImageContainer* output = NULL;
  396. if (NULL != data)
  397. {
  398. output = imageAlloc(_allocator
  399. , format
  400. , uint16_t(width)
  401. , uint16_t(height)
  402. , 0
  403. , 1
  404. , false
  405. , false
  406. , data
  407. );
  408. BX_FREE(_allocator, data);
  409. }
  410. return output;
  411. }
  412. static ImageContainer* imageParseStbImage(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err)
  413. {
  414. BX_ERROR_SCOPE(_err);
  415. const int isHdr = stbi_is_hdr_from_memory( (const uint8_t*)_data, (int)_size);
  416. void* data;
  417. uint32_t width = 0;
  418. uint32_t height = 0;
  419. int comp = 0;
  420. if (isHdr)
  421. {
  422. data = stbi_loadf_from_memory( (const uint8_t*)_data, (int)_size, (int*)&width, (int*)&height, &comp, 4);
  423. }
  424. else
  425. {
  426. data = stbi_load_from_memory ( (const uint8_t*)_data, (int)_size, (int*)&width, (int*)&height, &comp, 0);
  427. }
  428. if (NULL == data)
  429. {
  430. return NULL;
  431. }
  432. bimg::TextureFormat::Enum format = bimg::TextureFormat::RGBA8;
  433. if (isHdr)
  434. {
  435. format = bimg::TextureFormat::RGBA32F;
  436. }
  437. else
  438. {
  439. switch (comp)
  440. {
  441. case 1: format = bimg::TextureFormat::R8; break;
  442. case 2: format = bimg::TextureFormat::RG8; break;
  443. case 3: format = bimg::TextureFormat::RGB8; break;
  444. default: break;
  445. }
  446. }
  447. ImageContainer* output = imageAlloc(_allocator
  448. , format
  449. , uint16_t(width)
  450. , uint16_t(height)
  451. , 0
  452. , 1
  453. , false
  454. , false
  455. , data
  456. );
  457. stbi_image_free(data);
  458. return output;
  459. }
  460. static ImageContainer* imageParseJpeg(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err)
  461. {
  462. bx::MemoryReader reader(_data, _size);
  463. bx::Error err;
  464. uint16_t magic = 0;
  465. bx::readHE(&reader, magic, false, &err);
  466. if (!err.isOk()
  467. || 0xffd8 != magic)
  468. {
  469. return NULL;
  470. }
  471. Orientation::Enum orientation = Orientation::R0;
  472. while (err.isOk() )
  473. {
  474. bx::readHE(&reader, magic, false, &err);
  475. uint16_t size;
  476. bx::readHE(&reader, size, false, &err);
  477. if (!err.isOk() )
  478. {
  479. return NULL;
  480. }
  481. if (0xffe1 != magic)
  482. {
  483. bx::seek(&reader, size-2);
  484. continue;
  485. }
  486. char exif00[6];
  487. bx::read(&reader, exif00, 6, &err);
  488. if (0 == bx::memCmp(exif00, "Exif\0\0", 6) )
  489. {
  490. uint16_t iimm = 0;
  491. bx::read(&reader, iimm, &err);
  492. const bool littleEndian = iimm == 0x4949; //II - Intel - little endian
  493. if (!err.isOk()
  494. && !littleEndian
  495. && iimm != 0x4d4d) // MM - Motorola - big endian
  496. {
  497. return NULL;
  498. }
  499. bx::readHE(&reader, magic, littleEndian, &err);
  500. if (!err.isOk()
  501. || 0x2a != magic)
  502. {
  503. return NULL;
  504. }
  505. uint32_t ifd0;
  506. bx::readHE(&reader, ifd0, littleEndian, &err);
  507. if (!err.isOk()
  508. || 8 > ifd0)
  509. {
  510. return NULL;
  511. }
  512. bx::seek(&reader, ifd0-8);
  513. uint16_t numEntries;
  514. bx::readHE(&reader, numEntries, littleEndian, &err);
  515. for (uint32_t ii = 0; err.isOk() && ii < numEntries; ++ii)
  516. {
  517. // https://sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
  518. uint16_t tag;
  519. bx::readHE(&reader, tag, littleEndian, &err);
  520. uint16_t format;
  521. bx::readHE(&reader, format, littleEndian, &err);
  522. uint32_t length;
  523. bx::readHE(&reader, length, littleEndian, &err);
  524. uint32_t data;
  525. bx::readHE(&reader, data, littleEndian, &err);
  526. switch (tag)
  527. {
  528. case 0x112: // orientation
  529. if (3 == format)
  530. {
  531. bx::seek(&reader, -4);
  532. uint16_t u16;
  533. bx::readHE(&reader, u16, littleEndian, &err);
  534. uint16_t pad;
  535. bx::read(&reader, pad, &err);
  536. switch (u16)
  537. {
  538. default:
  539. case 1: orientation = Orientation::R0; break; // Horizontal (normal)
  540. case 2: orientation = Orientation::HFlip; break; // Mirror horizontal
  541. case 3: orientation = Orientation::R180; break; // Rotate 180
  542. case 4: orientation = Orientation::VFlip; break; // Mirror vertical
  543. case 5: orientation = Orientation::HFlipR270; break; // Mirror horizontal and rotate 270 CW
  544. case 6: orientation = Orientation::R90; break; // Rotate 90 CW
  545. case 7: orientation = Orientation::HFlipR90; break; // Mirror horizontal and rotate 90 CW
  546. case 8: orientation = Orientation::R270; break; // Rotate 270 CW
  547. }
  548. }
  549. break;
  550. default:
  551. break;
  552. }
  553. }
  554. }
  555. break;
  556. }
  557. ImageContainer* image = imageParseStbImage(_allocator, _data, _size, _err);
  558. if (NULL != image)
  559. {
  560. image->m_orientation = orientation;
  561. }
  562. return image;
  563. }
  564. ImageContainer* imageParse(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, TextureFormat::Enum _dstFormat, bx::Error* _err)
  565. {
  566. BX_ERROR_SCOPE(_err);
  567. ImageContainer* input = imageParseDds (_allocator, _data, _size, _err) ;
  568. input = NULL == input ? imageParseKtx (_allocator, _data, _size, _err) : input;
  569. input = NULL == input ? imageParsePvr3 (_allocator, _data, _size, _err) : input;
  570. input = NULL == input ? imageParseLodePng (_allocator, _data, _size, _err) : input;
  571. input = NULL == input ? imageParseTinyExr (_allocator, _data, _size, _err) : input;
  572. input = NULL == input ? imageParseJpeg (_allocator, _data, _size, _err) : input;
  573. input = NULL == input ? imageParseStbImage(_allocator, _data, _size, _err) : input;
  574. if (NULL == input)
  575. {
  576. return NULL;
  577. }
  578. _dstFormat = TextureFormat::Count == _dstFormat
  579. ? input->m_format
  580. : _dstFormat
  581. ;
  582. if (_dstFormat == input->m_format)
  583. {
  584. return input;
  585. }
  586. ImageContainer* output = imageConvert(_allocator, _dstFormat, *input);
  587. imageFree(input);
  588. return output;
  589. }
  590. } // namespace bimg