MultiChannelImageT.tcc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. #include <iostream>
  2. #include <assert.h>
  3. #include <stdio.h>
  4. namespace NICE {
  5. template<class P>
  6. MultiChannelImageT<P>::MultiChannelImageT( int _xsize, int _ysize, uint _numChannels)
  7. {
  8. data = NULL;
  9. numChannels = 0;
  10. xsize = 0;
  11. ysize = 0;
  12. reInit( _xsize, _ysize, _numChannels);
  13. }
  14. template<class P>
  15. MultiChannelImageT<P>::MultiChannelImageT()
  16. {
  17. xsize = 0;
  18. ysize = 0;
  19. numChannels = 0;
  20. data = NULL;
  21. }
  22. template<class P>
  23. P & MultiChannelImageT<P>::operator() (int x, int y, uint channel)
  24. {
  25. assert( channel < numChannels );
  26. assert(( x < xsize ) && ( x >= 0 ) );
  27. assert(( y < ysize ) && ( y >= 0 ) );
  28. assert( data[channel] != NULL );
  29. return data[channel][x + y*xsize];
  30. }
  31. template<class P>
  32. ImageT<P> MultiChannelImageT<P>::operator[] (uint c)
  33. {
  34. // This was our first idea ... but it creates a real copy
  35. // ImageT<P> tmp ( data[c], xsize, ysize, xsize*sizeof(P), GrayColorImageCommonImplementation::noAlignment );
  36. // This is the correct version. The funny thing about this is that shallowCopy
  37. // is not an enum parameter, but an instance of ShallowCopyMode, which is a class.
  38. // This fancy trick was done in older to prevent automatic conversion between enum types
  39. // as done implicitly by C++.
  40. ImageT<P> tmp ( data[c], xsize, ysize, xsize*sizeof(P), GrayColorImageCommonImplementation::shallowCopy );
  41. return tmp;
  42. }
  43. template<class P>
  44. MultiChannelImageT<P>& MultiChannelImageT<P>::operator=(const MultiChannelImageT<P>& orig)
  45. {
  46. if(!(xsize == orig.xsize && ysize == orig.ysize && numChannels == orig.numChannels))
  47. {
  48. freeData();
  49. xsize = orig.xsize;
  50. ysize = orig.ysize;
  51. numChannels = orig.numChannels;
  52. if(orig.data != NULL)
  53. {
  54. data = new P *[numChannels];
  55. for ( int c = 0; c < ( int )numChannels; c++ )
  56. {
  57. if ( orig.data[c] == NULL )
  58. {
  59. data[c] = NULL;
  60. }
  61. else
  62. {
  63. data[c] = new P [xsize*ysize];
  64. }
  65. }
  66. }
  67. else
  68. data = NULL;
  69. }
  70. for ( int c = 0; c < ( int )numChannels; c++ )
  71. {
  72. if ( orig.data[c] != NULL )
  73. {
  74. for ( int x = 0; x < xsize*ysize; x++ )
  75. {
  76. data[c][x] = orig.data[c][x];
  77. }
  78. }
  79. }
  80. return *this;
  81. }
  82. template<class P>
  83. MultiChannelImageT<P>::MultiChannelImageT( const MultiChannelImageT<P>& p )
  84. {
  85. data = NULL;
  86. xsize = p.xsize;
  87. ysize = p.ysize;
  88. numChannels = p.numChannels;
  89. if(p.data != NULL)
  90. data = new P *[numChannels];
  91. else
  92. data = NULL;
  93. for ( int c = 0; c < ( int )numChannels; c++ )
  94. {
  95. if ( p.data[c] == NULL )
  96. {
  97. data[c] = NULL;
  98. }
  99. else
  100. {
  101. data[c] = new P [xsize*ysize];
  102. for ( int x = 0; x < xsize*ysize; x++ )
  103. {
  104. data[c][x] = p.data[c][x];
  105. }
  106. }
  107. }
  108. }
  109. template<class P>
  110. void MultiChannelImageT<P>::addChannel( int newChans )
  111. {
  112. P **tmpData = new P *[numChannels+newChans];
  113. bool allocMem = false;
  114. int i = 0;
  115. for ( ; i < (int)numChannels; i++ )
  116. {
  117. tmpData[i] = data[i];
  118. if ( data[i] != NULL )
  119. allocMem = true;
  120. }
  121. if ( allocMem )
  122. {
  123. for ( ; i < newChans + (int)numChannels; i++ )
  124. {
  125. tmpData[i] = new P [xsize*ysize];
  126. }
  127. }
  128. numChannels += newChans;
  129. delete [] data;
  130. data = new P *[numChannels];
  131. for ( i = 0; i < (int)numChannels; i++ )
  132. {
  133. data[i] = tmpData[i];
  134. }
  135. delete [] tmpData;
  136. }
  137. template<class P>
  138. template<class SrcP>
  139. void MultiChannelImageT<P>::addChannel(const NICE::ImageT<SrcP> &newImg)
  140. {
  141. int oldchan = numChannels;
  142. if(this->xsize > 0)
  143. {
  144. assert(newImg.width() == this->width() && newImg.height() == this->height());
  145. addChannel(1);
  146. }
  147. else
  148. {
  149. reInit( newImg.width(), newImg.height(), 1 );
  150. }
  151. for(int y = 0; y < this->ysize; y++)
  152. {
  153. for(int x = 0; x < this->xsize; x++)
  154. {
  155. data[oldchan][x + y*xsize] = (P)newImg(x,y);
  156. }
  157. }
  158. }
  159. template<class P>
  160. template<class SrcP>
  161. void MultiChannelImageT<P>::addChannel(const NICE::MultiChannelImageT<SrcP> &newImg)
  162. {
  163. int oldchan = numChannels;
  164. if(numChannels > 0)
  165. {
  166. assert(newImg.width() == this->width() && newImg.height() == this->height());
  167. addChannel(newImg.channels());
  168. }
  169. else
  170. {
  171. reInit( newImg.width(), newImg.height(), newImg.channels() );
  172. }
  173. int chanNI = 0;
  174. for(int c = oldchan; c < (int)numChannels; c++, chanNI++)
  175. {
  176. int val = 0;
  177. for(int y = 0; y < this->ysize; y++)
  178. {
  179. for(int x = 0; x < this->xsize; x++, val++)
  180. {
  181. data[c][val] = newImg.get(x,y,chanNI);
  182. }
  183. }
  184. }
  185. }
  186. template<class P>
  187. MultiChannelImageT<P>::~MultiChannelImageT()
  188. {
  189. freeData();
  190. }
  191. template<class P>
  192. void MultiChannelImageT<P>::freeData()
  193. {
  194. if ( data != NULL )
  195. {
  196. for ( uint i = 0 ; i < numChannels ; i++ )
  197. if ( data[i] != NULL )
  198. delete [] data[i];
  199. delete [] data;
  200. data = NULL;
  201. }
  202. }
  203. template<class P>
  204. void MultiChannelImageT<P>::reInit( int _xsize, int _ysize, int _numChannels )
  205. {
  206. freeData();
  207. xsize = _xsize;
  208. ysize = _ysize;
  209. numChannels = _numChannels;
  210. data = new P *[numChannels];
  211. for ( uint i = 0 ; i < numChannels; i++ )
  212. data[i] = new P [xsize*ysize];
  213. }
  214. template<class P>
  215. template<class SrcP>
  216. void MultiChannelImageT<P>::reInitFrom( const MultiChannelImageT<SrcP> & src )
  217. {
  218. freeData();
  219. xsize = src.width();
  220. ysize = src.height();
  221. numChannels = src.channels();
  222. data = new P *[numChannels];
  223. for ( uint i = 0 ; i < numChannels; i++ )
  224. data[i] = new P [xsize*ysize];
  225. }
  226. template<class P>
  227. P MultiChannelImageT<P>::get( int x, int y, uint channel ) const
  228. {
  229. assert( channel < numChannels );
  230. assert(( x < xsize ) && ( x >= 0 ) );
  231. assert(( y < ysize ) && ( y >= 0 ) );
  232. assert( data[channel] != NULL );
  233. return data[channel][x + y*xsize];
  234. }
  235. template<class P>
  236. P ** MultiChannelImageT<P>::getDataPointer()
  237. {
  238. return data;
  239. }
  240. template<class P>
  241. void MultiChannelImageT<P>::set( int x, int y, P val, uint channel )
  242. {
  243. assert( channel < numChannels );
  244. assert(( x < xsize ) && ( x >= 0 ) );
  245. assert(( y < ysize ) && ( y >= 0 ) );
  246. assert( data[channel] != NULL );
  247. data[channel][x + y*xsize] = val;
  248. }
  249. template<class P>
  250. void MultiChannelImageT<P>::set( P val, uint channel )
  251. {
  252. assert( channel < numChannels );
  253. assert( data[channel] != NULL );
  254. for ( int k = 0 ; k < xsize*ysize ; k++ )
  255. data[channel][k] = val;
  256. }
  257. template<class P>
  258. void MultiChannelImageT<P>::setAll( P val )
  259. {
  260. for ( uint channel = 0 ; channel < numChannels ; channel++ )
  261. if ( data[channel] != NULL )
  262. set( val, channel );
  263. }
  264. template<class P>
  265. void MultiChannelImageT<P>::statistics( P & min, P & max, uint channel ) const
  266. {
  267. assert( channel < numChannels );
  268. for ( long k = 0 ; k < xsize*ysize ; k++ )
  269. {
  270. P val = data [channel][k];
  271. if (( k == 0 ) || ( val > max ) ) max = val;
  272. if (( k == 0 ) || ( val < min ) ) min = val;
  273. }
  274. assert(NICE::isFinite(max));
  275. assert(NICE::isFinite(min));
  276. }
  277. template<class P>
  278. Image MultiChannelImageT<P>::getChannel( uint channel ) const
  279. {
  280. assert( channel < numChannels );
  281. NICE::Image img;
  282. convertToGrey( img, channel, true );
  283. /*
  284. P min, max;
  285. statistics ( min, max, channel );
  286. fprintf (stderr, "MultiChannelImageT<>::showChannel: max %f min %f\n", (double)max, (double)min );*/
  287. return img;
  288. }
  289. /** convert to ice image */
  290. template<class P>
  291. void MultiChannelImageT<P>::convertToGrey( NICE::Image & img, uint channel, bool normalize ) const
  292. {
  293. assert( channel < numChannels );
  294. P min, max;
  295. if ( normalize ) {
  296. statistics( min, max, channel );
  297. fprintf( stderr, "MultiChannelImageT<>::showChannel: max %f min %f\n", ( double )max, ( double )min );
  298. }
  299. bool skip_assignment = false;
  300. img.resize( xsize, ysize );
  301. if ( normalize )
  302. if ( max - min < std::numeric_limits<double>::min() )
  303. {
  304. img.set( max );
  305. skip_assignment = true;
  306. fprintf( stderr, "MultiChannelImageT::showChannel: image is uniform! (%f)\n", ( double )max );
  307. }
  308. if ( ! skip_assignment )
  309. {
  310. long k = 0;
  311. for ( int y = 0 ; y < ysize; y++ )
  312. for ( int x = 0 ; x < xsize ; x++, k++ )
  313. if ( normalize )
  314. img.setPixel( x, y, ( int )(( data[channel][k] - min ) * 255 / ( max - min ) ) );
  315. else
  316. img.setPixel( x, y, ( int )( data[channel][k] ) );
  317. }
  318. }
  319. template<class P>
  320. void MultiChannelImageT<P>::convertToColor( NICE::ColorImage & img, const int chan1, const int chan2, const int chan3) const
  321. {
  322. assert( chan1 < numChannels && chan2 < numChannels && chan3 < numChannels);
  323. img.resize( xsize, ysize );
  324. long k = 0;
  325. for ( int y = 0 ; y < ysize; y++ )
  326. for ( int x = 0 ; x < xsize ; x++, k++ )
  327. {
  328. img.setPixel( x, y, 0, ( int )( data[chan1][k] ) );
  329. img.setPixel( x, y, 1, ( int )( data[chan2][k] ) );
  330. img.setPixel( x, y, 2, ( int )( data[chan3][k] ) );
  331. }
  332. }
  333. template<class P>
  334. ColorImage MultiChannelImageT<P>::getColor() const
  335. {
  336. assert( numChannels == 3 );
  337. NICE::ColorImage img( xsize, ysize );
  338. long k = 0;
  339. for ( int y = 0 ; y < ysize; y++ )
  340. for ( int x = 0 ; x < xsize ; x++, k++ )
  341. {
  342. img.setPixel( x, y, 0, ( int )( data[0][k] ) );
  343. img.setPixel( x, y, 1, ( int )( data[1][k] ) );
  344. img.setPixel( x, y, 2, ( int )( data[2][k] ) );
  345. }
  346. //showImage(img);
  347. //getchar();
  348. return img;
  349. }
  350. template<class P>
  351. void MultiChannelImageT<P>::calcIntegral( uint channel )
  352. {
  353. assert( channel < numChannels );
  354. assert( data[channel] != NULL );
  355. int k;
  356. P *integralImage = data[channel];
  357. k = xsize;
  358. for ( int y = 1 ; y < ysize; y++, k += xsize )
  359. integralImage[k] += integralImage[k-xsize];
  360. k = 1;
  361. for ( int x = 1 ; x < xsize; x++, k++ )
  362. integralImage[k] += integralImage[k-1];
  363. k = xsize + 1;
  364. for ( int y = 1 ; y < ysize ; y++, k++ )
  365. for ( int x = 1 ; x < xsize ; x++, k++ )
  366. {
  367. integralImage[k] += integralImage[k-1];
  368. integralImage[k] += integralImage[k - xsize];
  369. integralImage[k] -= integralImage[k - xsize - 1];
  370. }
  371. }
  372. template<class P>
  373. P MultiChannelImageT<P>::getIntegralValue(int ulx, int uly, int lrx, int lry, int channel) const
  374. {
  375. ulx = std::max(ulx-1, -1);
  376. ulx = std::min(ulx, xsize-1);
  377. uly = std::max(uly-1, -1);
  378. uly = std::min(uly, ysize-1);
  379. lrx = std::max(lrx, 0);
  380. lrx = std::min(lrx, xsize-1);
  381. lry = std::max(lry, 0);
  382. lry = std::min(lry, ysize-1);
  383. P val1, val2, val3, val4;
  384. val1 = get(lrx, lry, channel);
  385. if(uly > -1)
  386. val2 = get(lrx, uly, channel);
  387. else
  388. val2 = 0;
  389. if(ulx > -1)
  390. val3 = get(ulx, lry, channel);
  391. else
  392. val3 = 0;
  393. if(ulx > -1 && uly > -1)
  394. val4 = get(ulx, uly, channel);
  395. else
  396. val4 = 0;
  397. P area = abs((P)(lrx-ulx)*(lry-uly));
  398. P val = val1 - val2 - val3 + val4;
  399. return val/area;
  400. }
  401. template<class P>
  402. void MultiChannelImageT<P>::store( std::string filename ) const
  403. {
  404. // simple raw format
  405. FILE *f = fopen( filename.c_str(), "w" );
  406. if ( f == NULL ) {
  407. fprintf( stderr, "MultiChannelImageT::store: error writing to %s\n", filename.c_str() );
  408. exit( -1 );
  409. }
  410. fwrite( &xsize, sizeof( int ), 1, f );
  411. fwrite( &ysize, sizeof( int ), 1, f );
  412. fwrite( &numChannels, sizeof( uint ), 1, f );
  413. for ( uint channel = 0 ; channel < numChannels ; channel++ )
  414. {
  415. assert( data[channel] != NULL );
  416. fwrite( data[channel], sizeof( P ), xsize*ysize, f );
  417. }
  418. fclose( f );
  419. }
  420. template<class P>
  421. void MultiChannelImageT<P>::restore( std::string filename )
  422. {
  423. // simple raw format
  424. FILE *f = fopen( filename.c_str(), "r" );
  425. if ( f == NULL ) {
  426. fprintf( stderr, "MultiChannelImageT::store: error reading from %s\n", filename.c_str() );
  427. exit( -1 );
  428. }
  429. fread( &xsize, sizeof( int ), 1, f );
  430. fread( &ysize, sizeof( int ), 1, f );
  431. fread( &numChannels, sizeof( uint ), 1, f );
  432. if ( numChannels > 0 ) {
  433. reInit( xsize, ysize, numChannels );
  434. for ( uint channel = 0 ; channel < numChannels ; channel++ )
  435. {
  436. assert( data[channel] != NULL );
  437. fread( data[channel], sizeof( P ), xsize*ysize, f );
  438. }
  439. } else {
  440. freeData();
  441. data = NULL;
  442. }
  443. fclose( f );
  444. }
  445. template<class P>
  446. int MultiChannelImageT<P>::width() const
  447. {
  448. return xsize;
  449. }
  450. template<class P>
  451. int MultiChannelImageT<P>::height() const
  452. {
  453. return ysize;
  454. }
  455. template<class P>
  456. int MultiChannelImageT<P>::channels() const
  457. {
  458. return ( int )numChannels;
  459. }
  460. template<class P>
  461. int MultiChannelImageT<P>::getPixelInt( int x, int y, int channel ) const
  462. {
  463. throw( "this type is not implemented\n" );
  464. return -1;
  465. }
  466. template<class P>
  467. double MultiChannelImageT<P>::getPixelFloat( int x, int y, int channel ) const
  468. {
  469. throw( "this type is not implemented\n" );
  470. return -1.0;
  471. }
  472. template<class P>
  473. void MultiChannelImageT<P>::setPixelInt( int x, int y, int channel, int pixel )
  474. {
  475. throw( "this type is not implemented\n" );
  476. }
  477. template<class P>
  478. void MultiChannelImageT<P>::setPixelFloat( int x, int y, int channel, double pixel )
  479. {
  480. throw( "this type is not implemented\n" );
  481. }
  482. #define SET_FUNCS_PROTO_MACRO(MYTYPE) \
  483. template<>\
  484. int MultiChannelImageT<MYTYPE>::getPixelInt(int x, int y, int channel) const;\
  485. template<>\
  486. double MultiChannelImageT<MYTYPE>::getPixelFloat(int x, int y, int channel) const;\
  487. template<>\
  488. void MultiChannelImageT<MYTYPE>::setPixelInt(int x, int y, int channel, int pixel);\
  489. template<>\
  490. void MultiChannelImageT<MYTYPE>::setPixelFloat(int x, int y, int channel, double pixel);
  491. SET_FUNCS_PROTO_MACRO( double )
  492. SET_FUNCS_PROTO_MACRO( int )
  493. SET_FUNCS_PROTO_MACRO( long int )
  494. SET_FUNCS_PROTO_MACRO( float )
  495. SET_FUNCS_PROTO_MACRO( unsigned int )
  496. } // namespace