#include #include #include #include int filter(unsigned char *); void map(PICFILE *, PICFILE *, int (*)(unsigned char *), int); main(int argc, char *argv[]){ PICFILE *in, *out; argc=getflags(argc, argv, ""); if(argc!=1 && argc!=2) usage("[picture]"); in=picopen_r(argc==2?argv[1]:"IN"); if(in==0){ picerror(argc==2?argv[1]:"IN"); exits("open input"); } out=picopen_w("OUT", PIC_SAMEARGS(in)); if(out==0){ picerror("OUT"); exits("creat output"); } map(in, out, filter, NWIN); return 0; } #define new(t, n) ((t *)emalloc((n)*sizeof(t))) char *emalloc(int n){ char *v=malloc(n); if(v==0){ fprint(2, "Out of space\n"); exits("no space"); } return v; } struct line{ unsigned char *left; unsigned char *read; unsigned char *eread; unsigned char *right; unsigned char *cursor; }; void getline(PICFILE *, struct line *, struct line *); void dupline(struct line *, struct line *); /* * Neighbourhood mapping from picture in to out. Each pixel of out * is written with some funcion of an n by n neighbourhood of in. * rou is called once for each channel of each output pixel. Its * argument is an n by n array of unsigned chars containing one channel * of the neighbourhood surrounding the corresponding input pixel. * Pixels on in's boundary are replicated to provide neighbours * for pixels close to the edge. * Should take a mask argument to indicate what channels to operate on. */ void map(PICFILE *in, PICFILE *out, int (*rou)(unsigned char *), int n){ int j; unsigned char *p, *q; int nchan=PIC_NCHAN(in); int i; unsigned char *op, *eout, *buf, *box=new(unsigned char, n*n); unsigned char *outline=new(unsigned char, PIC_WIDTH(in)*nchan); int y; struct line *line, t; eout=outline+PIC_WIDTH(in)*nchan; line=new(struct line, n); line[0].left=buf=new(unsigned char, n*(PIC_WIDTH(in)+n-1)*nchan); for(i=0;i!=n;i++){ if(i) line[i].left=line[i-1].right; line[i].read=line[i].left+(n/2)*nchan; line[i].eread=line[i].read+PIC_WIDTH(in)*nchan; line[i].right=line[i].left+(PIC_WIDTH(in)+n-1)*nchan; } getline(in, &line[n/2], &line[n/2]); for(i=0;i!=n/2;i++) dupline(&line[i], &line[n/2]); for(i=n/2+1;iread)) dupline(lp, mp); else{ p=lp->read; q=p+f->nchan; while(p!=lp->left) *--p = *--q; p=lp->eread; q=p-f->nchan; while(p!=lp->right) *p++ = *q++; } } /* * copy line mp into lp */ void dupline(struct line *lp, struct line *mp){ memcpy((char *)lp->left, (char *)mp->left, mp->right-mp->left); }