Image.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. #ifndef GUL_IMAGE_H
  2. #define GUL_IMAGE_H
  3. #include<iostream>
  4. #include<string.h>
  5. #include<cassert>
  6. #include<type_traits>
  7. #include<functional>
  8. #include<cstdint>
  9. #include<cmath>
  10. namespace gul
  11. {
  12. inline uint8_t mix( uint8_t a, uint8_t b, float t)
  13. {
  14. return static_cast<uint8_t>( (float(a) * (1.0f-t) + float(b)*t));
  15. }
  16. /**
  17. * @brief The channel1f struct
  18. *
  19. * Essentially a 1D image of floating point values.
  20. * Mostly used for intermediate stages;
  21. */
  22. struct channel1f
  23. {
  24. std::vector<float> data;
  25. channel1f(uint32_t w, uint32_t h) : _width(w), _height(h)
  26. {
  27. data.resize(w*h);
  28. }
  29. float & operator()(uint32_t u, uint32_t v)
  30. {
  31. return data[v*_width+u];
  32. }
  33. float const & operator()(uint32_t u, uint32_t v) const
  34. {
  35. return data[v*_width+u];
  36. }
  37. uint32_t width() const
  38. {
  39. return _width;
  40. }
  41. uint32_t height() const
  42. {
  43. return _height;
  44. }
  45. private:
  46. uint32_t _width;
  47. uint32_t _height;
  48. };
  49. struct ColorChannel
  50. {
  51. using channel_type = ColorChannel;
  52. uint32_t stride = 0;
  53. uint32_t offset = 0;
  54. ColorChannel()
  55. {
  56. }
  57. ColorChannel(uint8_t * data, uint32_t _offset, uint32_t _stride, uint32_t w, uint32_t h) : stride(_stride), offset(_offset), width(w), height(h), ptr(data)
  58. {
  59. }
  60. void reset(uint8_t * data, uint32_t _offset, uint32_t _stride, uint32_t w, uint32_t h)
  61. {
  62. stride = _stride;
  63. offset = _offset;
  64. width = w;
  65. height = h;
  66. ptr = data;
  67. }
  68. uint8_t & operator()(uint32_t u, uint32_t v)
  69. {
  70. const auto rowLength = stride * width;
  71. return ptr[ v*rowLength + u*stride + offset ];
  72. //return static_cast<uint8_t*>(static_cast<void*>(&ptr[v*width+u]))[offset];
  73. }
  74. uint8_t const & operator()(uint32_t u, uint32_t v) const
  75. {
  76. const auto rowLength = stride * width;
  77. return ptr[ v*rowLength + u*stride + offset ];
  78. //return static_cast<uint8_t*>(static_cast<void*>(&ptr[v*width+u]))[offset];
  79. }
  80. ColorChannel& operator=( ColorChannel const & other)
  81. {
  82. if( width != other.width ||
  83. height != other.height)
  84. {
  85. throw std::logic_error("Channels are of different size");
  86. }
  87. auto w = other.getWidth();
  88. auto h = other.getHeight();
  89. for(uint32_t j=0;j<h;j++)
  90. {
  91. for(uint32_t i=0;i<w;i++)
  92. {
  93. (*this)(i,j) = other(i,j);
  94. }
  95. }
  96. return *this;
  97. }
  98. ColorChannel& operator=( uint8_t val)
  99. {
  100. auto w = getWidth();
  101. auto h = getHeight();
  102. for(uint32_t j=0;j<h;j++)
  103. {
  104. for(uint32_t i=0;i<w;i++)
  105. {
  106. (*this)(i,j) = val;
  107. }
  108. }
  109. return *this;
  110. }
  111. ColorChannel& operator=( int val )
  112. {
  113. return this->operator=( static_cast<uint8_t>(val) );
  114. }
  115. ColorChannel& operator=( float val )
  116. {
  117. return this->operator=( static_cast<uint8_t>(val*255.0f) );
  118. }
  119. ColorChannel& operator=( channel1f && val )
  120. {
  121. for(uint32_t j = 0; j < getHeight(); j++)
  122. {
  123. for(uint32_t i = 0; i < getWidth(); i++)
  124. {
  125. (*this)(i,j) = static_cast<uint8_t>(255.0f * val(i,j));
  126. }
  127. }
  128. return *this;
  129. }
  130. ColorChannel& operator=( channel1f const &val )
  131. {
  132. for(uint32_t j = 0; j < getHeight(); j++)
  133. {
  134. for(uint32_t i = 0; i < getWidth(); i++)
  135. {
  136. (*this)(i,j) = static_cast<uint8_t>(255.0f * val(i,j));
  137. }
  138. }
  139. return *this;
  140. }
  141. channel1f operator+( ColorChannel const & other) const
  142. {
  143. channel1f R(width,height);
  144. auto & b1 = *this;
  145. auto & b2 = other;
  146. const float sc = 1.0f / 255.0f;
  147. for(uint32_t j = 0; j < getHeight(); j++)
  148. {
  149. for(uint32_t i = 0; i < getWidth(); i++)
  150. {
  151. R(i,j) =( static_cast<float>( b1(i,j) ) + static_cast<float>(b2(i,j))) * sc;
  152. }
  153. }
  154. return R;
  155. }
  156. channel1f operator*( ColorChannel const & other) const
  157. {
  158. channel1f R(width,height);
  159. auto & b1 = *this;
  160. auto & b2 = other;
  161. const float sc = 1.0f / (255.0f*255.0f);
  162. for(uint32_t j = 0; j < getHeight(); j++)
  163. {
  164. for(uint32_t i = 0; i < getWidth(); i++)
  165. {
  166. R(i,j) = ( static_cast<float>( b1(i,j) ) * static_cast<float>(b2(i,j))) * sc;
  167. }
  168. }
  169. return R;
  170. }
  171. template<typename Callable_t>
  172. void apply( Callable_t C)
  173. {
  174. float sw = 1.0f / float(width);
  175. float sh = 1.0f / float(height);
  176. for(uint32_t v = 0; v < height; ++v)
  177. for(uint32_t u = 0; u < width; ++u)
  178. {
  179. float x = static_cast<float>(u) * sw;
  180. float y = static_cast<float>(v) * sh;
  181. (*this)(u,v) = static_cast<uint8_t>( C(x,y) * 255);
  182. }
  183. }
  184. template<typename Callable_t>
  185. ColorChannel& operator=( Callable_t C )
  186. {
  187. apply(C);
  188. return *this;
  189. }
  190. uint32_t getWidth() const
  191. {
  192. return width;
  193. }
  194. uint32_t getHeight() const
  195. {
  196. return height;
  197. }
  198. uint32_t getStride() const
  199. {
  200. return stride;
  201. }
  202. private:
  203. uint32_t width = 0;
  204. uint32_t height= 0;
  205. uint8_t *ptr =nullptr;
  206. friend class Image;
  207. };
  208. inline channel1f operator * (ColorChannel const & a, float b)
  209. {
  210. channel1f D( a.getWidth(), a.getHeight());
  211. auto *Y = &a(0,0);
  212. const float sc = 1.0f/255.0f;
  213. for(auto & v : D.data)
  214. {
  215. v = sc * *Y * b;
  216. Y+=4;
  217. }
  218. return D;
  219. }
  220. inline channel1f operator * (float b, ColorChannel const & a)
  221. {
  222. return operator*(a,b);
  223. }
  224. inline channel1f operator + (ColorChannel const & a, float b)
  225. {
  226. //std::cout << "construct OneChannel+float" << std::endl;
  227. channel1f D(a.getWidth(),a.getHeight());
  228. auto *Y = &a(0,0);
  229. float sc = 1.0f/255.0f;
  230. for(auto & v : D.data)
  231. {
  232. v = *Y*sc + b;
  233. Y+=4;
  234. }
  235. return D;
  236. }
  237. inline channel1f operator + (float b, ColorChannel const & a )
  238. {
  239. return operator+(a,b);
  240. }
  241. inline channel1f&& operator + (channel1f && D, channel1f && E)
  242. {
  243. //std::cout << "move OneChannel+OneChannel" << std::endl;
  244. auto b = E.data.begin();
  245. for(auto & v : D.data)
  246. {
  247. v += *b++;
  248. }
  249. return std::move(D);
  250. }
  251. inline channel1f&& operator + (channel1f && D, float b)
  252. {
  253. for(auto & v : D.data)
  254. {
  255. v += b;
  256. }
  257. return std::move(D);
  258. }
  259. inline channel1f&& operator - (channel1f && D, float b)
  260. {
  261. return operator+( std::move(D),-b);
  262. }
  263. inline channel1f operator - (ColorChannel const & a, float b)
  264. {
  265. return operator+(a,-b);
  266. }
  267. inline channel1f operator - (float b, ColorChannel const & a )
  268. {
  269. //std::cout << "Construct OneChannel+float" << std::endl;
  270. channel1f D(a.getWidth(),a.getHeight());
  271. auto *Y = &a(0,0);
  272. const float sc = 1.0f / 255.0f;
  273. for(auto & v : D.data)
  274. {
  275. v = b - *Y*sc;
  276. Y+=4;
  277. }
  278. return D;
  279. }
  280. class Image
  281. {
  282. public:
  283. Image() : Image(8,8,4)
  284. {
  285. }
  286. explicit Image(uint32_t w) : Image(w,w,4)
  287. {
  288. }
  289. Image(uint32_t w, uint32_t h, uint32_t ch=4)
  290. {
  291. resize(w,h,ch);
  292. }
  293. Image(const Image & other) : Image()
  294. {
  295. resize(other.getWidth(), other.getHeight(), other.getChannels());
  296. m_data = other.m_data;
  297. _setChannels( other.getWidth(), other.getHeight(), other.getChannels() );
  298. }
  299. Image(Image && other) : Image(1,1,4)
  300. {
  301. m_data = std::move(other.m_data);
  302. _setChannels( other.getWidth(), other.getHeight(), other.getChannels() );
  303. other.m_width = other.m_height = other.m_channels = 0;
  304. }
  305. Image& operator=(const Image & other)
  306. {
  307. if( &other != this)
  308. {
  309. resize(other.getWidth(), other.getHeight(), other.getChannels());
  310. auto & out = *this;
  311. for(uint32_t j=0;j<out.getHeight();j++)
  312. {
  313. for(uint32_t i=0;i<out.getWidth();i++)
  314. {
  315. for(uint32_t c =0; c < out.getChannels(); c++)
  316. {
  317. out(i,j,c) = other( i, j, c );
  318. }
  319. }
  320. }
  321. }
  322. return *this;
  323. }
  324. Image& operator=(Image && other)
  325. {
  326. if( &other != this)
  327. {
  328. m_data = std::move(other.m_data);
  329. _setChannels( other.getWidth(), other.getHeight(), other.getChannels() );
  330. other.m_width = other.m_height = other.m_channels = 0;
  331. }
  332. return *this;
  333. }
  334. void resize(uint32_t w, uint32_t h, uint32_t channels=4)
  335. {
  336. assert( channels <= 4);
  337. if( w*h*channels != m_data.size())
  338. {
  339. m_data.resize(w*h*channels);
  340. }
  341. m_channels = channels;
  342. _setChannels(w,h,channels);
  343. }
  344. void _setChannels(uint32_t width, uint32_t height, uint32_t channels)
  345. {
  346. //assert( channels <= 4 && channels >= 1);
  347. m_channels = channels;
  348. m_width = width;
  349. m_height = height;
  350. if( channels == 4)
  351. {
  352. a.reset( m_data.data(), 3, 4, width, height);
  353. b.reset( m_data.data(), 2, 4, width, height);
  354. g.reset( m_data.data(), 1, 4, width, height);
  355. r.reset( m_data.data(), 0, 4, width, height);
  356. }
  357. if( channels == 3)
  358. {
  359. a.reset( m_data.data(), 2, 3, width, height);
  360. b.reset( m_data.data(), 2, 3, width, height);
  361. g.reset( m_data.data(), 1, 3, width, height);
  362. r.reset( m_data.data(), 0, 3, width, height);
  363. }
  364. if( channels == 2)
  365. {
  366. a.reset( m_data.data(), 1, 2, width, height);
  367. b.reset( m_data.data(), 1, 2, width, height);
  368. g.reset( m_data.data(), 1, 2, width, height);
  369. r.reset( m_data.data(), 0, 2, width, height);
  370. }
  371. if( channels == 1)
  372. {
  373. a.reset( m_data.data(), 0, 1, width, height);
  374. b.reset( m_data.data(), 0, 1, width, height);
  375. g.reset( m_data.data(), 0, 1, width, height);
  376. r.reset( m_data.data(), 0, 1, width, height);
  377. }
  378. }
  379. void copyFromBuffer(void const * src, uint32_t totalBytes, uint32_t width, uint32_t height, uint32_t ch=4)
  380. {
  381. assert(totalBytes%sizeof(uint32_t)==0);
  382. resize(width,height,ch);
  383. memcpy(data(), src, totalBytes);
  384. }
  385. uint8_t & operator()(uint32_t u, uint32_t v, uint32_t c)
  386. {
  387. return m_data[ (v*m_width + u)*m_channels +c ] ;//r.ptr[v*r.width+u];
  388. }
  389. uint8_t const & operator()(uint32_t u, uint32_t v, uint32_t c) const
  390. {
  391. return m_data[ (v*m_width + u)*m_channels +c ] ;//r.ptr[v*r.width+u];
  392. }
  393. ColorChannel& operator[](size_t i)
  394. {
  395. return (&r)[i];
  396. }
  397. ColorChannel const& operator[](size_t i) const
  398. {
  399. return (&r)[i];
  400. }
  401. /**
  402. * @brief sample
  403. * @param u
  404. * @param v
  405. * @return
  406. *
  407. * Samples a 2x2 block of pixels and returns the average. really only used for
  408. * the nextMipMap() method.
  409. */
  410. uint8_t sample(uint32_t u, uint32_t v, uint32_t c) const
  411. {
  412. auto & R = *this;
  413. auto c1 = R(u,v ,c);
  414. auto c2 = R(u,v+1 ,c);
  415. auto c3 = R(u+1,v ,c);
  416. auto c4 = R(u+1,v+1,c);
  417. return static_cast<uint8_t>( (static_cast<uint32_t>(c1) + static_cast<uint32_t>(c2) + static_cast<uint32_t>(c3) + static_cast<uint32_t>(c4) ) / 4u);
  418. }
  419. /**
  420. * @brief nextMipMap
  421. * @return
  422. *
  423. * Returns the next mipmap level of the image. The next mipmap level has
  424. * width and height which is half the original.
  425. */
  426. Image nextMipMap() const
  427. {
  428. Image out;
  429. out.resize( getWidth()/2, getHeight()/2, getChannels());
  430. for(uint32_t j=0;j<out.getHeight();j++)
  431. {
  432. for(uint32_t i=0;i<out.getWidth();i++)
  433. {
  434. for(uint32_t c=0; c < out.getChannels(); c++)
  435. {
  436. out(i,j,c) = sample( i*2, j*2,c );
  437. }
  438. }
  439. }
  440. return out;
  441. }
  442. Image allocateNextMipMap() const
  443. {
  444. Image out;
  445. out.resize( getWidth()/2, getHeight()/2, getChannels());
  446. return out;
  447. }
  448. void const* data() const
  449. {
  450. return m_data.data();
  451. }
  452. void * data()
  453. {
  454. return m_data.data();
  455. }
  456. size_t size() const
  457. {
  458. return m_data.size();
  459. }
  460. size_t byteSize() const
  461. {
  462. return m_data.size();
  463. }
  464. uint32_t width() const
  465. {
  466. return m_width;
  467. }
  468. uint32_t height() const
  469. {
  470. return m_height;
  471. }
  472. uint32_t getWidth() const
  473. {
  474. return m_width;
  475. }
  476. uint32_t getHeight() const
  477. {
  478. return m_height;
  479. }
  480. uint32_t getChannels() const
  481. {
  482. return m_channels;
  483. }
  484. void clear()
  485. {
  486. m_data.clear();
  487. m_channels = 0;
  488. m_width = 0;
  489. m_height = 0;
  490. _setChannels(0,0,0);
  491. }
  492. public:
  493. size_t hash() const
  494. {
  495. auto w = getWidth();
  496. auto h = getHeight();
  497. uint32_t c = 4;
  498. auto hashCo = [](size_t _seed, size_t h2)
  499. {
  500. _seed ^= h2 + 0x9e3779b9 + (_seed<<6) + (_seed>>2);
  501. return _seed;
  502. };
  503. std::hash<uint32_t> Hu;
  504. auto seed = Hu(w);
  505. seed = hashCo(seed, Hu(h) );
  506. seed = hashCo(seed, Hu(c) );
  507. auto * begin = static_cast<uint32_t const*>(data());
  508. for(uint32_t i=0;i<w*h;i++)
  509. {
  510. seed = hashCo(seed, Hu(*begin++));
  511. }
  512. return seed;
  513. }
  514. //#endif
  515. std::vector<uint8_t> m_data;
  516. uint32_t m_channels;
  517. uint32_t m_width;
  518. uint32_t m_height;
  519. ColorChannel r;
  520. ColorChannel g;
  521. ColorChannel b;
  522. ColorChannel a;
  523. /**
  524. * @brief X
  525. * @param width
  526. * @param height
  527. * @return
  528. *
  529. * Returns a oneD_Channel where the value of the channel increases
  530. * linearly in the u direction
  531. */
  532. static channel1f X(uint32_t width, uint32_t height)
  533. {
  534. channel1f D(width,height);
  535. float sc = 1.0f / float(width);
  536. for( uint32_t v=0; v< height; ++v)
  537. {
  538. for( uint32_t u=0; u<width; ++u)
  539. {
  540. float x = static_cast<float>(u) * sc;
  541. D(u,v) = x;
  542. }
  543. }
  544. return D;
  545. }
  546. /**
  547. * @brief Y
  548. * @param width
  549. * @param height
  550. * @return
  551. *
  552. * Returns a oneD_Channel where the value of the channel increases
  553. * linearly in the v direction
  554. */
  555. static channel1f Y(uint32_t width, uint32_t height)
  556. {
  557. channel1f D(width,height);
  558. float sc = 1.0f / float(height);
  559. for( uint32_t v=0; v< height; ++v)
  560. {
  561. float y = static_cast<float>(v) * sc;
  562. for( uint32_t u=0; u<width; ++u)
  563. {
  564. D(u,v) = y;
  565. }
  566. }
  567. return D;
  568. }
  569. };
  570. inline channel1f mix( ColorChannel const & a, ColorChannel const & b, float t)
  571. {
  572. channel1f D( a.getWidth(), a.getHeight());
  573. auto * A = &a(0,0);
  574. auto * B = &b(0,0);
  575. float sc = 1.0f/255.0f;
  576. for(auto & v : D.data)
  577. {
  578. float x1 = static_cast<float>(*A);
  579. float x2 = static_cast<float>(*B);
  580. v = ( (1.0f - t) * x1 + t * x2 ) * sc;
  581. A+=4; B+=4;
  582. }
  583. return D;
  584. }
  585. inline channel1f mix( ColorChannel const & a, ColorChannel const & b, ColorChannel const & _t)
  586. {
  587. channel1f D( a.getWidth(), a.getHeight());
  588. auto * A = &a(0,0);
  589. auto * B = &b(0,0);
  590. auto * T = &_t(0,0);
  591. float sc = 1.0f/255.0f;
  592. for(auto & v : D.data)
  593. {
  594. float t = *T * sc;
  595. v = ( (1.0f - t) * (*A) + t * (*B) ) * sc;
  596. A+=4; B+=4; T+=4;
  597. }
  598. return D;
  599. }
  600. inline Image mix( Image const & a, Image const & b, Image const & _t)
  601. {
  602. Image D;
  603. assert( a.getWidth() == b.getWidth());
  604. assert( a.getHeight() == b.getHeight());
  605. assert( a.getChannels() == b.getChannels());
  606. assert( _t.getWidth() == b.getWidth());
  607. assert( _t.getHeight() == b.getHeight());
  608. assert( _t.getChannels() == b.getChannels());
  609. D.resize(a.getWidth(), a.getHeight(), a.getChannels());
  610. auto w = std::min( a.getWidth(), b.getWidth() );
  611. auto h = std::min( a.getHeight(), b.getHeight() );
  612. auto C = std::min( a.getChannels(), b.getChannels());
  613. for(uint32_t j=0;j<h;j++)
  614. {
  615. for(uint32_t i=0;i<w;i++)
  616. {
  617. for(uint32_t c =0; c < C; c++)
  618. {
  619. float t = static_cast<float>(_t(i,j,c)) / 255.0f;
  620. D(i,j,c) = mix( a(i,j,c), b(i,j,c), t );
  621. }
  622. }
  623. }
  624. return D;
  625. }
  626. inline Image mix( Image const & a, Image const & b, float t)
  627. {
  628. Image D;
  629. assert( a.getWidth() == b.getWidth());
  630. assert( a.getHeight() == b.getHeight());
  631. assert( a.getChannels() == b.getChannels());
  632. D.resize(a.getWidth(), a.getHeight(), a.getChannels());
  633. auto w = std::min( a.getWidth(), b.getWidth() );
  634. auto h = std::min( a.getHeight(), b.getHeight() );
  635. auto C = std::min( a.getChannels(), b.getChannels());
  636. for(uint32_t j=0;j<h;j++)
  637. {
  638. for(uint32_t i=0;i<w;i++)
  639. {
  640. for(uint32_t c =0; c < C; c++)
  641. {
  642. D(i,j,c) = mix( a(i,j,c), b(i,j,c), t );
  643. }
  644. }
  645. }
  646. return D;
  647. }
  648. /**
  649. * @brief The ImageMM struct
  650. *
  651. * An array of Images that represent the
  652. * chain of mipmaps.
  653. */
  654. struct ImageMM
  655. {
  656. std::vector<Image> level;
  657. ImageMM()
  658. {
  659. level.resize(1);
  660. }
  661. Image & getLevel(size_t i)
  662. {
  663. return level.at(i);
  664. }
  665. Image const& getLevel(size_t i) const
  666. {
  667. return level.at(i);
  668. }
  669. void resize(uint32_t w, uint32_t h)
  670. {
  671. level[0].resize(w,h);
  672. }
  673. uint32_t getChannels() const
  674. {
  675. return level.front().getChannels();
  676. }
  677. uint32_t getHeight() const
  678. {
  679. return level.front().getHeight();
  680. }
  681. uint32_t getWidth() const
  682. {
  683. return level.front().getWidth();
  684. }
  685. uint32_t getLevelCount() const
  686. {
  687. return static_cast<uint32_t>(level.size());
  688. }
  689. uint32_t maxLevels() const
  690. {
  691. auto w = level.at(0).getWidth();
  692. auto h = level.at(0).getHeight();
  693. auto m = uint32_t( std::log2( std::min(w,h) ) );
  694. return m;
  695. }
  696. void allocateMipMaps(uint32_t mips=0)
  697. {
  698. auto maxMips = maxLevels();
  699. if( mips != 0)
  700. {
  701. mips = std::min(maxMips, mips);
  702. }
  703. else
  704. {
  705. mips = maxMips;
  706. }
  707. mips=mips-1;
  708. level.resize(1);
  709. while(mips--)
  710. {
  711. auto m = level.back().allocateNextMipMap();
  712. level.push_back(m);
  713. }
  714. }
  715. void clearMipMaps()
  716. {
  717. level.resize(1);
  718. }
  719. };
  720. struct ImageArray
  721. {
  722. std::vector<ImageMM> layer;
  723. ImageArray()
  724. {
  725. layer.resize(1);
  726. }
  727. ImageArray(Image const & I)
  728. {
  729. ImageMM mm;
  730. mm.level.clear();
  731. mm.level.push_back(I);
  732. layer.push_back( std::move(mm));
  733. }
  734. ImageArray(Image && I)
  735. {
  736. ImageMM mm;
  737. mm.level.clear();
  738. mm.level.push_back( std::move(I) );
  739. layer.push_back( std::move(mm));
  740. }
  741. ImageMM& getLayer(size_t i)
  742. {
  743. return layer.at(i);
  744. }
  745. ImageMM const& getLayer(size_t i) const
  746. {
  747. return layer.at(i);
  748. }
  749. void resize(uint32_t w, uint32_t h, uint32_t L=1, uint32_t mips=1)
  750. {
  751. layer.clear();
  752. layer.resize(L);
  753. for(auto & l : layer)
  754. {
  755. l.resize(w,h);
  756. l.allocateMipMaps(mips);
  757. }
  758. }
  759. uint32_t getChannels() const
  760. {
  761. return layer.front().getChannels();
  762. }
  763. uint32_t getHeight() const
  764. {
  765. return layer.front().getHeight();
  766. }
  767. uint32_t getWidth() const
  768. {
  769. return layer.front().getWidth();
  770. }
  771. uint32_t getLevelCount() const
  772. {
  773. return layer.front().getLevelCount();
  774. }
  775. uint32_t getLayerCount() const
  776. {
  777. return static_cast<uint32_t>(layer.size());
  778. }
  779. void allocateMipMaps(uint32_t mips=0)
  780. {
  781. for(auto & l : layer)
  782. {
  783. l.allocateMipMaps(mips);
  784. }
  785. }
  786. };
  787. }
  788. namespace std
  789. {
  790. template<>
  791. struct hash<gul::Image>
  792. {
  793. static inline size_t hashCombine(size_t seed, size_t h2)
  794. {
  795. //std::hash<T> hasher;
  796. seed ^= h2 + 0x9e3779b9 + (seed<<6) + (seed>>2);
  797. return seed;
  798. }
  799. std::size_t operator()(gul::Image const & img) const noexcept
  800. {
  801. auto w = img.getWidth();
  802. auto h = img.getHeight();
  803. uint32_t c = img.getChannels();
  804. std::hash<uint32_t> Hu;
  805. auto seed = Hu(w);
  806. seed = hashCombine(seed, Hu(h) );
  807. seed = hashCombine(seed, Hu(c) );
  808. auto * begin = static_cast<uint32_t const*>(img.data());
  809. for(uint32_t i=0;i<w*h;i++)
  810. {
  811. seed = hashCombine(seed, Hu(*begin++));
  812. }
  813. return seed;
  814. }
  815. };
  816. }
  817. #endif