Image.cc
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:24k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. //############################################################
  2. // Image.cc
  3. // Kari Pulli
  4. // 10/25/95
  5. //############################################################
  6. #include <iostream.h>
  7. #include <fstream.h>
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <assert.h>
  11. #include <string.h>
  12. #include <strings.h>
  13. #include <math.h>
  14. #include "Image.h"
  15. #ifndef linux
  16. #include <ifl/iflFile.h>
  17. #endif
  18. ////////////////////////////////////////////////////////////////
  19. ////////////////////////////////////////////////////////////////
  20. ////////////////////////////////////////////////////////////////
  21. void
  22. bwtorgba(unsigned char *b,unsigned char *l,int n) 
  23. {
  24.   while(n--) {
  25.     l[0] = *b;
  26.     l[1] = *b;
  27.     l[2] = *b;
  28.     l[3] = 0xff;
  29.     l += 4; b++;
  30.   }
  31. }
  32. void
  33. bwtorgb(unsigned char *b,unsigned char *l,int n) 
  34. {
  35.   while(n--) {
  36.     l[0] = *b;
  37.     l[1] = *b;
  38.     l[2] = *b;
  39.     l += 3; b++;
  40.   }
  41. }
  42. void
  43. rgbtorgba(unsigned char *r,unsigned char *g,unsigned char *b,
  44.   unsigned char *l,int n) 
  45. {
  46.   while(n--) {
  47.     l[0] = r[0];
  48.     l[1] = g[0];
  49.     l[2] = b[0];
  50.     l[3] = 0xff;
  51.     l += 4; r++; g++; b++;
  52.   }
  53. }
  54. void
  55. rgbatorgba(unsigned char *r,unsigned char *g,unsigned char *b,
  56.    unsigned char *a,unsigned char *l,int n) 
  57. {
  58.   while(n--) {
  59.     l[0] = r[0];
  60.     l[1] = g[0];
  61.     l[2] = b[0];
  62.     l[3] = a[0];
  63.     l += 4; r++; g++; b++; a++;
  64.   }
  65. }
  66. void
  67. rgbtorgb(unsigned char *r,unsigned char *g,unsigned char *b,
  68.  unsigned char *l,int n) 
  69. {
  70.   while(n--) {
  71.     l[0] = r[0];
  72.     l[1] = g[0];
  73.     l[2] = b[0];
  74.     l += 3; r++; g++; b++;
  75.   }
  76. }
  77. typedef struct _ImageRec {
  78.   unsigned short imagic;
  79.   unsigned short type;
  80.   unsigned short dim;
  81.   unsigned short xsize, ysize, zsize;
  82.   unsigned int min, max;
  83.   unsigned int wasteBytes;
  84.   char name[80];
  85.   unsigned long colorMap;
  86.   FILE *file;
  87.   unsigned char *tmp, *tmpR, *tmpG, *tmpB;
  88.   unsigned long rleEnd;
  89.   unsigned int *rowStart;
  90.   int *rowSize;
  91. } ImageRec;
  92. static void
  93. ConvertShort(unsigned short *array, long length) 
  94. {
  95.   unsigned long b1, b2;
  96.   unsigned char *ptr;
  97.   
  98.   ptr = (unsigned char *)array;
  99.   while (length--) {
  100.     b1 = *ptr++;
  101.     b2 = *ptr++;
  102.     *array++ = (b1 << 8) | (b2);
  103.   }
  104. }
  105. static void
  106. ConvertLong(unsigned *array, long length) 
  107. {
  108.   unsigned long b1, b2, b3, b4;
  109.   unsigned char *ptr;
  110.   
  111.   ptr = (unsigned char *)array;
  112.   while (length--) {
  113.     b1 = *ptr++;
  114.     b2 = *ptr++;
  115.     b3 = *ptr++;
  116.     b4 = *ptr++;
  117.     *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
  118.   }
  119. }
  120. static ImageRec *
  121. ImageOpen(const char *fileName)
  122. {
  123.   union {
  124.     int  testWord;
  125.     char testByte[4];
  126.   } endianTest;
  127.   ImageRec *image;
  128.   int swapFlag;
  129.   int x;
  130.   
  131.   endianTest.testWord = 1;
  132.   if (endianTest.testByte[0] == 1) {
  133.     swapFlag = 1;
  134.   } else {
  135.     swapFlag = 0;
  136.   }
  137.   
  138.   image = (ImageRec *)malloc(sizeof(ImageRec));
  139.   if (image == NULL) {
  140.     fprintf(stderr, "Image: Out of memory!n");
  141.     exit(1);
  142.   }
  143.   if ((image->file = fopen(fileName, "rb")) == NULL) {
  144.     perror(fileName);
  145.     exit(1);
  146.   }
  147.   
  148.   fread(image, 1, 12, image->file);
  149.   
  150.   if (swapFlag) {
  151.     ConvertShort(&image->imagic, 6);
  152.   }
  153.   
  154.   image->tmp  = (unsigned char *)malloc(image->xsize*256);
  155.   image->tmpR = (unsigned char *)malloc(image->xsize*256);
  156.   image->tmpG = (unsigned char *)malloc(image->xsize*256);
  157.   image->tmpB = (unsigned char *)malloc(image->xsize*256);
  158.   if (image->tmp  == NULL || image->tmpR == NULL || 
  159.       image->tmpG == NULL || image->tmpB == NULL) {
  160.     fprintf(stderr, "Image: Out of memory!n");
  161.     exit(1);
  162.   }
  163.   
  164.   if ((image->type & 0xFF00) == 0x0100) {
  165.     x = image->ysize * image->zsize * sizeof(unsigned);
  166.     image->rowStart = (unsigned *)malloc(x);
  167.     image->rowSize = (int *)malloc(x);
  168.     if (image->rowStart == NULL || image->rowSize == NULL) {
  169.       fprintf(stderr, "Image: Out of memory!n");
  170.       exit(1);
  171.     }
  172.     image->rleEnd = 512 + (2 * x);
  173.     fseek(image->file, 512, SEEK_SET);
  174.     fread(image->rowStart, 1, x, image->file);
  175.     fread(image->rowSize, 1, x, image->file);
  176.     if (swapFlag) {
  177.       ConvertLong(image->rowStart, x/sizeof(unsigned));
  178.       ConvertLong((unsigned *)image->rowSize, x/sizeof(int));
  179.     }
  180.   }
  181.   return image;
  182. }
  183. static void
  184. ImageClose(ImageRec *image) 
  185. {
  186.   fclose(image->file);
  187.   free(image->tmp);
  188.   free(image->tmpR);
  189.   free(image->tmpG);
  190.   free(image->tmpB);
  191.   free(image);
  192. }
  193. static void
  194. ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) 
  195. {
  196.   unsigned char *iPtr, *oPtr, pixel;
  197.   int count;
  198.   
  199.   if ((image->type & 0xFF00) == 0x0100) {
  200.     fseek(image->file, image->rowStart[y+z*image->ysize], SEEK_SET);
  201.     fread(image->tmp, 1, (unsigned int)
  202.   image->rowSize[y+z*image->ysize], image->file);
  203.     
  204.     iPtr = image->tmp;
  205.     oPtr = buf;
  206.     while (1) {
  207.       pixel = *iPtr++;
  208.       count = (int)(pixel & 0x7F);
  209.       if (!count) {
  210. return;
  211.       }
  212.       if (pixel & 0x80) {
  213. while (count--) {
  214.   *oPtr++ = *iPtr++;
  215. }
  216.       } else {
  217. pixel = *iPtr++;
  218. while (count--) {
  219.   *oPtr++ = pixel;
  220. }
  221.       }
  222.     }
  223.   } else {
  224.     fseek(image->file, 512+(y*image->xsize)+
  225.   (z*image->xsize*image->ysize), SEEK_SET);
  226.     fread(buf, 1, image->xsize, image->file);
  227.   }
  228. }
  229. unsigned *
  230. read_texture(char *name, int *width, int *height, int *components) 
  231. {
  232.   unsigned *base, *lptr;
  233.   unsigned char *rbuf, *gbuf, *bbuf, *abuf;
  234.   ImageRec *image;
  235.   int y;
  236.   
  237.   image = ImageOpen(name);
  238.   
  239.   if(!image)
  240.     return NULL;
  241.   (*width)=image->xsize;
  242.   (*height)=image->ysize;
  243.   (*components)=image->zsize;
  244.   base = (unsigned *)malloc((*width)*(*height)*sizeof(unsigned));
  245.   rbuf = (unsigned char *)malloc((*width)*sizeof(unsigned char));
  246.   gbuf = (unsigned char *)malloc((*width)*sizeof(unsigned char));
  247.   bbuf = (unsigned char *)malloc((*width)*sizeof(unsigned char));
  248.   abuf = (unsigned char *)malloc((*width)*sizeof(unsigned char));
  249.   if(!base || !rbuf || !gbuf || !bbuf)
  250.     return NULL;
  251.   lptr = base;
  252.   for(y=0; y<image->ysize; y++) {
  253.     if(image->zsize>=4) {
  254.       ImageGetRow(image,rbuf,y,0);
  255.       ImageGetRow(image,gbuf,y,1);
  256.       ImageGetRow(image,bbuf,y,2);
  257.       ImageGetRow(image,abuf,y,3);
  258.       rgbatorgba(rbuf,gbuf,bbuf,abuf,(unsigned char *)lptr, 
  259.        image->xsize);
  260.       lptr += image->xsize;
  261.     } else if(image->zsize==3) {
  262.       ImageGetRow(image,rbuf,y,0);
  263.       ImageGetRow(image,gbuf,y,1);
  264.       ImageGetRow(image,bbuf,y,2);
  265.       rgbtorgba(rbuf,gbuf,bbuf,(unsigned char *)lptr,image->xsize);
  266.       lptr += image->xsize;
  267.     } else {
  268.       ImageGetRow(image,rbuf,y,0);
  269.       bwtorgba(rbuf,(unsigned char *)lptr,image->xsize);
  270.       lptr += image->xsize;
  271.     }
  272.   }
  273.   ImageClose(image);
  274.   free(rbuf);
  275.   free(gbuf);
  276.   free(bbuf);
  277.   free(abuf);
  278.   
  279.   return (unsigned *) base;
  280. }
  281. unsigned *
  282. read_textureRGB(char *name, int *width, int *height) 
  283. {
  284.   unsigned *base, *lptr;
  285.   unsigned char *rbuf, *gbuf, *bbuf, *abuf;
  286.   ImageRec *image;
  287.   int y;
  288.   
  289.   image = ImageOpen(name);
  290.   
  291.   if(!image)
  292.     return NULL;
  293.   (*width)=image->xsize;
  294.   (*height)=image->ysize;
  295.   base = (unsigned *)malloc((*width)*(*height)*sizeof(unsigned));
  296.   rbuf = (unsigned char *)malloc((*width)*sizeof(unsigned char));
  297.   gbuf = (unsigned char *)malloc((*width)*sizeof(unsigned char));
  298.   bbuf = (unsigned char *)malloc((*width)*sizeof(unsigned char));
  299.   abuf = (unsigned char *)malloc((*width)*sizeof(unsigned char));
  300.   if(!base || !rbuf || !gbuf || !bbuf)
  301.     return NULL;
  302.   lptr = base;
  303.   for(y=0; y<image->ysize; y++) {
  304.     if(image->zsize>=4) {
  305.       ImageGetRow(image,rbuf,y,0);
  306.       ImageGetRow(image,gbuf,y,1);
  307.       ImageGetRow(image,bbuf,y,2);
  308.       ImageGetRow(image,abuf,y,3);
  309.       rgbtorgb(rbuf,gbuf,bbuf,(unsigned char *)lptr,image->xsize);
  310.       lptr += image->xsize;
  311.     } else if(image->zsize==3) {
  312.       ImageGetRow(image,rbuf,y,0);
  313.       ImageGetRow(image,gbuf,y,1);
  314.       ImageGetRow(image,bbuf,y,2);
  315.       rgbtorgb(rbuf,gbuf,bbuf,(unsigned char *)lptr,image->xsize);
  316.       lptr += image->xsize;
  317.     } else {
  318.       ImageGetRow(image,rbuf,y,0);
  319.       bwtorgb(rbuf,(unsigned char *)lptr,image->xsize);
  320.       lptr += image->xsize;
  321.     }
  322.   }
  323.   ImageClose(image);
  324.   free(rbuf);
  325.   free(gbuf);
  326.   free(bbuf);
  327.   free(abuf);
  328.   
  329.   return (unsigned *) base;
  330. }
  331. ////////////////////////////////////////////////////////////////
  332. ////////////////////////////////////////////////////////////////
  333. ////////////////////////////////////////////////////////////////
  334. void 
  335. Image::create(const int w, const int h, const int d)
  336. {
  337.   if (w*h*d > xsize*ysize*dim) {
  338.     // need more room
  339.     delete[] data;
  340.     delete[] _data;
  341.     _data = new uchar[w*h*d];
  342.     data =  new uchar *[h];
  343.   }
  344.   if (w != xsize || d != dim) {
  345.     for (int i=0; i<h; i++) data[i] = &_data[w*d*i];
  346.     xsize = w;  dim = d;
  347.   }
  348.   ysize = h;
  349. }  
  350. Image::Image()
  351. : xsize(0), ysize(0), data(NULL), _data(NULL), dim(0)
  352. {
  353. }
  354. Image::Image(const Image& a)
  355. : xsize(0), ysize(0), dim(0), data(NULL), _data(NULL)
  356. {
  357.   create(a.xsize, a.ysize, a.dim);
  358.   //bcopy(a._data, _data, xsize*ysize*dim);
  359.   memcpy(_data, a._data, xsize*ysize*dim);
  360. }
  361. Image &
  362. Image::operator=(const Image& a)
  363. {
  364.   if (&a != this) {
  365.     //xsize = ysize = dim = 0;
  366.     //data = NULL;
  367.     //_data = NULL;
  368.     create(a.xsize, a.ysize, a.dim);
  369.     //bcopy(a._data, _data, xsize*ysize*dim);
  370.     memcpy(_data, a._data, xsize*ysize*dim);
  371.   }
  372.   return *this;
  373. }
  374. Image::Image(const int w, const int h, const int d)
  375. : data(NULL), _data(NULL), dim(0)
  376. {
  377.   create (w,h,d);
  378. }
  379. Image::~Image()
  380. {
  381.   delete[] data;
  382.   delete[] _data;
  383. }
  384. ostream &operator <<(ostream &out, Image &im)
  385. {
  386.   out << im.xsize << " x " << im.ysize << " image";
  387.   return out;
  388. }
  389. /*
  390. void 
  391. Image::rgb2bw()
  392. {
  393.   unsigned char tmp;
  394.   if (bw == 1) return;
  395.   for (int i=0; i<xsize*ysize; i++) {
  396.     tmp = (unsigned char)(double(_data[i].red())   * 0.30 +
  397.   double(_data[i].green()) * 0.59 +
  398.   double(_data[i].blue())  * 0.11);
  399.     _data[i] = Pixel(tmp, tmp, tmp);
  400.   }
  401.   bw = 1;
  402. }
  403. */
  404. void
  405. Image::toRGBA(void)
  406. {
  407.   assert(data && _data);
  408.   if (dim == 4) return;
  409.   uchar *new_data = new uchar[xsize*ysize*4];
  410.   uchar *ptr_old = _data;
  411.   uchar *ptr_new = new_data;
  412.   for (int i=0; i<xsize*ysize; i++) {
  413.     uchar tmp = *ptr_old++;
  414.     if        (dim == 3) {
  415.       *ptr_new++ = tmp;
  416.       *ptr_new++ = *ptr_old++;
  417.       *ptr_new++ = *ptr_old++;
  418.       *ptr_new++ = 255;
  419.     } else if (dim == 1) {
  420.       *ptr_new++ = tmp;
  421.       *ptr_new++ = tmp;
  422.       *ptr_new++ = tmp;
  423.       *ptr_new++ = 255;
  424.     } else if (dim == 2) {
  425.       *ptr_new++ = tmp;
  426.       *ptr_new++ = tmp;
  427.       *ptr_new++ = tmp;
  428.       *ptr_new++ = *ptr_old++;
  429.     }     
  430.   }
  431.   delete[] _data;
  432.   _data = new_data;
  433.   dim = 4;
  434.   for (i=0; i<ysize; i++) data[i] = &_data[xsize*dim*i];
  435. }
  436. void
  437. Image::toRGB(void)
  438. {
  439.   assert(data && _data);
  440.   if (dim == 3) return;
  441.   uchar *new_data = new uchar[xsize*ysize*3];
  442.   uchar *ptr_old = _data;
  443.   uchar *ptr_new = new_data;
  444.   for (int i=0; i<xsize*ysize; i++) {
  445.     uchar tmp = *ptr_old++;
  446.     if        (dim == 4) {
  447.       *ptr_new++ = tmp;
  448.       *ptr_new++ = *ptr_old++;
  449.       *ptr_new++ = *ptr_old++;
  450.       ptr_old++;
  451.     } else if (dim == 1) {
  452.       *ptr_new++ = tmp;
  453.       *ptr_new++ = tmp;
  454.       *ptr_new++ = tmp;
  455.     } else if (dim == 2) {
  456.       *ptr_new++ = tmp;
  457.       *ptr_new++ = tmp;
  458.       *ptr_new++ = tmp;
  459.       ptr_old++;
  460.     }     
  461.   }
  462.   delete[] _data;
  463.   _data = new_data;
  464.   dim = 3;
  465.   for (i=0; i<ysize; i++) data[i] = &_data[xsize*dim*i];
  466. }
  467. void 
  468. Image::RGB2HSV(void)
  469. {
  470.   assert(dim == 3);
  471.   float h,s,min,max; // max == v
  472.   for (int v=0; v<ysize; v++) {
  473.     for (int u=0; u<xsize; u++) {
  474.       uchar *tmp = getValues(u,v);
  475.       min = max = tmp[0];
  476.       if      (tmp[1] < min) min = tmp[1];
  477.       else if (tmp[1] > max) max = tmp[1];
  478.       if      (tmp[2] < min) min = tmp[2];
  479.       else if (tmp[2] > max) max = tmp[2];
  480.       if (max != 0) s = (max - min)/max;
  481.       else          s = 0;
  482.       if (s == 0)   h = 0;
  483.       else {
  484. float delta = max - min;
  485. if      (tmp[0] == max) h = (tmp[1]-tmp[2])/delta;
  486. else if (tmp[1] == max) h = 2 + (tmp[2]-tmp[0])/delta;
  487. else if (tmp[2] == max) h = 4 + (tmp[0]-tmp[1])/delta;
  488. if (h < 0.0) h += 6.0;
  489. h /= 6.0;
  490.       }
  491.       tmp[0] = h*255.0;
  492.       //tmp[1] = s*255.0;
  493.       //tmp[0] = max*h;
  494.       tmp[1] = max*s;
  495.       tmp[2] = max;
  496.     }
  497.   }
  498. }
  499. void 
  500. Image::HSV2RGB(void)
  501. {
  502.   assert(dim == 3);
  503.   float h,s;
  504.   for (int v=0; v<ysize; v++) {
  505.     for (int u=0; u<xsize; u++) {
  506.       uchar *tmp = getValues(u,v);
  507.       if (tmp[1] == 0) {
  508. // zero saturation
  509. tmp[0] = tmp[1] = tmp[2];
  510.       } else {
  511. if (tmp[0] == 255) h = 0.0;
  512. else               h = tmp[0]/255.0 * 6.0;
  513. int i = floor(h);
  514. float f = h - i;
  515. s = float(tmp[1]) / float(tmp[2]);
  516. float p = tmp[2] * (1.0-s);
  517. float q = tmp[2] * (1.0-s * f);
  518. float t = tmp[2] * (1.0-s * (1.0-f));
  519. switch(i) {
  520. case 0:
  521.   tmp[0] = tmp[2];
  522.   tmp[1] = t;
  523.   tmp[2] = p;
  524.   break;
  525. case 1:
  526.   tmp[0] = q;
  527.   tmp[1] = tmp[2];
  528.   tmp[2] = p;
  529.   break;
  530. case 2:
  531.   tmp[0] = p;
  532.   tmp[1] = tmp[2];
  533.   tmp[2] = t;
  534.   break;
  535. case 3:
  536.   tmp[0] = p;
  537.   tmp[1] = q;
  538.   //tmp[2] = tmp[2];
  539.   break;
  540. case 4:
  541.   tmp[0] = t;
  542.   tmp[1] = p;
  543.   //tmp[2] = tmp[2];
  544.   break;
  545. case 5:
  546.   tmp[0] = tmp[2];
  547.   tmp[1] = p;
  548.   tmp[2] = q;
  549.   break;
  550. }
  551.       }
  552.     }
  553.   }
  554. }
  555. void 
  556. Image::RGB2rgI(void)
  557. {
  558.   assert(dim == 3);
  559.   for (int v=0; v<ysize; v++) {
  560.     for (int u=0; u<xsize; u++) {
  561.       uchar *tmp = getValues(u,v);
  562.       int sum = int(tmp[0]) + int(tmp[1]) + int(tmp[2]);
  563.       if (sum < 10) {
  564. tmp[0] = tmp[1] = 85;
  565. tmp[2] = (sum / 3.0) + .5;
  566.       } else {
  567. tmp[0] = 255.0 * float(tmp[0]) / sum;
  568. tmp[1] = 255.0 * float(tmp[1]) / sum;
  569. tmp[2] = (sum / 3.0) + .5;
  570. if (sum < 45) {
  571.   float frac = float(45-sum)/36.0;
  572.   tmp[0] += (85-int(tmp[0])) * frac;
  573.   tmp[1] += (85-int(tmp[1])) * frac;
  574. }
  575.       }
  576.     }
  577.   }
  578. }
  579. void 
  580. Image::rgI2RGB(void)
  581. {
  582.   assert(dim == 3);
  583.   for (int v=0; v<ysize; v++) {
  584.     for (int u=0; u<xsize; u++) {
  585.       uchar *tmp = getValues(u,v);
  586.       uchar b = 255 - tmp[0] - tmp[1];
  587.       float frac = 3.0 * tmp[2] / 255.0;
  588.       tmp[0] = frac * tmp[0];
  589.       tmp[1] = frac * tmp[1];
  590.       tmp[2] = frac * b;
  591.     }
  592.   }
  593. }
  594. void
  595. Image::resize(int w, int h)
  596. {
  597.   // get new memory
  598.   uchar *n_data = new uchar[w*h*dim];
  599.   uchar **ndata = new uchar *[h];
  600.   for (int i=0; i<h; i++) ndata[i] = &n_data[w*dim*i];
  601.   // copy the data
  602.   int maxy = (h > ysize ? ysize : h);
  603.   int maxx = (w > xsize ? xsize : w);
  604.   for (i=0; i<maxy; i++) 
  605.     //bcopy(&_data[i*xsize*dim], &n_data[i*w*dim], maxx*dim);
  606.     memcpy(&n_data[i*w*dim], &_data[i*xsize*dim], maxx*dim);
  607.   // delete old space
  608.   delete[] data;
  609.   delete[] _data;
  610.   // write the correct info
  611.   _data = n_data;
  612.   data  = ndata;
  613.   xsize = w;
  614.   ysize = h;
  615. }
  616. void
  617. Image::flip(void)
  618. {
  619.   int row = dim*xsize;
  620.   uchar *buf = new uchar[row];
  621.  
  622.   for (int i=0; i<ysize/2; i++) {
  623.     memcpy(buf, data[i], row);
  624.     memcpy(data[i], data[ysize-i-1], row);
  625.     memcpy(data[ysize-i-1], buf, row);    
  626.   }
  627.  
  628.   delete[] buf;
  629. }
  630. // assume input is a single channel image with values 0 and 255
  631. // calculate distances from 0 by looking at neighbors and 
  632. // replacing the value with the min(nbors) + 1
  633. // do i iterations
  634. // use 8-nborhood
  635. // note: writes over itself while processing
  636. void
  637. Image::distances(int iter)
  638. {
  639.   for (int i=0; i<iter; i++) {
  640.     int vi = i%2;
  641.     for (int v=vi?0:ysize-1; 
  642.  vi?(v<ysize):(v>=0);
  643.  vi?v++:v--) {
  644.       int ui = (i%4)>>1;
  645.       for (int u=ui?0:xsize-1; 
  646.    ui?(u<xsize):(u>=0);
  647.    ui?u++:u--) {
  648. if (getR(u,v) == 0) continue;
  649. int min = 255;
  650. for (int j=-1; j<=1; j++) {
  651.   for (int k=-1; k<=1; k++) {
  652.     if (k==0 && j==0) continue;
  653.     if (inside(u+j, v+k)) {
  654.       uchar tmp = getR(u+j, v+k);
  655.       if (tmp < min) min = tmp;
  656.     }
  657.   }
  658. }
  659. if (min < 255) setValue(u,v,min+1);
  660.       }
  661.     }
  662.   }
  663. }
  664. // assume input is a single channel image with values 0 and 255
  665. // calculate distances from 0, use 4-nborhood
  666. // a fast inaccurate scanline version
  667. // note: writes over itself while processing
  668. void
  669. Image::dist4fast(void)
  670. {
  671.   int u,v;
  672.   // scan left to right
  673.   for (v=0; v<ysize; v++) {
  674.     uchar *ptr = &data[v][0];
  675.     for (u=1; u<xsize; u++, ptr++) {
  676.       if (ptr[1] > ptr[0]) ptr[1] = ptr[0]+1;
  677.     }
  678.   }
  679.   // scan down to up
  680.   for (u=0; u<xsize; u++) {
  681.     uchar *ptr = &data[0][u];
  682.     for (v=1; v<ysize; v++, ptr+=xsize) {
  683.       if (ptr[xsize] > ptr[0]) ptr[xsize] = ptr[0]+1;
  684.     }
  685.   }
  686.   // scan right to left
  687.   for (v=0; v<ysize; v++) {
  688.     uchar *ptr = &data[v][xsize-2];
  689.     for (u=xsize-2; u>=0; u--, ptr--) {
  690.       if (ptr[0] > ptr[1]) ptr[0] = ptr[1]+1;
  691.     }
  692.   }
  693.   // scan up to down
  694.   for (u=0; u<xsize; u++) {
  695.     uchar *ptr = &data[ysize-2][u];
  696.     for (v=ysize-2; v>=0; v--, ptr-=xsize) {
  697.       if (ptr[0] > ptr[xsize]) ptr[0] = ptr[xsize]+1;
  698.     }
  699.   }
  700. }
  701. int 
  702. Image::read(const char *fname, Format format, int w, int h)
  703. {
  704.   int i;
  705.   if (w==0) {
  706.     w=xsize; h=ysize;
  707.   }
  708.   
  709.   switch (format) {
  710.   case WSU:
  711.     {
  712.       ifstream from (fname);
  713.       if (!from) {
  714. cerr << "Cannot open inputfile " << fname << endl;
  715. return 0;
  716.       }
  717.       create (w, h, 1);
  718.       for (i=h-1; i>=0; i--)
  719. from.read(&_data[i*w], w);
  720.     }
  721.     break;
  722.   case SGI:
  723. #ifndef linux
  724.     {
  725.       iflStatus sts;
  726.       iflFile* file = iflFile::open(fname, O_RDONLY, &sts);
  727.       if (sts != iflOKAY) {
  728. cerr << "Cannot open inputfile " << fname << endl;
  729. return 0;
  730.       }
  731.       // read the entire image (just the first plane in z if image has depth)
  732.       // into a buffer of unsiged chars
  733.       iflSize dims;
  734.       file->getDimensions(dims);
  735. //      unsigned char* data = new unsigned char[dims.x*dims.y*dims.c];
  736. //      assert(dims.c == 1 || dims.c == 3);
  737. //      assert(w == dims.x && h == dims.y);
  738.       create(dims.x, dims.y, dims.c);
  739.       iflConfig cfg(iflUChar, iflInterleaved);
  740.       sts = file->getTile(0, 0, 0, dims.x, dims.y, 1, _data, &cfg);
  741.       if (sts != iflOKAY) {
  742. cerr << "Failed reading inputfile " << fname << endl;
  743. return 0;
  744.       }
  745.       // close the file
  746.       file->close();
  747.       /*      
  748.       ImageRec *image = ImageOpen(fname);
  749.       
  750.       if (!image) return 0;
  751.       
  752.       create(image->xsize, image->ysize, image->zsize);
  753.       uchar *rbuf = new uchar[xsize];
  754.       uchar *gbuf = new uchar[xsize];
  755.       uchar *bbuf = new uchar[xsize];
  756.       if (!rbuf || !gbuf || !bbuf) return NULL;
  757.       uchar *lptr = _data;
  758.       int step = 3*xsize;
  759.       for (int y=0; y<image->ysize; y++) {
  760. ImageGetRow(image,rbuf,y,0);
  761. if (image->zsize>=4) {
  762.   ImageGetRow(image,gbuf,y,1);
  763.   ImageGetRow(image,bbuf,y,2);
  764.   rgbtorgb(rbuf,gbuf,bbuf,lptr,xsize);
  765.   ImageGetRow(image,rbuf,y,3);
  766. } else if (image->zsize==3) {
  767.   ImageGetRow(image,gbuf,y,1);
  768.   ImageGetRow(image,bbuf,y,2);
  769.   rgbtorgb(rbuf,gbuf,bbuf,lptr,xsize);
  770. } else {
  771.   bwtorgb(rbuf,lptr,xsize);
  772. }
  773. lptr += step;
  774.       }
  775.       ImageClose(image);
  776.       delete[] rbuf;
  777.       delete[] gbuf;
  778.       delete[] bbuf;
  779.       */
  780.     }
  781.     break;
  782. #else
  783.     return 0;
  784. #endif
  785.   case RAWRGB:
  786.     {
  787.       ifstream from (fname);
  788.       if (!from) {
  789. cerr << "Cannot open inputfile " << fname << endl;
  790. return 0;
  791.       }
  792.       create(w,h,3);
  793.       from.read(_data, w*h*3);
  794.     }
  795.     break;
  796.   case FLOATRGB:
  797.     {
  798.       ifstream from (fname);
  799.       if (!from) {
  800. cerr << "Cannot open inputfile " << fname << endl;
  801. return 0;
  802.       }
  803.       int cnt = w*h*3;
  804.       float *tmp = new float[cnt];
  805.       create(w,h,3);
  806.       from.read((char *)tmp, cnt*sizeof(float));
  807.       for (i=0; i<cnt; i++) {
  808. _data[i] = (uchar)(255.999999 * tmp[i]);
  809.       }
  810.     }
  811.     break;
  812.   default:
  813.     cerr << "Unrecognized format" << endl;
  814.     return 0;
  815.   }
  816.   return 1;
  817. }
  818. int 
  819. Image::write(const char *fname, Format format)
  820. {
  821.   switch (format) {
  822.   case WSU:
  823.     {
  824.       cout << "Saving raw" << endl;
  825.       ofstream to (fname);
  826.       if (!to) {
  827. cerr << "Cannot open outputfile " << fname << endl;
  828. return 0;
  829.       }
  830.       for (int i=ysize-1; i>=0; i--)
  831. to.write(&_data[i*xsize], xsize);
  832.     }
  833.     break;
  834.   case SGI:
  835. #ifndef linux
  836.     {
  837.       cout << "Saving rgb" << endl;
  838.       // create a one-channel, unsigned char image file
  839.       iflSize dims(xsize, ysize, dim);
  840.       iflFileConfig fc(&dims, iflUChar);
  841.       fc.setCompression(iflSGIRLE);
  842.       iflStatus sts;
  843.       iflFile* file = iflFile::create(fname, NULL, &fc,NULL,&sts);
  844.       if (sts != iflOKAY) {
  845. cerr << "Error in creating file " << fname << endl;
  846. return 0;
  847.       }
  848.       // write a tile of data to it
  849.       sts = file->setTile(0, 0, 0, xsize, ysize, 1, _data);
  850.       if (sts != iflOKAY) {
  851. cerr <<"Error in setting the tile for file "<<fname<<endl;
  852. return 0;
  853.       }
  854.       file->close();
  855.     }
  856.     break;
  857. #else
  858.     return 0;
  859. #endif
  860.   default:
  861.     cerr << "Unknown format" << endl;
  862.     return 0;
  863.   }
  864.   int i=0;
  865.   i++;
  866.   return i;
  867. }
  868. Image
  869. Image::shrink(int factor) const
  870. {
  871.   int sx = xsize/factor;
  872.   int sy = ysize/factor;
  873.   Image simg(sx, sy, dim);
  874.   int fact2 = factor*factor;
  875.   uchar col[4];
  876.   col[0] = col[1] = col[2] = col[3] = 0;
  877.   for (int v=0; v<sy; v++) {
  878.     int y = v*factor;
  879.     for (int u=0; u<sx; u++) {
  880.       int x = u*factor;
  881.       for (int d=0; d<dim; d++) {
  882. int tmp = 0;
  883. for (int i=0; i<factor; i++) {
  884.   for (int j=0; j<factor; j++) {
  885.     tmp += at(x+i, y+j)[d];
  886.   }
  887. }
  888. col[d] = (tmp + fact2/2) / fact2;
  889.       }
  890.       simg.setValue(u,v,col[0],col[1],col[2],col[3]);
  891.     }
  892.   }
  893.   return simg;
  894. }
  895. void
  896. Image::shrink_by_half(Image &simg) const
  897. {
  898.   int sx = xsize>>1;
  899.   int sy = ysize>>1;
  900.   simg.create(sx, sy, dim);
  901.   int tmp[4];
  902.   int u,v,x,y;
  903.   uchar *ptr;
  904.   if (dim == 4) {
  905.     for (v=0,y=0; v<sy; v++, y+=2) {
  906.       for (u=0,x=0; u<sx; u++, x+=2) {
  907. ptr = at(x,y);
  908. tmp[0] = ptr[0] + ptr[4];
  909. tmp[1] = ptr[1] + ptr[5];
  910. tmp[2] = ptr[2] + ptr[6];
  911. tmp[3] = ptr[3] + ptr[7];
  912. ptr += xsize*4;
  913. tmp[0] += ptr[0] + ptr[4];
  914. tmp[1] += ptr[1] + ptr[5];
  915. tmp[2] += ptr[2] + ptr[6];
  916. tmp[3] += ptr[3] + ptr[7];
  917. ptr = simg.getValues(u,v);
  918. ptr[0] = (tmp[0]+2)>>2;
  919. ptr[1] = (tmp[1]+2)>>2;
  920. ptr[2] = (tmp[2]+2)>>2;
  921. ptr[3] = (tmp[3]+2)>>2;
  922.       }
  923.     }
  924.   } else if (dim == 3) {
  925.     for (v=0,y=0; v<sy; v++, y+=2) {
  926.       for (u=0,x=0; u<sx; u++, x+=2) {
  927. ptr = at(x,y);
  928. tmp[0] = ptr[0] + ptr[3];
  929. tmp[1] = ptr[1] + ptr[4];
  930. tmp[2] = ptr[2] + ptr[5];
  931. ptr += xsize*3;
  932. tmp[0] += ptr[0] + ptr[3];
  933. tmp[1] += ptr[1] + ptr[4];
  934. tmp[2] += ptr[2] + ptr[5];
  935. ptr = simg.getValues(u,v);
  936. ptr[0] = (tmp[0]+2)>>2;
  937. ptr[1] = (tmp[1]+2)>>2;
  938. ptr[2] = (tmp[2]+2)>>2;
  939.       }
  940.     }
  941.   } else if (dim == 2) {
  942.     for (v=0,y=0; v<sy; v++, y+=2) {
  943.       for (u=0,x=0; u<sx; u++, x+=2) {
  944. ptr = at(x,y);
  945. tmp[0] = ptr[0] + ptr[2];
  946. tmp[1] = ptr[1] + ptr[3];
  947. ptr += xsize*2;
  948. tmp[0] += ptr[0] + ptr[2];
  949. tmp[1] += ptr[1] + ptr[3];
  950. ptr = simg.getValues(u,v);
  951. ptr[0] = (tmp[0]+2)>>2;
  952. ptr[1] = (tmp[1]+2)>>2;
  953.       }
  954.     }
  955.   } else {
  956.     for (v=0,y=0; v<sy; v++, y+=2) {
  957.       for (u=0,x=0; u<sx; u++, x+=2) {
  958. ptr = at(x,y);
  959. tmp[0] = ptr[0] + ptr[1];
  960. ptr += xsize;
  961. tmp[0] += ptr[0] + ptr[1];
  962. ptr = simg.getValues(u,v);
  963. ptr[0] = (tmp[0]+2)>>2;
  964.       }
  965.     }
  966.   }
  967. }
  968. // return an image warped by the projective transformation
  969. // [x' y' w'] = [u v w] M
  970. Image
  971. Image::warp(float m[3][3]) const
  972. {
  973.   // first, invert the matrix by taking its adjoint
  974.   // works because it's a projection, scale invariant
  975.   float Mi[3][3];
  976.   Mi[0][0] = m[1][1]*m[2][2] - m[1][2]*m[2][1];
  977.   Mi[0][1] = m[0][2]*m[2][1] - m[0][1]*m[2][2];
  978.   Mi[0][2] = m[0][1]*m[1][2] - m[0][2]*m[1][1];
  979.   Mi[1][0] = m[1][2]*m[2][0] - m[1][0]*m[2][2];
  980.   Mi[1][1] = m[0][0]*m[2][2] - m[0][2]*m[2][0];
  981.   Mi[1][2] = m[0][2]*m[1][0] - m[0][0]*m[1][2];
  982.   Mi[2][0] = m[1][0]*m[2][1] - m[1][1]*m[2][0];
  983.   Mi[2][1] = m[0][1]*m[2][0] - m[0][0]*m[2][1];
  984.   Mi[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0];
  985.   
  986.   Image im(xsize, ysize, dim);
  987.   int tmp[4], cnt;
  988.   float x,y;
  989.   uchar *val;
  990.   for (int v=0; v<ysize; v++) {
  991.     for (int u=0; u<xsize; u++) {
  992.       tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
  993.       cnt = 0;
  994.       for (int i=0; i<=2; i++) {
  995. for (int j=0; j<=2; j++) {
  996.   float ui = u+i/3.0+1./6.;
  997.   float vj = v+j/3.0+1./6.;
  998.   float w = 1.0f / (ui*Mi[0][2] + vj*Mi[1][2] + Mi[2][2]);
  999.   x = (ui*Mi[0][0] + vj*Mi[1][0] + Mi[2][0]) * w;
  1000.   y = (ui*Mi[0][1] + vj*Mi[1][1] + Mi[2][1]) * w;
  1001.   if (x < 0.0 || y < 0.0 || x >= xsize || y >= ysize)
  1002.     continue;
  1003.   cnt++;
  1004.   val = at(x,y);
  1005.   for (int d=0; d<dim; d++) 
  1006.     tmp[d] += int(val[d]);
  1007. }
  1008.       }
  1009.       val = im.getValues(u,v);
  1010.       for (int d=0; d<dim; d++) 
  1011. val[d] = (cnt ? tmp[d] / float(cnt) : 0);
  1012.     }
  1013.   }
  1014.   return im;
  1015. }
  1016. Image 
  1017. Image::crop(int x, int y, int dx, int dy)
  1018. {
  1019.   Image im(dx,dy,dim);
  1020.   for (int v=0; v<dy; v++) {
  1021.     uchar *tmpo = getValues(x,y+v);
  1022.     uchar *tmpn = im.getValues(0,v);
  1023.     for (int i=0; i<dx*dim; i++) {
  1024.       tmpn[i] = tmpo[i];
  1025.     }
  1026.   }
  1027.   return im;
  1028. }
  1029. Image&
  1030. Image::fill(uchar a, uchar b, uchar c, uchar d)
  1031. {
  1032.   int size = xsize*ysize;
  1033.   for (int i=0; i<size; i++) {
  1034.     uchar *tmp = &_data[i*dim];
  1035.     if (dim == 4) tmp[3] = d;
  1036.     if (dim >= 3) tmp[2] = c;
  1037.     if (dim >= 2) tmp[1] = b;
  1038.     if (dim >= 1) tmp[0] = a;
  1039.   }
  1040.   return *this;
  1041. }