Image.cpp 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841
  1. //
  2. // Copyright (c) 2008-2015 the Urho3D project.
  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 deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // 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 FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Core/Context.h"
  23. #include "../Resource/Decompress.h"
  24. #include "../IO/File.h"
  25. #include "../IO/FileSystem.h"
  26. #include "../IO/Log.h"
  27. #include "../Core/Profiler.h"
  28. #include <cstdlib>
  29. #include <cstring>
  30. #include <STB/stb_image.h>
  31. #include <STB/stb_image_write.h>
  32. #include <JO/jo_jpeg.h>
  33. #include <SDL/SDL_surface.h>
  34. #include "../DebugNew.h"
  35. extern "C" unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len);
  36. #ifndef MAKEFOURCC
  37. #define MAKEFOURCC(ch0, ch1, ch2, ch3) ((unsigned)(ch0) | ((unsigned)(ch1) << 8) | ((unsigned)(ch2) << 16) | ((unsigned)(ch3) << 24))
  38. #endif
  39. #define FOURCC_DXT1 (MAKEFOURCC('D','X','T','1'))
  40. #define FOURCC_DXT2 (MAKEFOURCC('D','X','T','2'))
  41. #define FOURCC_DXT3 (MAKEFOURCC('D','X','T','3'))
  42. #define FOURCC_DXT4 (MAKEFOURCC('D','X','T','4'))
  43. #define FOURCC_DXT5 (MAKEFOURCC('D','X','T','5'))
  44. namespace Urho3D
  45. {
  46. /// DirectDraw color key definition.
  47. struct DDColorKey
  48. {
  49. unsigned dwColorSpaceLowValue_;
  50. unsigned dwColorSpaceHighValue_;
  51. };
  52. /// DirectDraw pixel format definition.
  53. struct DDPixelFormat
  54. {
  55. unsigned dwSize_;
  56. unsigned dwFlags_;
  57. unsigned dwFourCC_;
  58. union
  59. {
  60. unsigned dwRGBBitCount_;
  61. unsigned dwYUVBitCount_;
  62. unsigned dwZBufferBitDepth_;
  63. unsigned dwAlphaBitDepth_;
  64. unsigned dwLuminanceBitCount_;
  65. unsigned dwBumpBitCount_;
  66. unsigned dwPrivateFormatBitCount_;
  67. };
  68. union
  69. {
  70. unsigned dwRBitMask_;
  71. unsigned dwYBitMask_;
  72. unsigned dwStencilBitDepth_;
  73. unsigned dwLuminanceBitMask_;
  74. unsigned dwBumpDuBitMask_;
  75. unsigned dwOperations_;
  76. };
  77. union
  78. {
  79. unsigned dwGBitMask_;
  80. unsigned dwUBitMask_;
  81. unsigned dwZBitMask_;
  82. unsigned dwBumpDvBitMask_;
  83. struct
  84. {
  85. unsigned short wFlipMSTypes_;
  86. unsigned short wBltMSTypes_;
  87. } multiSampleCaps_;
  88. };
  89. union
  90. {
  91. unsigned dwBBitMask_;
  92. unsigned dwVBitMask_;
  93. unsigned dwStencilBitMask_;
  94. unsigned dwBumpLuminanceBitMask_;
  95. };
  96. union
  97. {
  98. unsigned dwRGBAlphaBitMask_;
  99. unsigned dwYUVAlphaBitMask_;
  100. unsigned dwLuminanceAlphaBitMask_;
  101. unsigned dwRGBZBitMask_;
  102. unsigned dwYUVZBitMask_;
  103. };
  104. };
  105. /// DirectDraw surface capabilities.
  106. struct DDSCaps2
  107. {
  108. unsigned dwCaps_;
  109. unsigned dwCaps2_;
  110. unsigned dwCaps3_;
  111. union
  112. {
  113. unsigned dwCaps4_;
  114. unsigned dwVolumeDepth_;
  115. };
  116. };
  117. /// DirectDraw surface description.
  118. struct DDSurfaceDesc2
  119. {
  120. unsigned dwSize_;
  121. unsigned dwFlags_;
  122. unsigned dwHeight_;
  123. unsigned dwWidth_;
  124. union
  125. {
  126. unsigned lPitch_;
  127. unsigned dwLinearSize_;
  128. };
  129. union
  130. {
  131. unsigned dwBackBufferCount_;
  132. unsigned dwDepth_;
  133. };
  134. union
  135. {
  136. unsigned dwMipMapCount_;
  137. unsigned dwRefreshRate_;
  138. unsigned dwSrcVBHandle_;
  139. };
  140. unsigned dwAlphaBitDepth_;
  141. unsigned dwReserved_;
  142. unsigned lpSurface_; // Do not define as a void pointer, as it is 8 bytes in a 64bit build
  143. union
  144. {
  145. DDColorKey ddckCKDestOverlay_;
  146. unsigned dwEmptyFaceColor_;
  147. };
  148. DDColorKey ddckCKDestBlt_;
  149. DDColorKey ddckCKSrcOverlay_;
  150. DDColorKey ddckCKSrcBlt_;
  151. union
  152. {
  153. DDPixelFormat ddpfPixelFormat_;
  154. unsigned dwFVF_;
  155. };
  156. DDSCaps2 ddsCaps_;
  157. unsigned dwTextureStage_;
  158. };
  159. bool CompressedLevel::Decompress(unsigned char* dest)
  160. {
  161. if (!data_)
  162. return false;
  163. switch (format_)
  164. {
  165. case CF_DXT1:
  166. case CF_DXT3:
  167. case CF_DXT5:
  168. DecompressImageDXT(dest, data_, width_, height_, depth_, format_);
  169. return true;
  170. case CF_ETC1:
  171. DecompressImageETC(dest, data_, width_, height_);
  172. return true;
  173. case CF_PVRTC_RGB_2BPP:
  174. case CF_PVRTC_RGBA_2BPP:
  175. case CF_PVRTC_RGB_4BPP:
  176. case CF_PVRTC_RGBA_4BPP:
  177. DecompressImagePVRTC(dest, data_, width_, height_, format_);
  178. return true;
  179. default:
  180. // Unknown format
  181. return false;
  182. }
  183. }
  184. Image::Image(Context* context) :
  185. Resource(context),
  186. width_(0),
  187. height_(0),
  188. depth_(0),
  189. components_(0)
  190. {
  191. }
  192. Image::~Image()
  193. {
  194. }
  195. void Image::RegisterObject(Context* context)
  196. {
  197. context->RegisterFactory<Image>();
  198. }
  199. bool Image::BeginLoad(Deserializer& source)
  200. {
  201. // Check for DDS, KTX or PVR compressed format
  202. String fileID = source.ReadFileID();
  203. if (fileID == "DDS ")
  204. {
  205. // DDS compressed format
  206. DDSurfaceDesc2 ddsd;
  207. source.Read(&ddsd, sizeof(ddsd));
  208. switch (ddsd.ddpfPixelFormat_.dwFourCC_)
  209. {
  210. case FOURCC_DXT1:
  211. compressedFormat_ = CF_DXT1;
  212. components_ = 3;
  213. break;
  214. case FOURCC_DXT3:
  215. compressedFormat_ = CF_DXT3;
  216. components_ = 4;
  217. break;
  218. case FOURCC_DXT5:
  219. compressedFormat_ = CF_DXT5;
  220. components_ = 4;
  221. break;
  222. case 0:
  223. if (ddsd.ddpfPixelFormat_.dwRGBBitCount_ != 32 && ddsd.ddpfPixelFormat_.dwRGBBitCount_ != 24 &&
  224. ddsd.ddpfPixelFormat_.dwRGBBitCount_ != 16)
  225. {
  226. LOGERROR("Unsupported DDS pixel byte size");
  227. return false;
  228. }
  229. compressedFormat_ = CF_RGBA;
  230. components_ = 4;
  231. break;
  232. default:
  233. LOGERROR("Unrecognized DDS image format");
  234. return false;
  235. }
  236. unsigned dataSize = source.GetSize() - source.GetPosition();
  237. data_ = new unsigned char[dataSize];
  238. width_ = ddsd.dwWidth_;
  239. height_ = ddsd.dwHeight_;
  240. depth_ = ddsd.dwDepth_;
  241. numCompressedLevels_ = ddsd.dwMipMapCount_;
  242. if (!numCompressedLevels_)
  243. numCompressedLevels_ = 1;
  244. SetMemoryUse(dataSize);
  245. source.Read(data_.Get(), dataSize);
  246. // If uncompressed DDS, convert the data to 8bit RGBA as the texture classes can not currently use eg. RGB565 format
  247. if (compressedFormat_ == CF_RGBA)
  248. {
  249. PROFILE(ConvertDDSToRGBA);
  250. unsigned sourcePixelByteSize = ddsd.ddpfPixelFormat_.dwRGBBitCount_ >> 3;
  251. unsigned numPixels = dataSize / sourcePixelByteSize;
  252. #define ADJUSTSHIFT(mask, l, r) \
  253. if (mask && mask >= 0x100) \
  254. { \
  255. while ((mask >> r) >= 0x100) \
  256. ++r; \
  257. } \
  258. else if (mask && mask < 0x80) \
  259. { \
  260. while ((mask << l) < 0x80) \
  261. ++l; \
  262. }
  263. unsigned rShiftL = 0, gShiftL = 0, bShiftL = 0, aShiftL = 0;
  264. unsigned rShiftR = 0, gShiftR = 0, bShiftR = 0, aShiftR = 0;
  265. unsigned rMask = ddsd.ddpfPixelFormat_.dwRBitMask_;
  266. unsigned gMask = ddsd.ddpfPixelFormat_.dwGBitMask_;
  267. unsigned bMask = ddsd.ddpfPixelFormat_.dwBBitMask_;
  268. unsigned aMask = ddsd.ddpfPixelFormat_.dwRGBAlphaBitMask_;
  269. ADJUSTSHIFT(rMask, rShiftL, rShiftR)
  270. ADJUSTSHIFT(gMask, gShiftL, gShiftR)
  271. ADJUSTSHIFT(bMask, bShiftL, bShiftR)
  272. ADJUSTSHIFT(aMask, aShiftL, aShiftR)
  273. SharedArrayPtr<unsigned char> rgbaData(new unsigned char[numPixels * 4]);
  274. SetMemoryUse(numPixels * 4);
  275. switch (sourcePixelByteSize)
  276. {
  277. case 4:
  278. {
  279. unsigned* src = (unsigned*)data_.Get();
  280. unsigned char* dest = rgbaData.Get();
  281. while (numPixels--)
  282. {
  283. unsigned pixels = *src++;
  284. *dest++ = ((pixels & rMask) << rShiftL) >> rShiftR;
  285. *dest++ = ((pixels & gMask) << gShiftL) >> gShiftR;
  286. *dest++ = ((pixels & bMask) << bShiftL) >> bShiftR;
  287. *dest++ = ((pixels & aMask) << aShiftL) >> aShiftR;
  288. }
  289. }
  290. break;
  291. case 3:
  292. {
  293. unsigned char* src = data_.Get();
  294. unsigned char* dest = rgbaData.Get();
  295. while (numPixels--)
  296. {
  297. unsigned pixels = src[0] | (src[1] << 8) | (src[2] << 16);
  298. src += 3;
  299. *dest++ = ((pixels & rMask) << rShiftL) >> rShiftR;
  300. *dest++ = ((pixels & gMask) << gShiftL) >> gShiftR;
  301. *dest++ = ((pixels & bMask) << bShiftL) >> bShiftR;
  302. *dest++ = ((pixels & aMask) << aShiftL) >> aShiftR;
  303. }
  304. }
  305. break;
  306. default:
  307. {
  308. unsigned short* src = (unsigned short*)data_.Get();
  309. unsigned char* dest = rgbaData.Get();
  310. while (numPixels--)
  311. {
  312. unsigned short pixels = *src++;
  313. *dest++ = ((pixels & rMask) << rShiftL) >> rShiftR;
  314. *dest++ = ((pixels & gMask) << gShiftL) >> gShiftR;
  315. *dest++ = ((pixels & bMask) << bShiftL) >> bShiftR;
  316. *dest++ = ((pixels & aMask) << aShiftL) >> aShiftR;
  317. }
  318. }
  319. break;
  320. }
  321. // Replace with converted data
  322. data_ = rgbaData;
  323. }
  324. }
  325. else if (fileID == "\253KTX")
  326. {
  327. source.Seek(12);
  328. unsigned endianness = source.ReadUInt();
  329. unsigned type = source.ReadUInt();
  330. /* unsigned typeSize = */ source.ReadUInt();
  331. unsigned format = source.ReadUInt();
  332. unsigned internalFormat = source.ReadUInt();
  333. /* unsigned baseInternalFormat = */ source.ReadUInt();
  334. unsigned width = source.ReadUInt();
  335. unsigned height = source.ReadUInt();
  336. unsigned depth = source.ReadUInt();
  337. /* unsigned arrayElements = */ source.ReadUInt();
  338. unsigned faces = source.ReadUInt();
  339. unsigned mipmaps = source.ReadUInt();
  340. unsigned keyValueBytes = source.ReadUInt();
  341. if (endianness != 0x04030201)
  342. {
  343. LOGERROR("Big-endian KTX files not supported");
  344. return false;
  345. }
  346. if (type != 0 || format != 0)
  347. {
  348. LOGERROR("Uncompressed KTX files not supported");
  349. return false;
  350. }
  351. if (faces > 1 || depth > 1)
  352. {
  353. LOGERROR("3D or cube KTX files not supported");
  354. return false;
  355. }
  356. if (mipmaps == 0)
  357. {
  358. LOGERROR("KTX files without explicitly specified mipmap count not supported");
  359. return false;
  360. }
  361. compressedFormat_ = CF_NONE;
  362. switch (internalFormat)
  363. {
  364. case 0x83f1:
  365. compressedFormat_ = CF_DXT1;
  366. components_ = 4;
  367. break;
  368. case 0x83f2:
  369. compressedFormat_ = CF_DXT3;
  370. components_ = 4;
  371. break;
  372. case 0x83f3:
  373. compressedFormat_ = CF_DXT5;
  374. components_ = 4;
  375. break;
  376. case 0x8d64:
  377. compressedFormat_ = CF_ETC1;
  378. components_ = 3;
  379. break;
  380. case 0x8c00:
  381. compressedFormat_ = CF_PVRTC_RGB_4BPP;
  382. components_ = 3;
  383. break;
  384. case 0x8c01:
  385. compressedFormat_ = CF_PVRTC_RGB_2BPP;
  386. components_ = 3;
  387. break;
  388. case 0x8c02:
  389. compressedFormat_ = CF_PVRTC_RGBA_4BPP;
  390. components_ = 4;
  391. break;
  392. case 0x8c03:
  393. compressedFormat_ = CF_PVRTC_RGBA_2BPP;
  394. components_ = 4;
  395. break;
  396. }
  397. if (compressedFormat_ == CF_NONE)
  398. {
  399. LOGERROR("Unsupported texture format in KTX file");
  400. return false;
  401. }
  402. source.Seek(source.GetPosition() + keyValueBytes);
  403. unsigned dataSize = source.GetSize() - source.GetPosition() - mipmaps * sizeof(unsigned);
  404. data_ = new unsigned char[dataSize];
  405. width_ = width;
  406. height_ = height;
  407. numCompressedLevels_ = mipmaps;
  408. unsigned dataOffset = 0;
  409. for (unsigned i = 0; i < mipmaps; ++i)
  410. {
  411. unsigned levelSize = source.ReadUInt();
  412. if (levelSize + dataOffset > dataSize)
  413. {
  414. LOGERROR("KTX mipmap level data size exceeds file size");
  415. return false;
  416. }
  417. source.Read(&data_[dataOffset], levelSize);
  418. dataOffset += levelSize;
  419. if (source.GetPosition() & 3)
  420. source.Seek((source.GetPosition() + 3) & 0xfffffffc);
  421. }
  422. SetMemoryUse(dataSize);
  423. }
  424. else if (fileID == "PVR\3")
  425. {
  426. /* unsigned flags = */ source.ReadUInt();
  427. unsigned pixelFormatLo = source.ReadUInt();
  428. /* unsigned pixelFormatHi = */ source.ReadUInt();
  429. /* unsigned colourSpace = */ source.ReadUInt();
  430. /* unsigned channelType = */ source.ReadUInt();
  431. unsigned height = source.ReadUInt();
  432. unsigned width = source.ReadUInt();
  433. unsigned depth = source.ReadUInt();
  434. /* unsigned numSurfaces = */ source.ReadUInt();
  435. unsigned numFaces = source.ReadUInt();
  436. unsigned mipmapCount = source.ReadUInt();
  437. unsigned metaDataSize = source.ReadUInt();
  438. if (depth > 1 || numFaces > 1)
  439. {
  440. LOGERROR("3D or cube PVR files not supported");
  441. return false;
  442. }
  443. if (mipmapCount == 0)
  444. {
  445. LOGERROR("PVR files without explicitly specified mipmap count not supported");
  446. return false;
  447. }
  448. compressedFormat_ = CF_NONE;
  449. switch (pixelFormatLo)
  450. {
  451. case 0:
  452. compressedFormat_ = CF_PVRTC_RGB_2BPP;
  453. components_ = 3;
  454. break;
  455. case 1:
  456. compressedFormat_ = CF_PVRTC_RGBA_2BPP;
  457. components_ = 4;
  458. break;
  459. case 2:
  460. compressedFormat_ = CF_PVRTC_RGB_4BPP;
  461. components_ = 3;
  462. break;
  463. case 3:
  464. compressedFormat_ = CF_PVRTC_RGBA_4BPP;
  465. components_ = 4;
  466. break;
  467. case 6:
  468. compressedFormat_ = CF_ETC1;
  469. components_ = 3;
  470. break;
  471. case 7:
  472. compressedFormat_ = CF_DXT1;
  473. components_ = 4;
  474. break;
  475. case 9:
  476. compressedFormat_ = CF_DXT3;
  477. components_ = 4;
  478. break;
  479. case 11:
  480. compressedFormat_ = CF_DXT5;
  481. components_ = 4;
  482. break;
  483. }
  484. if (compressedFormat_ == CF_NONE)
  485. {
  486. LOGERROR("Unsupported texture format in PVR file");
  487. return false;
  488. }
  489. source.Seek(source.GetPosition() + metaDataSize);
  490. unsigned dataSize = source.GetSize() - source.GetPosition();
  491. data_ = new unsigned char[dataSize];
  492. width_ = width;
  493. height_ = height;
  494. numCompressedLevels_ = mipmapCount;
  495. source.Read(data_.Get(), dataSize);
  496. SetMemoryUse(dataSize);
  497. }
  498. else
  499. {
  500. // Not DDS, KTX or PVR, use STBImage to load other image formats as uncompressed
  501. source.Seek(0);
  502. int width, height;
  503. unsigned components;
  504. unsigned char* pixelData = GetImageData(source, width, height, components);
  505. if (!pixelData)
  506. {
  507. LOGERROR("Could not load image " + source.GetName() + ": " + String(stbi_failure_reason()));
  508. return false;
  509. }
  510. SetSize(width, height, components);
  511. SetData(pixelData);
  512. FreeImageData(pixelData);
  513. }
  514. return true;
  515. }
  516. bool Image::Save(Serializer& dest) const
  517. {
  518. PROFILE(SaveImage);
  519. if (IsCompressed())
  520. {
  521. LOGERROR("Can not save compressed image " + GetName());
  522. return false;
  523. }
  524. if (!data_)
  525. {
  526. LOGERROR("Can not save zero-sized image " + GetName());
  527. return false;
  528. }
  529. int len;
  530. unsigned char *png = stbi_write_png_to_mem(data_.Get(), 0, width_, height_, components_, &len);
  531. bool success = dest.Write(png, len) == (unsigned)len;
  532. free(png);
  533. return success;
  534. }
  535. bool Image::SetSize(int width, int height, unsigned components)
  536. {
  537. return SetSize(width, height, 1, components);
  538. }
  539. bool Image::SetSize(int width, int height, int depth, unsigned components)
  540. {
  541. if (width == width_ && height == height_ && depth == depth_ && components == components_)
  542. return true;
  543. if (width <= 0 || height <= 0 || depth <= 0)
  544. return false;
  545. if (components > 4)
  546. {
  547. LOGERROR("More than 4 color components are not supported");
  548. return false;
  549. }
  550. data_ = new unsigned char[width * height * depth * components];
  551. width_ = width;
  552. height_ = height;
  553. depth_ = depth;
  554. components_ = components;
  555. compressedFormat_ = CF_NONE;
  556. numCompressedLevels_ = 0;
  557. nextLevel_.Reset();
  558. SetMemoryUse(width * height * depth * components);
  559. return true;
  560. }
  561. void Image::SetPixel(int x, int y, const Color& color)
  562. {
  563. SetPixelInt(x, y, 0, color.ToUInt());
  564. }
  565. void Image::SetPixel(int x, int y, int z, const Color& color)
  566. {
  567. SetPixelInt(x, y, z, color.ToUInt());
  568. }
  569. void Image::SetPixelInt(int x, int y, unsigned uintColor)
  570. {
  571. SetPixelInt(x, y, 0, uintColor);
  572. }
  573. void Image::SetPixelInt(int x, int y, int z, unsigned uintColor)
  574. {
  575. if (!data_ || x < 0 || x >= width_ || y < 0 || y >= height_ || z < 0 || z >= depth_ || IsCompressed())
  576. return;
  577. unsigned char* dest = data_ + (z * width_ * height_ + y * width_ + x) * components_;
  578. unsigned char* src = (unsigned char*)&uintColor;
  579. switch (components_)
  580. {
  581. case 4:
  582. dest[3] = src[3];
  583. // Fall through
  584. case 3:
  585. dest[2] = src[2];
  586. // Fall through
  587. case 2:
  588. dest[1]= src[1];
  589. // Fall through
  590. default:
  591. dest[0] = src[0];
  592. break;
  593. }
  594. }
  595. void Image::SetData(const unsigned char* pixelData)
  596. {
  597. if (!data_)
  598. return;
  599. if (IsCompressed())
  600. {
  601. LOGERROR("Can not set new pixel data for a compressed image");
  602. return;
  603. }
  604. memcpy(data_.Get(), pixelData, width_ * height_ * depth_ * components_);
  605. nextLevel_.Reset();
  606. }
  607. bool Image::LoadColorLUT(Deserializer& source)
  608. {
  609. String fileID = source.ReadFileID();
  610. if (fileID == "DDS " || fileID == "\253KTX" || fileID == "PVR\3")
  611. {
  612. LOGERROR("Invalid image format, can not load image");
  613. return false;
  614. }
  615. source.Seek(0);
  616. int width, height;
  617. unsigned components;
  618. unsigned char* pixelDataIn = GetImageData(source, width, height, components);
  619. if (!pixelDataIn)
  620. {
  621. LOGERROR("Could not load image " + source.GetName() + ": " + String(stbi_failure_reason()));
  622. return false;
  623. }
  624. if (components != 3)
  625. {
  626. LOGERROR("Invalid image format, can not load image");
  627. return false;
  628. }
  629. SetSize(COLOR_LUT_SIZE, COLOR_LUT_SIZE, COLOR_LUT_SIZE, components);
  630. SetMemoryUse(width_ * height_ * depth_ * components);
  631. unsigned char* pixelDataOut = GetData();
  632. for (int z = 0; z < depth_; ++z)
  633. {
  634. for (int y = 0; y < height_; ++y)
  635. {
  636. unsigned char* in = &pixelDataIn[z * width_ * 3 + y * width * 3];
  637. unsigned char* out = &pixelDataOut[z * width_ * height_ * 3 + y * width_ * 3];
  638. for (int x = 0; x < width_ * 3; x += 3)
  639. {
  640. out[x] = in[x];
  641. out[x+1] = in[x + 1];
  642. out[x+2] = in[x + 2];
  643. }
  644. }
  645. }
  646. FreeImageData(pixelDataIn);
  647. return true;
  648. }
  649. bool Image::FlipHorizontal()
  650. {
  651. if (!data_)
  652. return false;
  653. if (depth_ > 1)
  654. {
  655. LOGERROR("FlipHorizontal not supported for 3D images");
  656. return false;
  657. }
  658. if (!IsCompressed())
  659. {
  660. SharedArrayPtr<unsigned char> newData(new unsigned char[width_ * height_ * components_]);
  661. unsigned rowSize = width_ * components_;
  662. for (int y = 0; y < height_; ++y)
  663. {
  664. for (int x = 0; x < width_; ++x)
  665. {
  666. for (unsigned c = 0; c < components_; ++c)
  667. newData[y * rowSize + x * components_ + c] = data_[y * rowSize + (width_ - x - 1) * components_ + c];
  668. }
  669. }
  670. data_ = newData;
  671. }
  672. else
  673. {
  674. if (compressedFormat_ > CF_DXT5)
  675. {
  676. LOGERROR("FlipHorizontal not yet implemented for other compressed formats than RGBA & DXT1,3,5");
  677. return false;
  678. }
  679. // Memory use = combined size of the compressed mip levels
  680. SharedArrayPtr<unsigned char> newData(new unsigned char[GetMemoryUse()]);
  681. unsigned dataOffset = 0;
  682. for (unsigned i = 0; i < numCompressedLevels_; ++i)
  683. {
  684. CompressedLevel level = GetCompressedLevel(i);
  685. if (!level.data_)
  686. {
  687. LOGERROR("Got compressed level with no data, aborting horizontal flip");
  688. return false;
  689. }
  690. for (unsigned y = 0; y < level.rows_; ++y)
  691. {
  692. for (unsigned x = 0; x < level.rowSize_; x += level.blockSize_)
  693. {
  694. unsigned char* src = level.data_ + y * level.rowSize_ + (level.rowSize_ - level.blockSize_ - x);
  695. unsigned char* dest = newData.Get() + y * level.rowSize_ + x;
  696. FlipBlockHorizontal(dest, src, compressedFormat_);
  697. }
  698. }
  699. dataOffset += level.dataSize_;
  700. }
  701. data_ = newData;
  702. }
  703. return true;
  704. }
  705. bool Image::FlipVertical()
  706. {
  707. if (!data_)
  708. return false;
  709. if (depth_ > 1)
  710. {
  711. LOGERROR("FlipVertical not supported for 3D images");
  712. return false;
  713. }
  714. if (!IsCompressed())
  715. {
  716. SharedArrayPtr<unsigned char> newData(new unsigned char[width_ * height_ * components_]);
  717. unsigned rowSize = width_ * components_;
  718. for (int y = 0; y < height_; ++y)
  719. memcpy(&newData[(height_ - y - 1) * rowSize], &data_[y * rowSize], rowSize);
  720. data_ = newData;
  721. }
  722. else
  723. {
  724. if (compressedFormat_ > CF_DXT5)
  725. {
  726. LOGERROR("FlipVertical not yet implemented for other compressed formats than DXT1,3,5");
  727. return false;
  728. }
  729. // Memory use = combined size of the compressed mip levels
  730. SharedArrayPtr<unsigned char> newData(new unsigned char[GetMemoryUse()]);
  731. unsigned dataOffset = 0;
  732. for (unsigned i = 0; i < numCompressedLevels_; ++i)
  733. {
  734. CompressedLevel level = GetCompressedLevel(i);
  735. if (!level.data_)
  736. {
  737. LOGERROR("Got compressed level with no data, aborting vertical flip");
  738. return false;
  739. }
  740. for (unsigned y = 0; y < level.rows_; ++y)
  741. {
  742. unsigned char* src = level.data_ + y * level.rowSize_;
  743. unsigned char* dest = newData.Get() + dataOffset + (level.rows_ - y - 1) * level.rowSize_;
  744. for (unsigned x = 0; x < level.rowSize_; x += level.blockSize_)
  745. FlipBlockVertical(dest + x, src + x, compressedFormat_);
  746. }
  747. dataOffset += level.dataSize_;
  748. }
  749. data_ = newData;
  750. }
  751. return true;
  752. }
  753. bool Image::Resize(int width, int height)
  754. {
  755. PROFILE(ResizeImage);
  756. if (IsCompressed())
  757. {
  758. LOGERROR("Resize not supported for compressed images");
  759. return false;
  760. }
  761. if (depth_ > 1)
  762. {
  763. LOGERROR("Resize not supported for 3D images");
  764. return false;
  765. }
  766. if (!data_ || width <= 0 || height <= 0)
  767. return false;
  768. /// \todo Reducing image size does not sample all needed pixels
  769. SharedArrayPtr<unsigned char> newData(new unsigned char[width * height * components_]);
  770. for (int y = 0; y < height; ++y)
  771. {
  772. for (int x = 0; x < width; ++x)
  773. {
  774. // Calculate float coordinates between 0 - 1 for resampling
  775. float xF = (width_ > 1) ? (float)x / (float)(width - 1) : 0.0f;
  776. float yF = (height_ > 1) ? (float)y / (float)(height - 1) : 0.0f;
  777. unsigned uintColor = GetPixelBilinear(xF, yF).ToUInt();
  778. unsigned char* dest = newData + (y * width + x) * components_;
  779. unsigned char* src = (unsigned char*)&uintColor;
  780. switch (components_)
  781. {
  782. case 4:
  783. dest[3] = src[3];
  784. // Fall through
  785. case 3:
  786. dest[2] = src[2];
  787. // Fall through
  788. case 2:
  789. dest[1] = src[1];
  790. // Fall through
  791. default:
  792. dest[0] = src[0];
  793. break;
  794. }
  795. }
  796. }
  797. width_ = width;
  798. height_ = height;
  799. data_ = newData;
  800. SetMemoryUse(width * height * depth_ * components_);
  801. return true;
  802. }
  803. void Image::Clear(const Color& color)
  804. {
  805. ClearInt(color.ToUInt());
  806. }
  807. void Image::ClearInt(unsigned uintColor)
  808. {
  809. PROFILE(ClearImage);
  810. if (!data_)
  811. return;
  812. if (IsCompressed())
  813. {
  814. LOGERROR("Clear not supported for compressed images");
  815. return;
  816. }
  817. unsigned char* src = (unsigned char*)&uintColor;
  818. for (unsigned i = 0; i < width_ * height_ * depth_ * components_; ++i)
  819. data_[i] = src[i % components_];
  820. }
  821. bool Image::SaveBMP(const String& fileName) const
  822. {
  823. PROFILE(SaveImageBMP);
  824. FileSystem* fileSystem = GetSubsystem<FileSystem>();
  825. if (fileSystem && !fileSystem->CheckAccess(GetPath(fileName)))
  826. {
  827. LOGERROR("Access denied to " + fileName);
  828. return false;
  829. }
  830. if (IsCompressed())
  831. {
  832. LOGERROR("Can not save compressed image to BMP");
  833. return false;
  834. }
  835. if (data_)
  836. return stbi_write_bmp(fileName.CString(), width_, height_, components_, data_.Get()) != 0;
  837. else
  838. return false;
  839. }
  840. bool Image::SavePNG(const String& fileName) const
  841. {
  842. PROFILE(SaveImagePNG);
  843. FileSystem* fileSystem = GetSubsystem<FileSystem>();
  844. if (fileSystem && !fileSystem->CheckAccess(GetPath(fileName)))
  845. {
  846. LOGERROR("Access denied to " + fileName);
  847. return false;
  848. }
  849. if (IsCompressed())
  850. {
  851. LOGERROR("Can not save compressed image to PNG");
  852. return false;
  853. }
  854. if (data_)
  855. return stbi_write_png(GetNativePath(fileName).CString(), width_, height_, components_, data_.Get(), 0) != 0;
  856. else
  857. return false;
  858. }
  859. bool Image::SaveTGA(const String& fileName) const
  860. {
  861. PROFILE(SaveImageTGA);
  862. FileSystem* fileSystem = GetSubsystem<FileSystem>();
  863. if (fileSystem && !fileSystem->CheckAccess(GetPath(fileName)))
  864. {
  865. LOGERROR("Access denied to " + fileName);
  866. return false;
  867. }
  868. if (IsCompressed())
  869. {
  870. LOGERROR("Can not save compressed image to TGA");
  871. return false;
  872. }
  873. if (data_)
  874. return stbi_write_tga(GetNativePath(fileName).CString(), width_, height_, components_, data_.Get()) != 0;
  875. else
  876. return false;
  877. }
  878. bool Image::SaveJPG(const String & fileName, int quality) const
  879. {
  880. PROFILE(SaveImageJPG);
  881. FileSystem* fileSystem = GetSubsystem<FileSystem>();
  882. if (fileSystem && !fileSystem->CheckAccess(GetPath(fileName)))
  883. {
  884. LOGERROR("Access denied to " + fileName);
  885. return false;
  886. }
  887. if (IsCompressed())
  888. {
  889. LOGERROR("Can not save compressed image to JPG");
  890. return false;
  891. }
  892. if (data_)
  893. return jo_write_jpg(GetNativePath(fileName).CString(), data_.Get(), width_, height_, components_, quality) != 0;
  894. else
  895. return false;
  896. }
  897. Color Image::GetPixel(int x, int y) const
  898. {
  899. return GetPixel(x, y, 0);
  900. }
  901. Color Image::GetPixel(int x, int y, int z) const
  902. {
  903. if (!data_ || z < 0 || z >= depth_ || IsCompressed())
  904. return Color::BLACK;
  905. x = Clamp(x, 0, width_ - 1);
  906. y = Clamp(y, 0, height_ - 1);
  907. unsigned char* src = data_ + (z * width_ * height_ + y * width_ + x) * components_;
  908. Color ret;
  909. switch (components_)
  910. {
  911. case 4:
  912. ret.a_ = (float)src[3] / 255.0f;
  913. // Fall through
  914. case 3:
  915. ret.b_ = (float)src[2] / 255.0f;
  916. // Fall through
  917. case 2:
  918. ret.g_ = (float)src[1] / 255.0f;
  919. ret.r_ = (float)src[0] / 255.0f;
  920. break;
  921. default:
  922. ret.r_ = ret.g_ = ret.b_ = (float)src[0] / 255.0f;
  923. break;
  924. }
  925. return ret;
  926. }
  927. unsigned Image::GetPixelInt(int x, int y) const
  928. {
  929. return GetPixelInt(x, y, 0);
  930. }
  931. unsigned Image::GetPixelInt(int x, int y, int z) const
  932. {
  933. if (!data_ || z < 0 || z >= depth_ || IsCompressed())
  934. return 0xff000000;
  935. x = Clamp(x, 0, width_ - 1);
  936. y = Clamp(y, 0, height_ - 1);
  937. unsigned char* src = data_ + (z * width_ * height_ + y * width_ + x) * components_;
  938. unsigned ret = 0;
  939. if (components_ < 4)
  940. ret |= 0xff000000;
  941. switch (components_)
  942. {
  943. case 4:
  944. ret |= (unsigned)src[3] << 24;
  945. // Fall through
  946. case 3:
  947. ret |= (unsigned)src[2] << 16;
  948. // Fall through
  949. case 2:
  950. ret |= (unsigned)src[1] << 8;
  951. ret |= (unsigned)src[0];
  952. break;
  953. default:
  954. ret |= (unsigned)src[0] << 16;
  955. ret |= (unsigned)src[0] << 8;
  956. ret |= (unsigned)src[0];
  957. break;
  958. }
  959. return ret;
  960. }
  961. Color Image::GetPixelBilinear(float x, float y) const
  962. {
  963. x = Clamp(x * width_ - 0.5f, 0.0f, (float)(width_ - 1));
  964. y = Clamp(y * height_ - 0.5f, 0.0f, (float)(height_ - 1));
  965. int xI = (int)x;
  966. int yI = (int)y;
  967. float xF = x - floorf(x);
  968. float yF = y - floorf(y);
  969. Color topColor = GetPixel(xI, yI).Lerp(GetPixel(xI + 1, yI), xF);
  970. Color bottomColor = GetPixel(xI, yI + 1).Lerp(GetPixel(xI + 1, yI + 1), xF);
  971. return topColor.Lerp(bottomColor, yF);
  972. }
  973. Color Image::GetPixelTrilinear(float x, float y, float z) const
  974. {
  975. if (depth_ < 2)
  976. return GetPixelBilinear(x, y);
  977. x = Clamp(x * width_ - 0.5f, 0.0f, (float)(width_ - 1));
  978. y = Clamp(y * height_ - 0.5f, 0.0f, (float)(height_ - 1));
  979. z = Clamp(z * depth_ - 0.5f, 0.0f, (float)(depth_ - 1));
  980. int xI = (int)x;
  981. int yI = (int)y;
  982. int zI = (int)z;
  983. if (zI == depth_ - 1)
  984. return GetPixelBilinear(x, y);
  985. float xF = x - floorf(x);
  986. float yF = y - floorf(y);
  987. float zF = z - floorf(z);
  988. Color topColorNear = GetPixel(xI, yI, zI).Lerp(GetPixel(xI + 1, yI, zI), xF);
  989. Color bottomColorNear = GetPixel(xI, yI + 1, zI).Lerp(GetPixel(xI + 1, yI + 1, zI), xF);
  990. Color colorNear = topColorNear.Lerp(bottomColorNear, yF);
  991. Color topColorFar = GetPixel(xI, yI, zI + 1).Lerp(GetPixel(xI + 1, yI, zI + 1), xF);
  992. Color bottomColorFar = GetPixel(xI, yI + 1, zI + 1).Lerp(GetPixel(xI + 1, yI + 1, zI + 1), xF);
  993. Color colorFar = topColorFar.Lerp(bottomColorFar, yF);
  994. return colorNear.Lerp(colorFar, zF);
  995. }
  996. SharedPtr<Image> Image::GetNextLevel() const
  997. {
  998. if (IsCompressed())
  999. {
  1000. LOGERROR("Can not generate mip level from compressed data");
  1001. return SharedPtr<Image>();
  1002. }
  1003. if (components_ < 1 || components_ > 4)
  1004. {
  1005. LOGERROR("Illegal number of image components for mip level generation");
  1006. return SharedPtr<Image>();
  1007. }
  1008. if (nextLevel_)
  1009. return nextLevel_;
  1010. PROFILE(CalculateImageMipLevel);
  1011. int widthOut = width_ / 2;
  1012. int heightOut = height_ / 2;
  1013. int depthOut = depth_ / 2;
  1014. if (widthOut < 1)
  1015. widthOut = 1;
  1016. if (heightOut < 1)
  1017. heightOut = 1;
  1018. if (depthOut < 1)
  1019. depthOut = 1;
  1020. SharedPtr<Image> mipImage(new Image(context_));
  1021. if (depth_ > 1)
  1022. mipImage->SetSize(widthOut, heightOut, depthOut, components_);
  1023. else
  1024. mipImage->SetSize(widthOut, heightOut, components_);
  1025. const unsigned char* pixelDataIn = data_.Get();
  1026. unsigned char* pixelDataOut = mipImage->data_.Get();
  1027. // 1D case
  1028. if (depth_ == 1 && (height_ == 1 || width_ == 1))
  1029. {
  1030. // Loop using the larger dimension
  1031. if (widthOut < heightOut)
  1032. widthOut = heightOut;
  1033. switch (components_)
  1034. {
  1035. case 1:
  1036. for (int x = 0; x < widthOut; ++x)
  1037. pixelDataOut[x] = ((unsigned)pixelDataIn[x*2] + pixelDataIn[x*2+1]) >> 1;
  1038. break;
  1039. case 2:
  1040. for (int x = 0; x < widthOut*2; x += 2)
  1041. {
  1042. pixelDataOut[x] = ((unsigned)pixelDataIn[x*2] + pixelDataIn[x*2+2]) >> 1;
  1043. pixelDataOut[x+1] = ((unsigned)pixelDataIn[x*2+1] + pixelDataIn[x*2+3]) >> 1;
  1044. }
  1045. break;
  1046. case 3:
  1047. for (int x = 0; x < widthOut*3; x += 3)
  1048. {
  1049. pixelDataOut[x] = ((unsigned)pixelDataIn[x*2] + pixelDataIn[x*2+3]) >> 1;
  1050. pixelDataOut[x+1] = ((unsigned)pixelDataIn[x*2+1] + pixelDataIn[x*2+4]) >> 1;
  1051. pixelDataOut[x+2] = ((unsigned)pixelDataIn[x*2+2] + pixelDataIn[x*2+5]) >> 1;
  1052. }
  1053. break;
  1054. case 4:
  1055. for (int x = 0; x < widthOut*4; x += 4)
  1056. {
  1057. pixelDataOut[x] = ((unsigned)pixelDataIn[x*2] + pixelDataIn[x*2+4]) >> 1;
  1058. pixelDataOut[x+1] = ((unsigned)pixelDataIn[x*2+1] + pixelDataIn[x*2+5]) >> 1;
  1059. pixelDataOut[x+2] = ((unsigned)pixelDataIn[x*2+2] + pixelDataIn[x*2+6]) >> 1;
  1060. pixelDataOut[x+3] = ((unsigned)pixelDataIn[x*2+3] + pixelDataIn[x*2+7]) >> 1;
  1061. }
  1062. break;
  1063. }
  1064. }
  1065. // 2D case
  1066. else if (depth_ == 1)
  1067. {
  1068. switch (components_)
  1069. {
  1070. case 1:
  1071. for (int y = 0; y < heightOut; ++y)
  1072. {
  1073. const unsigned char* inUpper = &pixelDataIn[(y*2)*width_];
  1074. const unsigned char* inLower = &pixelDataIn[(y*2+1)*width_];
  1075. unsigned char* out = &pixelDataOut[y*widthOut];
  1076. for (int x = 0; x < widthOut; ++x)
  1077. {
  1078. out[x] = ((unsigned)inUpper[x*2] + inUpper[x*2+1] + inLower[x*2] + inLower[x*2+1]) >> 2;
  1079. }
  1080. }
  1081. break;
  1082. case 2:
  1083. for (int y = 0; y < heightOut; ++y)
  1084. {
  1085. const unsigned char* inUpper = &pixelDataIn[(y*2)*width_*2];
  1086. const unsigned char* inLower = &pixelDataIn[(y*2+1)*width_*2];
  1087. unsigned char* out = &pixelDataOut[y*widthOut*2];
  1088. for (int x = 0; x < widthOut*2; x += 2)
  1089. {
  1090. out[x] = ((unsigned)inUpper[x*2] + inUpper[x*2+2] + inLower[x*2] + inLower[x*2+2]) >> 2;
  1091. out[x+1] = ((unsigned)inUpper[x*2+1] + inUpper[x*2+3] + inLower[x*2+1] + inLower[x*2+3]) >> 2;
  1092. }
  1093. }
  1094. break;
  1095. case 3:
  1096. for (int y = 0; y < heightOut; ++y)
  1097. {
  1098. const unsigned char* inUpper = &pixelDataIn[(y*2)*width_*3];
  1099. const unsigned char* inLower = &pixelDataIn[(y*2+1)*width_*3];
  1100. unsigned char* out = &pixelDataOut[y*widthOut*3];
  1101. for (int x = 0; x < widthOut*3; x += 3)
  1102. {
  1103. out[x] = ((unsigned)inUpper[x*2] + inUpper[x*2+3] + inLower[x*2] + inLower[x*2+3]) >> 2;
  1104. out[x+1] = ((unsigned)inUpper[x*2+1] + inUpper[x*2+4] + inLower[x*2+1] + inLower[x*2+4]) >> 2;
  1105. out[x+2] = ((unsigned)inUpper[x*2+2] + inUpper[x*2+5] + inLower[x*2+2] + inLower[x*2+5]) >> 2;
  1106. }
  1107. }
  1108. break;
  1109. case 4:
  1110. for (int y = 0; y < heightOut; ++y)
  1111. {
  1112. const unsigned char* inUpper = &pixelDataIn[(y*2)*width_*4];
  1113. const unsigned char* inLower = &pixelDataIn[(y*2+1)*width_*4];
  1114. unsigned char* out = &pixelDataOut[y*widthOut*4];
  1115. for (int x = 0; x < widthOut*4; x += 4)
  1116. {
  1117. out[x] = ((unsigned)inUpper[x*2] + inUpper[x*2+4] + inLower[x*2] + inLower[x*2+4]) >> 2;
  1118. out[x+1] = ((unsigned)inUpper[x*2+1] + inUpper[x*2+5] + inLower[x*2+1] + inLower[x*2+5]) >> 2;
  1119. out[x+2] = ((unsigned)inUpper[x*2+2] + inUpper[x*2+6] + inLower[x*2+2] + inLower[x*2+6]) >> 2;
  1120. out[x+3] = ((unsigned)inUpper[x*2+3] + inUpper[x*2+7] + inLower[x*2+3] + inLower[x*2+7]) >> 2;
  1121. }
  1122. }
  1123. break;
  1124. }
  1125. }
  1126. // 3D case
  1127. else
  1128. {
  1129. switch (components_)
  1130. {
  1131. case 1:
  1132. for (int z = 0; z < depthOut; ++z)
  1133. {
  1134. const unsigned char* inOuter = &pixelDataIn[(z*2)*width_*height_];
  1135. const unsigned char* inInner = &pixelDataIn[(z*2+1)*width_*height_];
  1136. for (int y = 0; y < heightOut; ++y)
  1137. {
  1138. const unsigned char* inOuterUpper = &inOuter[(y*2)*width_];
  1139. const unsigned char* inOuterLower = &inOuter[(y*2+1)*width_];
  1140. const unsigned char* inInnerUpper = &inInner[(y*2)*width_];
  1141. const unsigned char* inInnerLower = &inInner[(y*2+1)*width_];
  1142. unsigned char* out = &pixelDataOut[z*widthOut*heightOut + y*widthOut];
  1143. for (int x = 0; x < widthOut; ++x)
  1144. {
  1145. out[x] = ((unsigned)inOuterUpper[x*2] + inOuterUpper[x*2+1] + inOuterLower[x*2] + inOuterLower[x*2+1] +
  1146. inInnerUpper[x*2] + inInnerUpper[x*2+1] + inInnerLower[x*2] + inInnerLower[x*2+1]) >> 3;
  1147. }
  1148. }
  1149. }
  1150. break;
  1151. case 2:
  1152. for (int z = 0; z < depthOut; ++z)
  1153. {
  1154. const unsigned char* inOuter = &pixelDataIn[(z*2)*width_*height_*2];
  1155. const unsigned char* inInner = &pixelDataIn[(z*2+1)*width_*height_*2];
  1156. for (int y = 0; y < heightOut; ++y)
  1157. {
  1158. const unsigned char* inOuterUpper = &inOuter[(y*2)*width_*2];
  1159. const unsigned char* inOuterLower = &inOuter[(y*2+1)*width_*2];
  1160. const unsigned char* inInnerUpper = &inInner[(y*2)*width_*2];
  1161. const unsigned char* inInnerLower = &inInner[(y*2+1)*width_*2];
  1162. unsigned char* out = &pixelDataOut[z*widthOut*heightOut*2 + y*widthOut*2];
  1163. for (int x = 0; x < widthOut*2; x += 2)
  1164. {
  1165. out[x] = ((unsigned)inOuterUpper[x*2] + inOuterUpper[x*2+2] + inOuterLower[x*2] + inOuterLower[x*2+2] +
  1166. inInnerUpper[x*2] + inInnerUpper[x*2+2] + inInnerLower[x*2] + inInnerLower[x*2+2]) >> 3;
  1167. out[x+1] = ((unsigned)inOuterUpper[x*2+1] + inOuterUpper[x*2+3] + inOuterLower[x*2+1] + inOuterLower[x*2+3] +
  1168. inInnerUpper[x*2+1] + inInnerUpper[x*2+3] + inInnerLower[x*2+1] + inInnerLower[x*2+3]) >> 3;
  1169. }
  1170. }
  1171. }
  1172. break;
  1173. case 3:
  1174. for (int z = 0; z < depthOut; ++z)
  1175. {
  1176. const unsigned char* inOuter = &pixelDataIn[(z*2)*width_*height_*3];
  1177. const unsigned char* inInner = &pixelDataIn[(z*2+1)*width_*height_*3];
  1178. for (int y = 0; y < heightOut; ++y)
  1179. {
  1180. const unsigned char* inOuterUpper = &inOuter[(y*2)*width_*3];
  1181. const unsigned char* inOuterLower = &inOuter[(y*2+1)*width_*3];
  1182. const unsigned char* inInnerUpper = &inInner[(y*2)*width_*3];
  1183. const unsigned char* inInnerLower = &inInner[(y*2+1)*width_*3];
  1184. unsigned char* out = &pixelDataOut[z*widthOut*heightOut*3 + y*widthOut*3];
  1185. for (int x = 0; x < widthOut*3; x += 3)
  1186. {
  1187. out[x] = ((unsigned)inOuterUpper[x*2] + inOuterUpper[x*2+3] + inOuterLower[x*2] + inOuterLower[x*2+3] +
  1188. inInnerUpper[x*2] + inInnerUpper[x*2+3] + inInnerLower[x*2] + inInnerLower[x*2+3]) >> 3;
  1189. out[x+1] = ((unsigned)inOuterUpper[x*2+1] + inOuterUpper[x*2+4] + inOuterLower[x*2+1] + inOuterLower[x*2+4] +
  1190. inInnerUpper[x*2+1] + inInnerUpper[x*2+4] + inInnerLower[x*2+1] + inInnerLower[x*2+4]) >> 3;
  1191. out[x+2] = ((unsigned)inOuterUpper[x*2+2] + inOuterUpper[x*2+5] + inOuterLower[x*2+2] + inOuterLower[x*2+5] +
  1192. inInnerUpper[x*2+2] + inInnerUpper[x*2+5] + inInnerLower[x*2+2] + inInnerLower[x*2+5]) >> 3;
  1193. }
  1194. }
  1195. }
  1196. break;
  1197. case 4:
  1198. for (int z = 0; z < depthOut; ++z)
  1199. {
  1200. const unsigned char* inOuter = &pixelDataIn[(z*2)*width_*height_*4];
  1201. const unsigned char* inInner = &pixelDataIn[(z*2+1)*width_*height_*4];
  1202. for (int y = 0; y < heightOut; ++y)
  1203. {
  1204. const unsigned char* inOuterUpper = &inOuter[(y*2)*width_*4];
  1205. const unsigned char* inOuterLower = &inOuter[(y*2+1)*width_*4];
  1206. const unsigned char* inInnerUpper = &inInner[(y*2)*width_*4];
  1207. const unsigned char* inInnerLower = &inInner[(y*2+1)*width_*4];
  1208. unsigned char* out = &pixelDataOut[z*widthOut*heightOut*4 + y*widthOut*4];
  1209. for (int x = 0; x < widthOut*4; x += 4)
  1210. {
  1211. out[x] = ((unsigned)inOuterUpper[x*2] + inOuterUpper[x*2+4] + inOuterLower[x*2] + inOuterLower[x*2+4] +
  1212. inInnerUpper[x*2] + inInnerUpper[x*2+4] + inInnerLower[x*2] + inInnerLower[x*2+4]) >> 3;
  1213. out[x+1] = ((unsigned)inOuterUpper[x*2+1] + inOuterUpper[x*2+5] + inOuterLower[x*2+1] + inOuterLower[x*2+5] +
  1214. inInnerUpper[x*2+1] + inInnerUpper[x*2+5] + inInnerLower[x*2+1] + inInnerLower[x*2+5]) >> 3;
  1215. out[x+2] = ((unsigned)inOuterUpper[x*2+2] + inOuterUpper[x*2+6] + inOuterLower[x*2+2] + inOuterLower[x*2+6] +
  1216. inInnerUpper[x*2+2] + inInnerUpper[x*2+6] + inInnerLower[x*2+2] + inInnerLower[x*2+6]) >> 3;
  1217. }
  1218. }
  1219. }
  1220. break;
  1221. }
  1222. }
  1223. return mipImage;
  1224. }
  1225. SharedPtr<Image> Image::ConvertToRGBA() const
  1226. {
  1227. if (IsCompressed())
  1228. {
  1229. LOGERROR("Can not convert compressed image to RGBA");
  1230. return SharedPtr<Image>();
  1231. }
  1232. if (components_ < 1 || components_ > 4)
  1233. {
  1234. LOGERROR("Illegal number of image components for conversion to RGBA");
  1235. return SharedPtr<Image>();
  1236. }
  1237. if (!data_)
  1238. {
  1239. LOGERROR("Can not convert image without data to RGBA");
  1240. return SharedPtr<Image>();
  1241. }
  1242. // Already RGBA?
  1243. if (components_ == 4)
  1244. return SharedPtr<Image>(const_cast<Image*>(this));
  1245. SharedPtr<Image> ret(new Image(context_));
  1246. ret->SetSize(width_, height_, depth_, 4);
  1247. const unsigned char* src = data_;
  1248. unsigned char* dest = ret->GetData();
  1249. switch (components_)
  1250. {
  1251. case 1:
  1252. for (unsigned i = 0; i < width_ * height_ * depth_; ++i)
  1253. {
  1254. unsigned char pixel = *src++;
  1255. *dest++ = pixel;
  1256. *dest++ = pixel;
  1257. *dest++ = pixel;
  1258. *dest++ = 255;
  1259. }
  1260. break;
  1261. case 2:
  1262. for (unsigned i = 0; i < width_ * height_ * depth_; ++i)
  1263. {
  1264. unsigned char pixel = *src++;
  1265. *dest++ = pixel;
  1266. *dest++ = pixel;
  1267. *dest++ = pixel;
  1268. *dest++ = *src++;
  1269. }
  1270. break;
  1271. case 3:
  1272. for (unsigned i = 0; i < width_ * height_ * depth_; ++i)
  1273. {
  1274. *dest++ = *src++;
  1275. *dest++ = *src++;
  1276. *dest++ = *src++;
  1277. *dest++ = 255;
  1278. }
  1279. break;
  1280. }
  1281. return ret;
  1282. }
  1283. CompressedLevel Image::GetCompressedLevel(unsigned index) const
  1284. {
  1285. CompressedLevel level;
  1286. if (compressedFormat_ == CF_NONE)
  1287. {
  1288. LOGERROR("Image is not compressed");
  1289. return level;
  1290. }
  1291. if (index >= numCompressedLevels_)
  1292. {
  1293. LOGERROR("Compressed image mip level out of bounds");
  1294. return level;
  1295. }
  1296. level.format_ = compressedFormat_;
  1297. level.width_ = width_;
  1298. level.height_ = height_;
  1299. level.depth_ = depth_;
  1300. if (compressedFormat_ == CF_RGBA)
  1301. {
  1302. level.blockSize_ = 4;
  1303. unsigned i = 0;
  1304. unsigned offset = 0;
  1305. for (;;)
  1306. {
  1307. if (!level.width_)
  1308. level.width_ = 1;
  1309. if (!level.height_)
  1310. level.height_ = 1;
  1311. if (!level.depth_)
  1312. level.depth_ = 1;
  1313. level.rowSize_ = level.width_ * level.blockSize_;
  1314. level.rows_ = level.height_;
  1315. level.data_ = data_.Get() + offset;
  1316. level.dataSize_ = level.depth_ * level.rows_ * level.rowSize_;
  1317. if (offset + level.dataSize_ > GetMemoryUse())
  1318. {
  1319. LOGERROR("Compressed level is outside image data. Offset: " + String(offset) + " Size: " + String(level.dataSize_) +
  1320. " Datasize: " + String(GetMemoryUse()));
  1321. level.data_ = 0;
  1322. return level;
  1323. }
  1324. if (i == index)
  1325. return level;
  1326. offset += level.dataSize_;
  1327. level.width_ /= 2;
  1328. level.height_ /= 2;
  1329. level.depth_ /= 2;
  1330. ++i;
  1331. }
  1332. }
  1333. else if (compressedFormat_ < CF_PVRTC_RGB_2BPP)
  1334. {
  1335. level.blockSize_ = (compressedFormat_ == CF_DXT1 || compressedFormat_ == CF_ETC1) ? 8 : 16;
  1336. unsigned i = 0;
  1337. unsigned offset = 0;
  1338. for (;;)
  1339. {
  1340. if (!level.width_)
  1341. level.width_ = 1;
  1342. if (!level.height_)
  1343. level.height_ = 1;
  1344. if (!level.depth_)
  1345. level.depth_ = 1;
  1346. level.rowSize_ = ((level.width_ + 3) / 4) * level.blockSize_;
  1347. level.rows_ = ((level.height_ + 3) / 4);
  1348. level.data_ = data_.Get() + offset;
  1349. level.dataSize_ = level.depth_ * level.rows_ * level.rowSize_;
  1350. if (offset + level.dataSize_ > GetMemoryUse())
  1351. {
  1352. LOGERROR("Compressed level is outside image data. Offset: " + String(offset) + " Size: " + String(level.dataSize_) +
  1353. " Datasize: " + String(GetMemoryUse()));
  1354. level.data_ = 0;
  1355. return level;
  1356. }
  1357. if (i == index)
  1358. return level;
  1359. offset += level.dataSize_;
  1360. level.width_ /= 2;
  1361. level.height_ /= 2;
  1362. level.depth_ /= 2;
  1363. ++i;
  1364. }
  1365. }
  1366. else
  1367. {
  1368. level.blockSize_ = compressedFormat_ < CF_PVRTC_RGB_4BPP ? 2 : 4;
  1369. unsigned i = 0;
  1370. unsigned offset = 0;
  1371. for (;;)
  1372. {
  1373. if (!level.width_)
  1374. level.width_ = 1;
  1375. if (!level.height_)
  1376. level.height_ = 1;
  1377. int dataWidth = Max(level.width_, level.blockSize_ == 2 ? 16 : 8);
  1378. int dataHeight = Max(level.height_, 8);
  1379. level.data_ = data_.Get() + offset;
  1380. level.dataSize_ = (dataWidth * dataHeight * level.blockSize_ + 7) >> 3;
  1381. level.rows_ = dataHeight;
  1382. level.rowSize_ = level.dataSize_ / level.rows_;
  1383. if (offset + level.dataSize_ > GetMemoryUse())
  1384. {
  1385. LOGERROR("Compressed level is outside image data. Offset: " + String(offset) + " Size: " + String(level.dataSize_) +
  1386. " Datasize: " + String(GetMemoryUse()));
  1387. level.data_ = 0;
  1388. return level;
  1389. }
  1390. if (i == index)
  1391. return level;
  1392. offset += level.dataSize_;
  1393. level.width_ /= 2;
  1394. level.height_ /= 2;
  1395. ++i;
  1396. }
  1397. }
  1398. }
  1399. Image* Image::GetSubimage(const IntRect& rect) const
  1400. {
  1401. if (!data_)
  1402. return 0;
  1403. if (depth_ > 1)
  1404. {
  1405. LOGERROR("Subimage not supported for 3D images");
  1406. return 0;
  1407. }
  1408. if (rect.left_ < 0 || rect.top_ < 0 || rect.right_ > width_ || rect.bottom_ > height_ || !rect.Width() || !rect.Height())
  1409. {
  1410. LOGERROR("Can not get subimage from image " + GetName() + " with invalid region");
  1411. return 0;
  1412. }
  1413. if (!IsCompressed())
  1414. {
  1415. int x = rect.left_;
  1416. int y = rect.top_;
  1417. int width = rect.Width();
  1418. int height = rect.Height();
  1419. Image* image = new Image(context_);
  1420. image->SetSize(width, height, components_);
  1421. unsigned char* dest = image->GetData();
  1422. unsigned char* src = data_.Get() + (y * width_ + x) * components_;
  1423. for (int i = 0; i < height; ++i)
  1424. {
  1425. memcpy(dest, src, width * components_);
  1426. dest += width * components_;
  1427. src += width_ * components_;
  1428. }
  1429. return image;
  1430. }
  1431. else
  1432. {
  1433. // Pad the region to be a multiple of block size
  1434. IntRect paddedRect = rect;
  1435. paddedRect.left_ = (rect.left_ / 4) * 4;
  1436. paddedRect.top_ = (rect.top_ / 4) * 4;
  1437. paddedRect.right_ = (rect.right_ / 4) * 4;
  1438. paddedRect.bottom_ = (rect.bottom_ / 4) * 4;
  1439. IntRect currentRect = paddedRect;
  1440. PODVector<unsigned char> subimageData;
  1441. unsigned subimageLevels = 0;
  1442. // Save as many mips as possible until the next mip would cross a block boundary
  1443. for (unsigned i = 0; i < numCompressedLevels_; ++i)
  1444. {
  1445. CompressedLevel level = GetCompressedLevel(i);
  1446. if (!level.data_)
  1447. break;
  1448. // Mips are stored continuously
  1449. unsigned destStartOffset = subimageData.Size();
  1450. unsigned destRowSize = currentRect.Width() / 4 * level.blockSize_;
  1451. unsigned destSize = currentRect.Height() / 4 * destRowSize;
  1452. if (!destSize)
  1453. break;
  1454. subimageData.Resize(destStartOffset + destSize);
  1455. unsigned char* dest = &subimageData[destStartOffset];
  1456. for (int y = currentRect.top_; y < currentRect.bottom_; y += 4)
  1457. {
  1458. unsigned char* src = level.data_ + level.rowSize_ * (y / 4) + currentRect.left_ / 4 * level.blockSize_;
  1459. memcpy(dest, src, destRowSize);
  1460. dest += destRowSize;
  1461. }
  1462. ++subimageLevels;
  1463. if ((currentRect.left_ & 4) || (currentRect.right_ & 4) || (currentRect.top_ & 4) || (currentRect.bottom_ & 4))
  1464. break;
  1465. else
  1466. {
  1467. currentRect.left_ /= 2;
  1468. currentRect.right_ /= 2;
  1469. currentRect.top_ /= 2;
  1470. currentRect.bottom_ /= 2;
  1471. }
  1472. }
  1473. if (!subimageLevels)
  1474. {
  1475. LOGERROR("Subimage region from compressed image " + GetName() + " did not produce any data");
  1476. return 0;
  1477. }
  1478. Image* image = new Image(context_);
  1479. image->width_ = paddedRect.Width();
  1480. image->height_ = paddedRect.Height();
  1481. image->depth_ = 1;
  1482. image->compressedFormat_ = compressedFormat_;
  1483. image->numCompressedLevels_ = subimageLevels;
  1484. image->components_ = components_;
  1485. image->data_ = new unsigned char[subimageData.Size()];
  1486. memcpy(image->data_.Get(), &subimageData[0], subimageData.Size());
  1487. image->SetMemoryUse(subimageData.Size());
  1488. return image;
  1489. }
  1490. }
  1491. SDL_Surface* Image::GetSDLSurface(const IntRect& rect) const
  1492. {
  1493. if (!data_)
  1494. return 0;
  1495. if (depth_ > 1)
  1496. {
  1497. LOGERROR("Can not get SDL surface from 3D image");
  1498. return 0;
  1499. }
  1500. if (IsCompressed())
  1501. {
  1502. LOGERROR("Can not get SDL surface from compressed image " + GetName());
  1503. return 0;
  1504. }
  1505. if (components_ < 3)
  1506. {
  1507. LOGERROR("Can not get SDL surface from image " + GetName() + " with less than 3 components");
  1508. return 0;
  1509. }
  1510. IntRect imageRect = rect;
  1511. // Use full image if illegal rect
  1512. if (imageRect.left_ < 0 || imageRect.top_ < 0 || imageRect.right_ > width_ || imageRect.bottom_ > height_ ||
  1513. imageRect.left_ >= imageRect.right_ || imageRect.top_ >= imageRect.bottom_)
  1514. {
  1515. imageRect.left_ = 0;
  1516. imageRect.top_ = 0;
  1517. imageRect.right_ = width_;
  1518. imageRect.bottom_ = height_;
  1519. }
  1520. int imageWidth = width_;
  1521. int width = imageRect.Width();
  1522. int height = imageRect.Height();
  1523. // Assume little-endian for all the supported platforms
  1524. unsigned rMask = 0x000000ff;
  1525. unsigned gMask = 0x0000ff00;
  1526. unsigned bMask = 0x00ff0000;
  1527. unsigned aMask = 0xff000000;
  1528. SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, components_ * 8, rMask, gMask, bMask, aMask);
  1529. if (surface)
  1530. {
  1531. SDL_LockSurface(surface);
  1532. unsigned char* destination = reinterpret_cast<unsigned char*>(surface->pixels);
  1533. unsigned char* source = data_ + components_ * (imageWidth * imageRect.top_ + imageRect.left_);
  1534. for (int i = 0; i < height; ++i)
  1535. {
  1536. memcpy(destination, source, components_ * width);
  1537. destination += surface->pitch;
  1538. source += components_ * imageWidth;
  1539. }
  1540. SDL_UnlockSurface(surface);
  1541. }
  1542. else
  1543. LOGERROR("Failed to create SDL surface from image " + GetName());
  1544. return surface;
  1545. }
  1546. void Image::PrecalculateLevels()
  1547. {
  1548. if (!data_ || IsCompressed())
  1549. return;
  1550. PROFILE(PrecalculateImageMipLevels);
  1551. nextLevel_.Reset();
  1552. if (width_ > 1 || height_ > 1)
  1553. {
  1554. SharedPtr<Image> current = GetNextLevel();
  1555. nextLevel_ = current;
  1556. while (current && (current->width_ > 1 || current->height_ > 1))
  1557. {
  1558. current->nextLevel_ = current->GetNextLevel();
  1559. current = current->nextLevel_;
  1560. }
  1561. }
  1562. }
  1563. unsigned char* Image::GetImageData(Deserializer& source, int& width, int& height, unsigned& components)
  1564. {
  1565. unsigned dataSize = source.GetSize();
  1566. SharedArrayPtr<unsigned char> buffer(new unsigned char[dataSize]);
  1567. source.Read(buffer.Get(), dataSize);
  1568. return stbi_load_from_memory(buffer.Get(), dataSize, &width, &height, (int *)&components, 0);
  1569. }
  1570. void Image::FreeImageData(unsigned char* pixelData)
  1571. {
  1572. if (!pixelData)
  1573. return;
  1574. stbi_image_free(pixelData);
  1575. }
  1576. }