home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************/
- /* CONVOLVE.C - Turbo C 2.0 implementation of image convolution */
- /* ---------- by Wesley G. Faler. All code is "as is". There */
- /* is NO copyright. Use this code as you will, and if you make */
- /* money at it, good for you. */
- /*****************************************************************/
-
- #include<stdlib.h>
- #include<stdio.h>
- #include<graphics.h>
- #include<alloc.h>
- #include<ctype.h>
-
- int load_cut(char *fname);
- int load_convolution_matrix(char *fname);
- int convolve_image(void);
- int swap_pictures(void);
-
- int minx,maxx,miny,maxy;
- int LOADPAGE=0;
- int ENHANCEPAGE=1;
- int *cmat, *pmat, *vmat;
- int cmx,cmy,cmnum;
-
- struct palettetype palette,newpal;
- int driver,mode;
-
- int cleancut=-1;
-
- int init_graphics(void)
- {
- driver=DETECT; mode=0;
- detectgraph(&driver,&mode);
- if(driver==VGA) mode=VGAMED;
- initgraph(&driver,&mode,"");
- getpalette(&palette);
- getpalette(&newpal);
- }
-
- int cleanup_image(void)
- {
- int i,j,num,x,y,k;
-
- if(cleancut<0) return;
- setactivepage(LOADPAGE);
- setvisualpage(ENHANCEPAGE);
- for(x=minx;x<maxx;x++) {
- for(y=miny;y<maxy;y++) {
- if(getpixel(x,y)!=0) num=-1;
- else num=0;
- for(j=-1;j<2;j++) {
- for(i=-1;i<2;i++) {
- if(getpixel(x+i,y+j)!=0) num++;
- }
- }
- if(num>cleancut) {
- k=getpixel(x,y);
- setactivepage(ENHANCEPAGE);
- putpixel(x,y,k);
- setactivepage(LOADPAGE);
- }
- }
- }
- k=ENHANCEPAGE; ENHANCEPAGE=LOADPAGE; LOADPAGE=k;
- }
-
- void show_test_image(void)
- {
- int i;
-
- minx=cmx; miny=cmy;
- maxx=100+minx; maxy=100+miny;
- setcolor(1);
- moveto(minx,miny);
- randomize();
- for(i=0;i<20;i++)
- lineto(random(100)+minx,random(100)+miny);
- for(i=0;i<10;i++)
- fillellipse(random(50)+25+minx,random(50)+25+miny,random(25),random(25));
- }
-
- main()
- {
- char fname[50];
- int flag=0;
-
- load_convolution_matrix("matrix.dat");
- printf(".CUT file (1) or test image (0)?");
- scanf("%d",&flag);
- flag= flag? 1:0;
- if(flag) {
- fflush(stdin);
- printf("filename to process:");
- gets(fname);
- }
-
- printf("Delete pixels with x or fewer neighbors. x=");
- scanf("%d",&cleancut);
- if(cleancut>8) cleancut=8;
-
- init_graphics();
- setactivepage(1); cleardevice();
- setactivepage(0); cleardevice();
-
- setactivepage(LOADPAGE); setvisualpage(LOADPAGE);
- if(flag) load_cut(fname);
- else show_test_image();
- cleanup_image();
-
- setvisualpage(ENHANCEPAGE);
- convolve_image();
-
- swap_pictures();
- restorecrtmode();
- }
-
- int toggle_colors(char c)
- {
- c=tolower(c);
- c=c-'a';
- if(c<0 || c>=palette.size) return 0;
- newpal.colors[c]= palette.colors[c]-newpal.colors[c];
- setpalette(c,newpal.colors[c]);
- return 1;
- }
-
- int swap_pictures(void)
- {
- int mode=0;
- char a;
-
- setvisualpage(LOADPAGE);
- for(;;) {
- a=getch();
- if(a==27) return;
- if(toggle_colors(a)) continue;
- if(mode==0) setvisualpage(ENHANCEPAGE);
- if(mode==1) setvisualpage(LOADPAGE);
- mode=1-mode;
- }
- }
-
- int convolve_image(void)
- {
- int i,j,k,nval;
- int *vx, *vy, *c;
- int colmax,offset,end,midy;
- char **lines=NULL;
- char *temp=NULL;
-
- offset=-minx+(cmx/2);
- end=cmy-1; midy=cmy/2;
- lines=(char **)malloc(cmy*sizeof(char *));
- for(i=0;i<cmy;i++) lines[i]=(char *)malloc(sizeof(char)*(maxx-minx+cmx+1));
- setactivepage(LOADPAGE);
- for(j=-cmy/2;j<cmy/2;j++) {
- for(i=minx-cmx/2;i<(maxx+cmx/2+1);i++) {
- lines[j+midy][i+offset]=getpixel(i,j+miny);
- }
- }
- colmax=getmaxcolor();
- for(j=miny;j<maxy;j++) {
- setactivepage(LOADPAGE);
- for(i=j+cmy/2,k=minx-cmx/2,nval=maxx+cmx/2;k<nval;k++)
- lines[end][k+offset]=getpixel(k,i);
- for(i=minx;i<maxx;i++) {
- /* Load & multiply neighbors into matrix */
- setactivepage(LOADPAGE);
- vx=vmat; vy=vmat+1; c=cmat; nval=0;
- for(k=0;k<cmnum;k++) {
- if(*c) nval+= lines[(*vy)+midy][i+(*vx)+offset]*(*c);
- /* if(*c) nval+= getpixel(i+(*vx),j+(*vy)) * (*c); */
- c++;
- vx+=2; vy+=2;
- }
- /* Cut off values too high or too low */
- if(nval<0) nval=0;
- if(nval>colmax) nval=colmax;
- /* Place new pixel value */
- setactivepage(ENHANCEPAGE);
- putpixel(i,j,nval);
- }
- if(kbhit()) { getch(); break; }
- /* rotate line pointers */
- temp=lines[0];
- for(i=1;i<cmy;i++) lines[i-1]=lines[i];
- lines[end]=temp;
- }
- for(i=0;i<cmy;i++) {
- if(lines[i]!=NULL) free(lines[i]);
- }
- if(lines!=NULL) {
- free(lines);
- }
- return;
- }
-
- int build_offset_vectors(void)
- {
- int *t;
- int il,im,jl,jm,i,j;
-
- il=-cmx/2; im=cmx+il;
- jl=-cmy/2; jm=cmy+jl;
- t=vmat;
- for(j=jl;j<jm;j++) {
- for(i=il;i<im;i++) {
- *t++=i; *t++=j;
- }
- }
- }
-
- int load_convolution_matrix(char *fname)
- {
- /* Layout of matrix file:
- #x #y
- x0y0 x1y0 ... xny1
- .... .... ... ....
- x0ym x1ym ... xnym
- */
- FILE *mf;
- int *t;
- int i,j,im,jm;
-
- if( (mf=fopen(fname,"rt"))==NULL ) {
- printf("Cannot load matrix file.\n");
- abort();
- }
- fscanf(mf,"%d%d",&im,&jm);
- if( (im&1)==0 || (jm&1)==0 ) {
- printf("Convolution matrix MUST have a center point.\n");
- abort();
- }
- if( (cmat=(int *)calloc(im*jm,sizeof(int)))==NULL ) {
- printf("Unable to calloc convolution matrix.\n");
- abort();
- }
- if( (vmat=(int *)calloc(2*im*jm,sizeof(int)))==NULL ) {
- printf("Unable to calloc offset vector matrix.\n");
- abort();
- }
- cmx=im; cmy=jm; cmnum=im*jm;
- t=cmat;
- for(j=0;j<jm;j++) {
- for(i=0;i<im;i++) {
- if( fscanf(mf,"%d",t++)!=1 ) {
- printf("Unable to read matrix.\n");
- abort();
- }
- }
- }
- fclose(mf);
- build_offset_vectors();
- }
-
- int load_cut(char *fname)
- {
- static unsigned char st[3000];
- char *sp=st,*spend;
- int stp=0;
- int width,height;
- FILE *fp;
- int x,y,xl,yl;
- int i,n,len,d,j;
-
- fp=fopen(fname,"rb");
- width=getw(fp); height=getw(fp);
- xl=cmx; yl=cmy;
- minx=xl; miny=yl;
- maxx=xl+width; maxy=yl+height;
- if(maxy>(getmaxy()-cmy)) {
- maxy=getmaxy()-cmy;
- height=maxy-yl;
- }
- getw(fp);
- y=yl-1;
- for(sp=st,n=0;n<height;n++) {
- stp=getw(fp);
- for(sp=st,spend=st+stp;sp<spend;) *sp++=getc(fp);
- sp=st; spend=sp+stp; x=xl; y++;
- while(sp<spend) {
- if(*((unsigned char *)sp)>0x80) {
- len=(*sp++) & 0x7f;
- if(!(*sp)) { x+=len; continue; }
- setcolor(*sp++);
- moveto(x,y);
- linerel(len,0);
- x+=len;
- continue;
- } else {
- len=*sp++;
- for(j=0;j<len;j++) putpixel(x++,y,*sp++);
- continue;
- }
- }
- }
- fclose(fp);
- }