image.c
Upload User: shhuayu888
Upload Date: 2013-03-28
Package Size: 1788k
Code Size: 13k
Category:

Windows Develop

Development Platform:

Unix_Linux

  1. /***************************************************************************
  2.  File Name  : image.c
  3.  Purpose    : provides basic functionality to read, write, display, enhance
  4.       and correlate images ( SUN raster or BIN format )
  5.  Release    : Version 1.0
  6.  Date     : Aug 31,1995
  7. GSNAKE API is jointly developed by the Information Technology Institute (ITI), Singapore, and the School of Applied Science, Nanyang Technological
  8. University (NTU), Singapore. 
  9. These software programs are available to the user without any license or royalty fees. Permission is hereby granted to use, copy, modify, and distribute this software and its documentation for any purpose. ITI and NTU gives no warranty, express, implied, or statuary for the software and/or documentation provided, including, without limitation, waranty of merchantibility and warranty of fitness for a particular purpose. The software provided hereunder is on an "as is"  basis, and ITI and NTU has no obligation to provide maintenance, support, updates, enhaucements, or modifications.
  10. GSNAKE API is available for any UNIX compatible system. User feedback, bugs, or software and manual suggestions should be sent via electronic mail to one of the following, who may or may not act on them as he/she desires :
  11. asschan@ntu.ac.sg
  12. kflai@iti.gov.sg
  13. **************************************************************************/
  14. #include "gsnake.h"
  15. #include "xwindow.h"
  16. /* Constructor and destructor methods */
  17. IMAGE::IMAGE(void)
  18. {
  19. data = NULL;
  20. ximg = NULL;
  21. row = col = 0;
  22. }
  23. IMAGE::~IMAGE(void)
  24. {
  25. reset();
  26. }
  27. /* reset _iMemFrees previously allocated memory. Allows reuse of IMAGE */
  28. void IMAGE::reset(void)
  29. {
  30. _iMemFree(data);
  31. if(ximg) XDestroyImage(ximg);
  32. data=NULL;
  33. ximg=NULL;
  34. row = col = 0;
  35. }
  36. /* Method init allocates memory for matrix. It returns an integer 1/0 
  37.    informing of memory allocation error if any */
  38. int IMAGE::init(int _row, int _col)
  39. {
  40. row = _row;
  41. col = _col;
  42. if( !(data = (float *) _iMemAlloc(_col*_row*sizeof(float))) ) {
  43.                 fprintf(stderr, "<IMAGE::init> : memory allocation errorn");
  44.                 return MEMORYERROR;
  45.         }
  46.         memset(data, 0, _col*_row*sizeof(float)) ;
  47. return NOERROR;
  48. }
  49. /* Method init_gauss33 performs memory allocation and initialises a gaussian
  50.    3x3 conditioning matrix. */
  51. void IMAGE::initAsGauss()
  52. {
  53. float term[3];
  54. int m,n;
  55. init(3,3); /* initialise new matrix */
  56. term[0] = term[2] = 0.2236;
  57. term[1] = 0.5477;
  58. for ( m = 0 ; m < row ; m++)
  59. for ( n = 0 ; n < col ; n++)
  60. put(m,n,term[m]*term[n]);
  61. }
  62.  
  63. /* Method print prints out all values in matrix */
  64. void IMAGE::print()
  65. {
  66. register short i, j;
  67. printf("row : %d  col : %dn", row, col);
  68. for (i = 0; i<row; i++) {
  69. for (j = 0; j<col; j++)
  70. printf("%f ", get(i,j));
  71. printf("n");
  72. }
  73. }
  74. /* Method read reads data in char form from filename. File type can be of 
  75.    image _bin file or sun raster file image. Returns error if otherwise. The    
  76.    image data is then converted to a floating point form. Read returns
  77.    an integer value indicating error if any .
  78.    Modified to be able to read raster file images -- 8/2
  79. */
  80. IMAGE::read(char *filename)
  81. {
  82. FILE *bin ;
  83. short format=_bin;
  84. unsigned char *buf ;
  85. unsigned char word[2];
  86. register int i, j ;
  87. unsigned char *cptr ;
  88. float *fptr ;
  89. int filecheck ;
  90. bin = fopen(filename, "rb") ;
  91. if( !bin ) {
  92. fprintf(stderr, "<IMAGE::read> : %s cannot be readn", 
  93. filename) ;
  94. return FILEIOERROR ;
  95. }
  96.        
  97. fread(&filecheck,sizeof(int),1,bin);
  98. rewind(bin);
  99. if (filecheck==0x59a66a95) (format= _ras);
  100. /* read file in BIN format */
  101. if (format == _bin)
  102. {
  103. /* read columns and rows */
  104. fread(word, sizeof(char), 2, bin) ;
  105. col = word[1]*256 + word[0] ;
  106. fread(word, sizeof(char), 2, bin) ;
  107. row = word[1]*256 + word[0] ;
  108. if( (init(row, col)) || !( buf = (unsigned char *)
  109.  _iMemAlloc(row*col*sizeof(unsigned char)))) {
  110.                  fprintf(stderr, 
  111.     "<IMAGE::init> : memory allocation errorn");
  112. return MEMORYERROR ;
  113. }
  114. fread(buf, sizeof(char), row*col, bin);
  115. /* casting char to float */
  116. for(i=0, cptr = buf, fptr = data; i<row; i++)
  117. for(j=0; j<col; j++, cptr++, fptr++)
  118. *fptr = (float) *cptr ;
  119. }
  120. /* Reading raster file format */
  121. if (format == _ras)
  122. {
  123. int header[8];
  124. int length ;
  125. int depth ;
  126. for (i=0;i<8;i++) header[i]=0;
  127. /* read the raster file header = 8 integers */
  128. fread(header, sizeof(int), 8, bin) ;  
  129. fseek(bin, header[7], 1);
  130. col = header[1];
  131. row = header[2];
  132. length = header[4] ;
  133. depth = header[3];
  134. if ( (init(row, col)) || 
  135.     !(buf=(unsigned char*) _iMemAlloc(length) ) ) {
  136.                  fprintf(stderr, 
  137.     "<IMAGE::init> : memory allocation errorn");
  138.      return MEMORYERROR ;
  139. }
  140. fread(buf, 1, length, bin) ;
  141. if( depth == 8 ) {
  142.     for (i=0,cptr=buf, fptr=data; i<row; i++) {
  143. for (j=0;j<col;j++, cptr++, fptr++)
  144. *fptr= (float) *cptr;
  145. /* Raster file rounds up to nearest 16 bits.
  146.    For odd cols, must increase by 1 byte */
  147. if (col%2) cptr++;
  148.     }
  149. }
  150. else if (depth == 1) {
  151.     unsigned char c  ;
  152.     for(i=0, cptr=buf, fptr=data; i<row; i++) 
  153.         for(j=0, c=128; j<col; fptr++) {
  154.          *fptr = ( *cptr & c ) ? GRAYLEVELRANGE-1 : 0.0 ;
  155.          ++j ;
  156.          if( !(j%8) ) {
  157.          c = 128 ;
  158.          cptr++;
  159.          }
  160.          else ( c = c >> 1 ) ;
  161.         }
  162. }
  163. else 
  164.    fprintf(stderr, 
  165.    "<IMAGE::init> : do not know how to handle depth = %dn", 
  166.     depth) ;
  167. };
  168. _iMemFree(buf);
  169. fclose(bin);
  170. return NOERROR;
  171. }
  172. /* Write saves the image data onto file, specified by file type format. either
  173.    bin or ras. Returns FILEIOERROR and MEMORYERROR if either occurs, other
  174.    wise returns NOERROR */
  175. IMAGE::write(char *filename, short format)
  176. {
  177. FILE *bin;
  178. short row, col;
  179. register int i,j;
  180. unsigned char word[2];
  181. float min,max,prange;
  182. float *fptr;
  183. unsigned char *cptr, *buf;
  184. bin = fopen(filename, "wb") ;
  185. if( !bin ) {
  186. fprintf(stderr, "<IMAGE::write> : %s cannot be openedn", 
  187. filename) ;
  188. return FILEIOERROR ;
  189. }
  190. col = getCol();
  191. row = getRow();
  192. if (!( buf = (unsigned char*) 
  193. _iMemAlloc(row*col*sizeof(unsigned char) )))
  194. return MEMORYERROR;
  195. /* Perform linear stretching of pixel values to full range of 255 */
  196. max=*data;
  197. min=*data;
  198. /* Get Max and Min pixel values in Image */
  199. for(i=0, fptr=data; i<row; i++)
  200. for(j=0; j<col; j++,fptr++)
  201. {
  202. if (*fptr > max) max = *fptr;
  203. else if (*fptr < min) min =*fptr;
  204. }
  205. /* Map to full range */
  206. prange = max - min;
  207. for(i=0, fptr=data; i<row; i++)
  208. for(j=0; j<col; j++,fptr++)
  209. *fptr = (*fptr-min)/prange * 255 ;
  210. /* casting float to char */
  211. for(i=0, cptr=buf,fptr = data; i<row; i++)
  212. for(j=0; j<col; j++, fptr++,cptr++)
  213. *cptr = (unsigned) *fptr  ;
  214. if (format == _bin)
  215. {
  216. /* Write row and col info */
  217. printf("nWriting to binary file ...n");
  218. word[1] = col / 256;
  219. word[0] = col - word[1]*256;
  220. fwrite(word, sizeof(char), 2, bin);
  221. word[1] = row /256;
  222. word[0] = row - word[1]*256;
  223. fwrite(word, sizeof(char), 2, bin);
  224. /* write rest of data */
  225. fwrite(buf, sizeof(unsigned char), row*col, bin);
  226. }
  227. else 
  228. { int header[8];
  229. char odd = col%2 ;
  230. for (i=0;i<8;i++) header[i]=0;
  231. printf("nWriting to sun raster file ... n");
  232. header[0] = 0x59a66a95;     /* Magic number */
  233. header[1] = col;     /* ras_width */
  234. header[2] = row;     /* ras_height */
  235. header[3] = 8;     /* ras_depth */
  236. header[4] = row * col;      /* ras_length */     
  237. header[5] = 1;     /* ras_type */
  238. header[6] = 1;      /* ras_maptype */
  239. header[7] = 0;     /* ras_maplength */
  240. fwrite(header, sizeof(int),8,bin);
  241. for (i=0,cptr=buf;i<row;i++,cptr+=col) {
  242. fwrite(cptr, sizeof(unsigned char),col,bin);
  243. if (odd) fputc(0,bin);
  244. }
  245. };
  246. _iMemFree(buf);
  247. fclose(bin);
  248. return NOERROR;
  249. }
  250. /* Method show creates an Xwindow to show the image.
  251.    Requires parameter blowup as magnification factor */
  252. void IMAGE::show(unsigned char blowup,int num,int h_offset, int v_offset)
  253. {
  254. /* raise or resize the window to fit */
  255. if (!h_offset && !v_offset) 
  256. xwin_raiseWindow(blowup*col*num, blowup*row);
  257. generateX(blowup);
  258. xwin_drawImg(ximg,h_offset*blowup,v_offset*blowup);
  259. }
  260. void IMAGE::generateX(unsigned char blowup)
  261. {
  262.  
  263. if( ximg ) XDestroyImage(ximg);
  264.         ximg = xwin_creatXimage(data, row, col, blowup);
  265. }
  266. IMAGE *IMAGE::correlate(
  267.         IMAGE *Template,
  268.         int RowStep,
  269.         int ColStep,
  270. char verbose)
  271. {
  272.         IMAGE *Output;
  273.         register short im, in, om, on;
  274.         short newrow, newcol;
  275. if(verbose) {
  276. fprintf(stdout, "ttCorrelating Image : ");
  277. fflush(stdout);
  278. }
  279.         /* create a new output buffer */
  280.         newrow = ROUNDOFF( (float) (getRow()) / (float) (RowStep) );
  281.         newcol = ROUNDOFF( (float) (getCol()) / (float) (ColStep) );
  282.         Output = new IMAGE;
  283. Output->init(newrow, newcol);
  284.         if( !Output ) {
  285.                 fprintf(stderr, "correlate : Cannot create new imagen");
  286.                 return NULL;
  287.         }
  288.         /* main correlation loop */
  289.         for (om = im = 0 ; om < newrow ; om++, im += RowStep) {
  290.     if( verbose && !(om%10)) {
  291. fprintf(stdout, "#");
  292. fflush(stdout);
  293.     }
  294.             for (on =in = 0 ; on < newcol ; on++, in += ColStep) {
  295.                 /* correlation is centered at (im, in) at input image */
  296.                 Output->put(om, on, innerProd(Template, im, in));
  297.             }
  298.         }
  299. if(verbose)
  300. fprintf(stdout, "n");
  301.         return Output;
  302. }
  303. /*
  304.  * Calculate the inner product (element by element product) between
  305.  * template and portion of input. This is the primary operation
  306.  * used in correlation and convolution
  307.  */
  308. double IMAGE::innerProd(
  309.         IMAGE *Template,
  310.         int InpRowIndex,        /* center of box in input matrix  */
  311.         int InpColIndex)
  312. {
  313.         register short i, j;
  314.         double RESULTS;
  315.         short tm_off, tn_off, _row, _col;
  316.         short m_ind, n_ind;
  317.         short temp_m, temp_n;
  318.         tm_off = (_row = Template->getRow())/ 2;
  319.         tn_off = (_col = Template->getCol())/ 2;
  320.         RESULTS = 0;
  321.         for( i = 0  ; i < _row ; i++) /* correlates */
  322.             for( j = 0 ; j < _col ;  j++) {
  323.                 m_ind = InpRowIndex + i - tm_off ;      /* index into input  */
  324.                 n_ind = InpColIndex + j - tn_off ;
  325.                 /* cap location to within input image range */
  326.                 temp_m = CAP(0, m_ind, row-1);
  327.                 temp_n = CAP(0, n_ind, col-1);
  328.                 RESULTS += Template->get(i,j) * get(temp_m, temp_n);
  329.               }
  330.         return RESULTS;
  331. }
  332. /* Method condition performs image conditioning based on histogram equalisation
  333.    Parameters required are  */
  334.    
  335. void IMAGE::condition(double low_pct, double high_pct, double low_val, double high_val, double imm_pow) 
  336. {
  337. int histo[GRAYLEVELRANGE+1] ;      /* histogram for edge conditioning */
  338.         double mapping[GRAYLEVELRANGE+1], cu[GRAYLEVELRANGE+1] ;
  339.         double size = row*col ;
  340.         register int i, j ;
  341.         memset(histo, 0, (GRAYLEVELRANGE+1)*sizeof(int) ) ;
  342. for (i=0; i<row; i++)
  343.     for (j=0; j<col; j++)
  344. ++histo[(int) CAP(0, *(data + i*col + j), GRAYLEVELRANGE)];
  345. /* get cumulative probability */
  346.         memset(cu, 0, (GRAYLEVELRANGE+1)*sizeof(double)) ;
  347.         for(i=0; i<GRAYLEVELRANGE+1; i++) {
  348.                 for(j=0; j<=i; j++)
  349.                         cu[i] += histo[j] ;
  350.                 cu[i] /= size ;
  351.         }
  352. /* obtain mapping table */
  353.         mapping[0] = 0 ;
  354.         for(i=1; i<GRAYLEVELRANGE+1; i++)  {
  355.            if( cu[i] <= low_pct )
  356.                 mapping[i] = cu[i]/low_pct*low_val ;
  357.            else if( cu[i] <= high_pct )
  358.                 mapping[i] = pow((cu[i]-low_pct)/(high_pct-low_pct), imm_pow)
  359.                                         *(high_val-low_val)+low_val ;
  360.            else
  361.                 mapping[i] = CAP(0, (cu[i]-high_pct)/(1-high_pct)*(1-high_val)
  362.                                         + high_val, 1) ;
  363.         }
  364.         for(i=0; i<row; i++)
  365.              for(j=0; j<col; j++)
  366.          *(data + i*col + j) =
  367.                      mapping[(int)CAP(0, *(data + i*col + j), GRAYLEVELRANGE)];
  368. }
  369. /*
  370.  * cut portion of give image. If memory allocation error will return a 
  371.    NULL pointer , otherwise returns pointer to new image. If sx and sy 
  372.    are illegal, will return NULL. Otherwise, it will size the box to the
  373.    bounds of the image
  374.  */
  375.  
  376. IMAGE *IMAGE::cut(int sx,int sy,int length, int height)
  377. {
  378. IMAGE *segment;
  379.         float *tptr,*sptr;
  380.         int i,j;
  381. /* return NULL if illegal parameter */
  382. if (  (sx>col) || (sy>row)  ) return NULL;
  383. /* Trap cut to limit to bounds of image size */
  384. if (sx+length > col) length = col - sx;
  385. if (sy+height > row) height = row - sy;
  386. if ( !( segment = new IMAGE ) ) {
  387. fprintf(stderr,
  388. "<IMAGE::cut>: memory allocation errorn");
  389. return NULL;
  390. }
  391.  
  392.         if (!(segment->init(height, length)) ) {
  393.                 sptr = data+col*sy+sx;
  394.                 tptr = segment->data;
  395.                 for ( i=0;i<height ;i++) {
  396.    for (j=0;j<length;j++,sptr++,tptr++) 
  397.                           *tptr = *sptr;
  398.                         sptr += col - length;
  399.                 }
  400.                 return(segment);
  401.         }
  402. }
  403. /* Method fill fills a specified square area with a value */
  404. /* If all co-ordinate parameters are 0, will fill the whole image */
  405. int IMAGE:: fill(float val,int sx, int sy, int length, int height)
  406. {int i,j;
  407. if (!length && !height && !sx && !sy )
  408. {
  409. length = col;
  410. height = row;
  411. };
  412. if ( (row<(sx+length)) || (col<(sy+height)) )
  413. return PARAMERROR;
  414. for (i=sy;i<height;i++)
  415. for(j=sx;j<length;j++)
  416. put(i,j,val);
  417. return NOERROR;
  418. };