home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 320_01 / convolve.c < prev    next >
Text File  |  1990-08-06  |  6KB  |  298 lines

  1. /*****************************************************************/
  2. /* CONVOLVE.C - Turbo C 2.0 implementation of image convolution  */
  3. /* ----------   by Wesley G. Faler.  All code is "as is".  There */
  4. /* is NO copyright.  Use this code as you will, and if you make  */
  5. /* money at it, good for you.                                    */
  6. /*****************************************************************/
  7.  
  8. #include<stdlib.h>
  9. #include<stdio.h>
  10. #include<graphics.h>
  11. #include<alloc.h>
  12. #include<ctype.h>
  13.  
  14. int load_cut(char *fname);
  15. int load_convolution_matrix(char *fname);
  16. int convolve_image(void);
  17. int swap_pictures(void);
  18.  
  19. int minx,maxx,miny,maxy;
  20. int LOADPAGE=0;
  21. int ENHANCEPAGE=1;
  22. int *cmat, *pmat, *vmat;
  23. int cmx,cmy,cmnum;
  24.  
  25. struct palettetype palette,newpal;
  26. int driver,mode;
  27.  
  28. int cleancut=-1;
  29.  
  30. int init_graphics(void)
  31. {
  32.  driver=DETECT; mode=0;
  33.  detectgraph(&driver,&mode);
  34.  if(driver==VGA) mode=VGAMED;
  35.  initgraph(&driver,&mode,"");
  36.  getpalette(&palette);
  37.  getpalette(&newpal);
  38. }
  39.  
  40. int cleanup_image(void)
  41. {
  42.  int i,j,num,x,y,k;
  43.  
  44.  if(cleancut<0) return;
  45.  setactivepage(LOADPAGE);
  46.  setvisualpage(ENHANCEPAGE);
  47.  for(x=minx;x<maxx;x++) {
  48.   for(y=miny;y<maxy;y++) {
  49.    if(getpixel(x,y)!=0) num=-1;
  50.     else num=0;
  51.    for(j=-1;j<2;j++) {
  52.     for(i=-1;i<2;i++) {
  53.      if(getpixel(x+i,y+j)!=0) num++;
  54.     }
  55.    }
  56.    if(num>cleancut) {
  57.     k=getpixel(x,y);
  58.     setactivepage(ENHANCEPAGE);
  59.     putpixel(x,y,k);
  60.     setactivepage(LOADPAGE);
  61.    }
  62.   }
  63.  }
  64.  k=ENHANCEPAGE; ENHANCEPAGE=LOADPAGE; LOADPAGE=k;
  65. }
  66.  
  67. void show_test_image(void)
  68. {
  69.  int i;
  70.  
  71.  minx=cmx; miny=cmy;
  72.  maxx=100+minx; maxy=100+miny;
  73.  setcolor(1);
  74.  moveto(minx,miny);
  75.  randomize();
  76.  for(i=0;i<20;i++)
  77.   lineto(random(100)+minx,random(100)+miny);
  78.  for(i=0;i<10;i++)
  79.   fillellipse(random(50)+25+minx,random(50)+25+miny,random(25),random(25));
  80. }
  81.  
  82. main()
  83. {
  84.  char fname[50];
  85.  int flag=0;
  86.  
  87.  load_convolution_matrix("matrix.dat");
  88.  printf(".CUT file (1) or test image (0)?");
  89.  scanf("%d",&flag);
  90.  flag= flag? 1:0;
  91.  if(flag) {
  92.   fflush(stdin);
  93.   printf("filename to process:");
  94.   gets(fname);
  95.  }
  96.  
  97.  printf("Delete pixels with x or fewer neighbors. x=");
  98.  scanf("%d",&cleancut);
  99.  if(cleancut>8) cleancut=8;
  100.  
  101.  init_graphics();
  102.  setactivepage(1); cleardevice();
  103.  setactivepage(0); cleardevice();
  104.  
  105.  setactivepage(LOADPAGE); setvisualpage(LOADPAGE);
  106.  if(flag) load_cut(fname);
  107.   else show_test_image();
  108.  cleanup_image();
  109.  
  110.  setvisualpage(ENHANCEPAGE);
  111.  convolve_image();
  112.  
  113.  swap_pictures();
  114.  restorecrtmode();
  115. }
  116.  
  117. int toggle_colors(char c)
  118. {
  119.  c=tolower(c);
  120.  c=c-'a';
  121.  if(c<0 || c>=palette.size) return 0;
  122.  newpal.colors[c]= palette.colors[c]-newpal.colors[c];
  123.  setpalette(c,newpal.colors[c]);
  124.  return 1;
  125. }
  126.  
  127. int swap_pictures(void)
  128. {
  129.  int mode=0;
  130.  char a;
  131.  
  132.  setvisualpage(LOADPAGE);
  133.  for(;;) {
  134.   a=getch();
  135.   if(a==27) return;
  136.   if(toggle_colors(a)) continue;
  137.   if(mode==0) setvisualpage(ENHANCEPAGE);
  138.   if(mode==1) setvisualpage(LOADPAGE);
  139.   mode=1-mode;
  140.  }
  141. }
  142.  
  143. int convolve_image(void)
  144. {
  145.  int i,j,k,nval;
  146.  int *vx, *vy, *c;
  147.  int colmax,offset,end,midy;
  148.  char **lines=NULL;
  149.  char *temp=NULL;
  150.  
  151.  offset=-minx+(cmx/2);
  152.  end=cmy-1; midy=cmy/2;
  153.  lines=(char **)malloc(cmy*sizeof(char *));
  154.  for(i=0;i<cmy;i++) lines[i]=(char *)malloc(sizeof(char)*(maxx-minx+cmx+1));
  155.  setactivepage(LOADPAGE);
  156.  for(j=-cmy/2;j<cmy/2;j++) {
  157.   for(i=minx-cmx/2;i<(maxx+cmx/2+1);i++) {
  158.    lines[j+midy][i+offset]=getpixel(i,j+miny);
  159.   }
  160.  }
  161.  colmax=getmaxcolor();
  162.  for(j=miny;j<maxy;j++) {
  163.   setactivepage(LOADPAGE);
  164.   for(i=j+cmy/2,k=minx-cmx/2,nval=maxx+cmx/2;k<nval;k++)
  165.    lines[end][k+offset]=getpixel(k,i);
  166.   for(i=minx;i<maxx;i++) {
  167.    /* Load & multiply neighbors into matrix */
  168.    setactivepage(LOADPAGE);
  169.    vx=vmat; vy=vmat+1; c=cmat; nval=0;
  170.    for(k=0;k<cmnum;k++) {
  171.     if(*c) nval+= lines[(*vy)+midy][i+(*vx)+offset]*(*c);
  172.     /* if(*c) nval+= getpixel(i+(*vx),j+(*vy)) * (*c); */
  173.     c++;
  174.     vx+=2; vy+=2;
  175.    }
  176.    /* Cut off values too high or too low */
  177.    if(nval<0) nval=0;
  178.    if(nval>colmax) nval=colmax;
  179.    /* Place new pixel value */
  180.    setactivepage(ENHANCEPAGE);
  181.    putpixel(i,j,nval);
  182.   }
  183.   if(kbhit()) { getch(); break; }
  184.   /* rotate line pointers */
  185.   temp=lines[0];
  186.   for(i=1;i<cmy;i++) lines[i-1]=lines[i];
  187.   lines[end]=temp;
  188.  }
  189.  for(i=0;i<cmy;i++) {
  190.   if(lines[i]!=NULL) free(lines[i]);
  191.  }
  192.  if(lines!=NULL) {
  193.   free(lines);
  194.  }
  195.  return;
  196. }
  197.  
  198. int build_offset_vectors(void)
  199. {
  200.  int *t;
  201.  int il,im,jl,jm,i,j;
  202.  
  203.  il=-cmx/2; im=cmx+il;
  204.  jl=-cmy/2; jm=cmy+jl;
  205.  t=vmat;
  206.  for(j=jl;j<jm;j++) {
  207.   for(i=il;i<im;i++) {
  208.    *t++=i; *t++=j;
  209.   }
  210.  }
  211. }
  212.  
  213. int load_convolution_matrix(char *fname)
  214. {
  215.  /* Layout of matrix file:
  216.      #x #y
  217.      x0y0 x1y0 ... xny1
  218.      .... .... ... ....
  219.      x0ym x1ym ... xnym
  220.  */
  221.  FILE *mf;
  222.  int *t;
  223.  int i,j,im,jm;
  224.  
  225.  if( (mf=fopen(fname,"rt"))==NULL ) {
  226.   printf("Cannot load matrix file.\n");
  227.   abort();
  228.  }
  229.  fscanf(mf,"%d%d",&im,&jm);
  230.  if( (im&1)==0 || (jm&1)==0 ) {
  231.   printf("Convolution matrix MUST have a center point.\n");
  232.   abort();
  233.  }
  234.  if( (cmat=(int *)calloc(im*jm,sizeof(int)))==NULL ) {
  235.   printf("Unable to calloc convolution matrix.\n");
  236.   abort();
  237.  }
  238.  if( (vmat=(int *)calloc(2*im*jm,sizeof(int)))==NULL ) {
  239.   printf("Unable to calloc offset vector matrix.\n");
  240.   abort();
  241.  }
  242.  cmx=im; cmy=jm; cmnum=im*jm;
  243.  t=cmat;
  244.  for(j=0;j<jm;j++) {
  245.   for(i=0;i<im;i++) {
  246.    if( fscanf(mf,"%d",t++)!=1 ) {
  247.     printf("Unable to read matrix.\n");
  248.     abort();
  249.    }
  250.   }
  251.  }
  252.  fclose(mf);
  253.  build_offset_vectors();
  254. }
  255.  
  256. int load_cut(char *fname)
  257. {
  258.  static unsigned char st[3000];
  259.  char *sp=st,*spend;
  260.  int stp=0;
  261.  int width,height;
  262.  FILE *fp;
  263.  int x,y,xl,yl;
  264.  int i,n,len,d,j;
  265.  
  266.  fp=fopen(fname,"rb");
  267.  width=getw(fp); height=getw(fp);
  268.  xl=cmx; yl=cmy;
  269.  minx=xl; miny=yl;
  270.  maxx=xl+width; maxy=yl+height;
  271.  if(maxy>(getmaxy()-cmy)) {
  272.   maxy=getmaxy()-cmy;
  273.   height=maxy-yl;
  274.  }
  275.  getw(fp);
  276.  y=yl-1;
  277.  for(sp=st,n=0;n<height;n++) {
  278.   stp=getw(fp);
  279.   for(sp=st,spend=st+stp;sp<spend;) *sp++=getc(fp);
  280.   sp=st; spend=sp+stp; x=xl; y++;
  281.   while(sp<spend) {
  282.    if(*((unsigned char *)sp)>0x80) {
  283.     len=(*sp++) & 0x7f;
  284.     if(!(*sp)) { x+=len; continue; }
  285.     setcolor(*sp++);
  286.     moveto(x,y);
  287.     linerel(len,0);
  288.     x+=len;
  289.     continue;
  290.    } else {
  291.     len=*sp++;
  292.     for(j=0;j<len;j++) putpixel(x++,y,*sp++);
  293.     continue;
  294.    }
  295.   }
  296.  }
  297.  fclose(fp);
  298. }