/***************************************************************** * flconv.c: FBM Release 1.2 18-Apr-93 Michael Mauldin * * Copyright (C) 1993 by Michael Mauldin. Permission is granted * to use this file in whole or in part for any purpose, educational, * recreational or commercial, provided that this copyright notice * is retained unchanged. This software is available to all free of * charge by anonymous FTP and in the UUNET archives. * * flconv.c: * Apply arbitary convolutions to an image. For multi-plane * images, the convolution is applied to each image separately. * * Only odd kernel sizes are allowed (3x3, 5x5, etc.). Of course, * you can always use a kernel one size larger with the rightmost * and bottommost values set to 0 to implement the smaller kernel. * * Edges are set to the product of the edge pixel value and * the sum of the kernel (so for kernels that sum to zero, the * edges are set to black). * * If absval is non-zero, then the absolute value of the weighted * sum is used, else it is set to 0. * * Internally, the kernel is converted to fixed binary arithmetic, * with 8 bits used to represent the fraction, 23 for the integer, * and 1 for the sign. * * CONTENTS * convolve_fbm (input, output, kernel, n, absval) * FBM *input, *output; * double **kernel; * * EDITLOG * LastEditDate = Mon Jun 25 00:18:02 1990 - Michael Mauldin * LastFileName = /usr2/mlm/src/misc/fbm/flconv.c * * HISTORY * 18-Apr-93 Michael Mauldin (mlm) at Carnegie-Mellon University * Created from flshrp.c *****************************************************************/ # include # include # include # include "fbm.h" /**************************************************************** * convolve_fbm: apply a convolution ****************************************************************/ #ifndef lint static char *fbmid = "$FBM flconv.c <1.2> 18-Apr-93 (C) 1993 by Michael Mauldin, source \ code available free from MLM@CS.CMU.EDU and from UUNET archives$"; #endif convolve_fbm (input, output, kernel, n, absval) FBM *input, *output; int n, absval; double **kernel; { register int i, m, *ko, *kw, sum; register unsigned char *ibm, *obm; int j, k, n2, nsq, rowlen, plnlen, w, h, *koff, *kwgt; double msum = 0.0, floor (); if ((n&1) == 0) { fprintf (stderr, "convolve_fbm: only odd kernel sizes are allowed.\n"); return (0); } fprintf (stderr, "\nIn flconv, kernel is:\n"); /* Print the kernel */ for (j=0; jhdr = input->hdr; alloc_fbm (output); /* Cache important size values */ w = input->hdr.cols; h = input->hdr.rows; rowlen = input->hdr.rowlen; plnlen = input->hdr.plnlen; /* Preprocess kernel, convert to fixed arithmetic */ n2 = n/2; nsq = n * n; kwgt = (int *) malloc (nsq * sizeof (int *)); koff = (int *) malloc (nsq * sizeof (int *)); for (j=0; jhdr.planes; k++) { /* Copy edges directly */ for (j=0; jbm[k*plnlen + j*rowlen]; obm = &output->bm[k*plnlen + j*rowlen]; for (m=0; m < n2; m++) { obm[m] = ibm[m] * msum + 0.5; obm[w-(m+1)] = ibm[w-(m+1)] * msum + 0.5; } } ibm = &input->bm[k*plnlen]; obm = &output->bm[k*plnlen]; for (i=0; ibm[k*plnlen + j*rowlen]); obm = &(output->bm[k*plnlen + j*rowlen]); for (i=n2; i < w-n2; i++) { sum = 0; kw = kwgt; ko = koff; for (m = nsq; --m >= 0; ) { sum += *kw++ * ibm[i + *ko++]; } sum >>= 8; /* Divide by 256 */ if (sum < BLACK) sum = absval ? -sum : BLACK; if (sum > WHITE) sum = WHITE; obm[i] = sum; } } } return (1); } sobel_fbm (input, output) FBM *input, *output; { register int i, j, sum1, sum2; register unsigned char *ibm, *obm; int k, rowlen, plnlen, w, h; /* Allocate output */ output->hdr = input->hdr; alloc_fbm (output); /* Cache important size values */ w = input->hdr.cols; h = input->hdr.rows; rowlen = input->hdr.rowlen; plnlen = input->hdr.plnlen; /* Loop through each plane */ for (k=0; khdr.planes; k++) { /* Clear edges */ for (j=0; jbm[k*plnlen + j*rowlen] = 0; output->bm[k*plnlen + j*rowlen + w-1] = 0; } ibm = &input->bm[k*plnlen]; obm = &output->bm[k*plnlen]; for (i=0; ibm[k*plnlen + j*rowlen]); obm = &(output->bm[k*plnlen + j*rowlen]); for (i=1; i < w-1; i++) { /* Compute horizontal gradient */ sum1 = ibm[i-rowlen-1] + 2 * ibm[i-rowlen] + ibm[i-rowlen+1] + -ibm[i+rowlen-1] - 2 * ibm[i+rowlen] - ibm[i+rowlen+1]; /* Compute vertical gradient */ if (sum1 < 0) sum1 = -sum1; sum2 = ibm[i-rowlen-1] - ibm[i-rowlen+1] + 2 * (ibm[i-1] - ibm[i+1]) + ibm[i+rowlen-1] - ibm[i+rowlen+1]; if (sum2 < 0) sum2 = -sum2; sum1 += sum2; if (sum1 > WHITE) sum1 = WHITE; obm[i] = sum1; } } } return (1); } sobel_5x5_fbm (input, output) FBM *input, *output; { register int i, j, sum1, sum2; register unsigned char *ibm, *obm; int k, rowlen, plnlen, w, h; int max1=0, min1=0, max2=0, min2=0; /* Allocate output */ output->hdr = input->hdr; alloc_fbm (output); /* Cache important size values */ w = input->hdr.cols; h = input->hdr.rows; rowlen = input->hdr.rowlen; plnlen = input->hdr.plnlen; /* Loop through each plane */ for (k=0; khdr.planes; k++) { /* Clear edges */ for (j=0; jbm[k*plnlen + j*rowlen] = 0; output->bm[k*plnlen + j*rowlen+1] = 0; output->bm[k*plnlen + j*rowlen + w-2] = 0; output->bm[k*plnlen + j*rowlen + w-1] = 0; } ibm = &input->bm[k*plnlen]; obm = &output->bm[k*plnlen]; for (i=0; ibm[k*plnlen + j*rowlen]); obm = &(output->bm[k*plnlen + j*rowlen]); for (i=2; i < w-2; i++) { /* Compute horizontal gradient */ sum1 = -ibm[i-2*rowlen-1] + -2 * ibm[i-2*rowlen] + -ibm[i-2*rowlen+1] + -ibm[i-rowlen-2] + -2 * ibm[i-rowlen-1] + -4 * ibm[i-rowlen] + -2 * ibm[i-rowlen+1] + -ibm[i-rowlen+2] + ibm[i+rowlen-2] + 2 * ibm[i+rowlen-1] + 4 * ibm[i+rowlen] + 2 * ibm[i+rowlen+1] + ibm[i+rowlen+2] + ibm[i+2*rowlen-1] + 2 * ibm[i+2*rowlen] + ibm[i+2*rowlen+1]; if (sum1 < min1) min1 = sum1; if (sum1 > max1) max1 = sum1; if (sum1 < 0) sum1 = -sum1; /* Compute vertical gradient */ sum2 = -ibm[i-2*rowlen-1] + ibm[i-2*rowlen+1] + -ibm[i-rowlen-2] + -2 * ibm[i-rowlen-1] + 2 * ibm[i-rowlen+1] + ibm[i-rowlen+2] + -2 * ibm[i-2] + -4 * ibm[i-1] + 4 * ibm[i+1] + 2 * ibm[i+2] + -ibm[i+rowlen-2] + -2 * ibm[i+rowlen-1] + 2 * ibm[i+rowlen+1] + ibm[i+rowlen+2] + -ibm[i+2*rowlen-1] + ibm[i+2*rowlen+1]; if (sum2 < min2) min2 = sum2; if (sum2 > max2) max2 = sum2; if (sum2 < 0) sum2 = -sum2; sum1 += sum2; sum1 >>= 2; if (sum1 > WHITE) sum1 = WHITE; obm[i] = sum1; } } } fprintf (stderr, "Vertical range %d..%d, horizontal range %d..%d\n", min1, max1, min2, max2); return (1); }