home *** CD-ROM | disk | FTP | other *** search
- #undef DBL_LOOP /* def for for(x..., for(y... loops */
- #undef INL_SORT /* def to inline piksrt() in median() */
-
- /*
- * process.c - all the image processing functions.
- */
-
- static char *sccsid = "@(#) process.c 1.3 91/6/9 rosenkra\0\0 ";
-
- #include <stdio.h>
- #include "mgif.h"
-
- /*
- * local functions
- */
- int larger (); /* frame processes... */
- int zoom ();
- int smaller ();
- int cut ();
- int rotate ();
- int mirror ();
- int convolve (); /* area processes... */
- int blur ();
- int median ();
- int piksrt ();
- int logscale (); /* point processes... */
- int Log2x10 ();
- int contrast ();
- int brighten ();
- int invert ();
- int threshold ();
- int histeq ();
- int redistribute ();
- int copyrast (); /* others... */
-
- /*
- * external functions
- */
- extern int do_hist ();
- extern int copyrast ();
-
-
- /*------------------------------*/
- /* larger */
- /*------------------------------*/
-
- #define L_BOTH 0
- #define L_HOR 1
- #define L_VERT 2
-
- int larger (pras, w, h, opt, ptrans)
- uchar_t *pras;
- int w;
- int h;
- int opt; /* checked by caller! */
- uchar_t *ptrans;
- {
-
- /*
- * enlarge an image (so far 320x200 -> 640x400). return 1 if
- * successful, else 0.
- */
-
- register uchar_t *pr;
- register uchar_t *pt;
- register long x;
- register long y;
- long x2;
- long y2;
- register long wold;
- long hold;
- register long w2;
- long h2;
-
-
- /*
- * fail if enlarged image will be too big for buffer
- */
- #if 0
- if ((w > 320) || (h > 200))
- return (0);
- #endif
- switch (opt)
- {
- case L_BOTH:
- if (4L * (long) w * (long) h > MAXIMG)
- return (0);
- break;
- case L_HOR:
- if (2L * (long) w * (long) h > MAXIMG)
- return (0);
- break;
- case L_VERT:
- if (2L * (long) w * (long) h > MAXIMG)
- return (0);
- break;
- }
-
-
-
- /*
- * here we always do the transform in situ (in ptrans)...
- */
- if (pras == ptrans)
- {
- /*
- * do in place...
- */
- pr = pras;
- pt = pras;
- }
- else
- {
- /*
- * copy to new image
- */
- pr = pras;
- pt = ptrans;
-
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- pr = ptrans;
- }
-
-
- wold = w;
- hold = h;
- switch (opt)
- {
- case L_BOTH:
- /*
- * set new sizes
- */
- w2 = wold*2L;
- h2 = hold*2L;
-
-
- /*
- * shift existing data:
- *
- * 0123456789
- * 0|**********| *=existing pixels
- * 1|**********| +=new pixels
- * .
- * .
- * |
- * v
- * 1111111111
- * 01234567890123456789
- * 0| |
- * 1| + + + + + + + + + +|
- * 2| |
- * 3| + + + + + + + + + +|
- * .
- * .
- */
- for (y = hold-1; y >= 0; y--)
- {
- for (x = wold-1; x >= 0; x--)
- {
- x2 = (2*x)+1;
- y2 = (2*y)+1;
- pt[y2*w2 + x2] = pt[y*wold + x];
- }
- }
-
-
- /*
- * now make intermediate points within row (average):
- *
- * 1111111111
- * 01234567890123456789
- * 0| | *=existing pixels
- * 1|+*+*+*+*+*+*+*+*+*+*| +=new pixels
- * 2| |
- * 3|+*+*+*+*+*+*+*+*+*+*|
- * .
- * .
- */
- for (y = 1; y < h2; y += 2)
- {
- /* first point is duplicate of second */
- pt[y*w2 + 0] = pt[y*w2 + 1];
-
- /* others are average */
- for (x = 2; x < w2; x += 2)
- {
- pt[y*w2 + x] = (uchar_t) (
- ((uint_t) pt[y*w2 + (x-1)]
- + (uint_t) pt[y*w2 + (x+1)]) / 2);
- }
- }
-
-
- /*
- * first row is duplicate of second row:
- *
- * 1111111111
- * 01234567890123456789
- * 0|++++++++++++++++++++|<---
- * 1|********************| *=existing pixels
- * 2| | +=new pixels
- * 3|********************|
- * .
- * .
- */
- for (x = 0; x < w2; x++)
- {
- pt[x] = pt[w2 + x];
- }
-
-
- /*
- * finally, make new rows (average):
- *
- * 1111111111
- * 01234567890123456789
- * 0|********************| *=existing pixels
- * 1|********************| +=new pixels
- * 2|++++++++++++++++++++|<---
- * 3|********************|
- * .
- * .
- */
- for (y = 2; y < h2; y += 2)
- {
- for (x = 0; x < w2; x++)
- {
- pt[y*w2 + x] = (uchar_t) (
- ((uint_t) pt[(y-1)*w2 + x]
- + (uint_t) pt[(y+1)*w2 + x]) / 2);
- }
- }
- break;
-
-
- case L_HOR:
- /*
- * set new sizes
- */
- w2 = wold*2L;
- h2 = hold;
-
-
- /*
- * shift existing data:
- *
- * 0123456789
- * 0|**********| *=existing pixels
- * 1|**********| +=new pixels
- * .
- * .
- * |
- * v
- * 1111111111
- * 01234567890123456789
- * 0| + + + + + + + + + +|
- * 1| + + + + + + + + + +|
- * .
- * .
- */
- for (y = hold-1; y >= 0; y--)
- {
- for (x = wold-1; x >= 0; x--)
- {
- x2 = (2*x)+1;
- pt[y*w2 + x2] = pt[y*wold + x];
- }
- }
-
-
- /*
- * now make intermediate points within row (average):
- *
- * 1111111111
- * 01234567890123456789
- * 0|+*+*+*+*+*+*+*+*+*+*| *=existing pixels
- * 1|+*+*+*+*+*+*+*+*+*+*| +=new pixels
- * .
- * .
- */
- for (y = 0; y < hold; y++)
- {
- /* first point is duplicate of second */
- pt[y*w2 + 0] = pt[y*w2 + 1];
-
- /* others are average */
- for (x = 2; x < w2; x += 2)
- {
- pt[y*w2 + x] = (uchar_t) (
- ((uint_t) pt[y*w2 + (x-1)]
- + (uint_t) pt[y*w2 + (x+1)]) / 2);
- }
- }
- break;
-
- case L_VERT:
- /*
- * set new sizes
- */
- w2 = wold;
- h2 = hold*2L;
-
-
- /*
- * shift existing data:
- *
- * 0123456789
- * 0|**********| *=existing pixels
- * 1|**********| +=new pixels
- * .
- * .
- * |
- * v
- * 0123456789
- * 0| |
- * 1|++++++++++|
- * 2| |
- * 3|++++++++++|
- * .
- * .
- */
- for (y = hold-1; y >= 0; y--)
- {
- for (x = wold-1; x >= 0; x--)
- {
- y2 = (2*y)+1;
- pt[y2*wold + x] = pt[y*wold + x];
- }
- }
-
-
- /*
- * first row is duplicate of second row:
- *
- * 0123456789
- * 0|++++++++++|<---
- * 1|**********| *=existing pixels
- * 2| | +=new pixels
- * 3|**********|
- * .
- * .
- */
- for (x = 0; x < wold; x++)
- {
- pt[x] = pt[wold + x];
- }
-
-
- /*
- * finally, make new rows (average):
- *
- * 0123456789
- * 0|**********| *=existing pixels
- * 1|**********| +=new pixels
- * 2|++++++++++|<---
- * 3|**********|
- * .
- * .
- */
- for (y = 2; y < h2; y += 2)
- {
- for (x = 0; x < wold; x++)
- {
- pt[y*wold + x] = (uchar_t) (
- ((uint_t) pt[(y-1)*wold + x]
- + (uint_t) pt[(y+1)*wold + x]) / 2);
- }
- }
- break;
- }
-
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* zoom */
- /*------------------------------*/
- int zoom (pras, w, h, xstart, ystart, ptrans)
- uchar_t *pras;
- int w;
- int h;
- int xstart;
- int ystart;
- uchar_t *ptrans;
- {
-
- /*
- * zoom in and enlarge an image (so far 2x) starting at xstart,ystart.
- * return 1 if successful, else 0.
- */
-
- register uchar_t *pr;
- register uchar_t *pt;
- register long x;
- register long y;
- long x2;
- long y2;
- register long wold;
- long hold;
- register long w2;
- long h2;
-
-
-
- /*
- * enlarged image should ALWAYS fit in buffer!
- *
- * here we always do the transform in situ (in ptrans)...
- */
- if (pras == ptrans)
- {
- /*
- * do in place. pr points to "cut" area, pt to start
- */
- pr = &pras[xstart + (ystart-1)*w];
- pt = pras;
-
- /*
- * shift smaller image to ul corner of pt
- */
- if ((xstart != 0) && (ystart != 0))
- {
- for (y = 0L; y < h/2; y++)
- {
- for (x = 0L; x < w/2; x++)
- {
- pt[x + w*(y-1)/2] = pr[x + w*(y-1)];
- }
- }
- }
- }
- else
- {
- /*
- * copy to new image
- */
- pr = &pras[xstart + (ystart-1)*w];
- pt = ptrans;
-
- /*
- * first copy orig image to transform image
- */
- for (y = 0L; y < h/2; y++)
- {
- for (x = 0L; x < w/2; x++)
- {
- pt[x + w*(y-1)/2] = pr[x + w*(y-1)];
- }
- }
- }
-
-
-
- /*
- * set new sizes
- */
- wold = w/2L;
- hold = h/2L;
- w2 = wold*2L;
- h2 = hold*2L;
-
-
- /*
- * shift existing data:
- *
- * 0123456789
- * 0|**********| *=existing pixels
- * 1|**********| +=new pixels
- * .
- * .
- * |
- * v
- * 1111111111
- * 01234567890123456789
- * 0| |
- * 1| + + + + + + + + + +|
- * 2| |
- * 3| + + + + + + + + + +|
- * .
- * .
- */
- for (y = hold-1; y >= 0; y--)
- {
- for (x = wold-1; x >= 0; x--)
- {
- x2 = (2*x)+1;
- y2 = (2*y)+1;
- pt[y2*w2 + x2] = pt[y*wold + x];
- }
- }
-
-
- /*
- * now make intermediate points within row (average):
- *
- * 1111111111
- * 01234567890123456789
- * 0| | *=existing pixels
- * 1|+*+*+*+*+*+*+*+*+*+*| +=new pixels
- * 2| |
- * 3|+*+*+*+*+*+*+*+*+*+*|
- * .
- * .
- */
- for (y = 1; y < h2; y += 2)
- {
- /* first point is duplicate of second */
- pt[y*w2 + 0] = pt[y*w2 + 1];
-
- /* others are average */
- for (x = 2; x < w2; x += 2)
- {
- pt[y*w2 + x] = (uchar_t) (
- ((uint_t) pt[y*w2 + (x-1)]
- + (uint_t) pt[y*w2 + (x+1)]) / 2);
- }
- }
-
-
- /*
- * first row is duplicate of second row:
- *
- * 1111111111
- * 01234567890123456789
- * 0|++++++++++++++++++++|<---
- * 1|********************| *=existing pixels
- * 2| | +=new pixels
- * 3|********************|
- * .
- * .
- */
- for (x = 0; x < w2; x++)
- {
- pt[x] = pt[w2 + x];
- }
-
-
- /*
- * finally, make new rows (average):
- *
- * 1111111111
- * 01234567890123456789
- * 0|********************| *=existing pixels
- * 1|********************| +=new pixels
- * 2|++++++++++++++++++++|<---
- * 3|********************|
- * .
- * .
- */
- for (y = 2; y < h2; y += 2)
- {
- for (x = 0; x < w2; x++)
- {
- pt[y*w2 + x] = (uchar_t) (
- ((uint_t) pt[(y-1)*w2 + x]
- + (uint_t) pt[(y+1)*w2 + x]) / 2);
- }
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* smaller */
- /*------------------------------*/
-
- #define S_BOTH 0
- #define S_HOR 1
- #define S_VERT 2
-
- int smaller (pras, w, h, opt, ptrans)
- uchar_t *pras;
- int w;
- int h;
- int opt; /* checked by caller! */
- uchar_t *ptrans;
- {
-
- /*
- * reduce an image by half. return 1 if successful, else 0.
- */
-
- register uchar_t *pr;
- register uchar_t *pt;
- register long x;
- register long y;
- register long wold;
- register long w2;
- long hold;
- long h2;
-
-
- /*
- * there is a limit to what is practical...
- */
- if ((w < 10) || (h < 10))
- return (0);
-
-
- if (pras == ptrans)
- {
- /*
- * do in place...
- */
- pr = pras;
- pt = pras;
- }
- else
- {
- /*
- * copy to new image
- */
- pr = pras;
- pt = ptrans;
- }
-
-
- /*
- * do it. skip odd lines and pixels
- */
- wold = w;
- hold = h;
- switch (opt)
- {
- case S_BOTH:
- /*
- * set new sizes
- */
- w2 = wold/2L;
- h2 = hold/2L;
-
- for (y = 0; y < h2; y++)
- {
- for (x = 0; x < w2; x++)
- {
- pt[y*w2 + x] = pr[2*y*wold + x*2];
- }
- }
- break;
-
- case S_HOR:
- /*
- * set new sizes
- */
- w2 = wold/2L;
- h2 = hold;
-
- for (y = 0; y < h2; y++)
- {
- for (x = 0; x < w2; x++)
- {
- pt[y*w2 + x] = pr[y*wold + x*2];
- }
- }
- break;
-
- case S_VERT:
- /*
- * set new sizes
- */
- w2 = wold;
- h2 = hold/2L;
-
- for (y = 0; y < h2; y++)
- {
- for (x = 0; x < w2; x++)
- {
- pt[y*w2 + x] = pr[2*y*wold + x];
- }
- }
- break;
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* cut */
- /*------------------------------*/
- int cut (pras, w, h, x1, y1, x2, y2, ptrans)
- uchar_t *pras;
- int w;
- int h;
- int x1, y1;
- int x2, y2;
- uchar_t *ptrans;
- {
-
- /*
- * cut out a section of the image from pras to ptrans
- */
-
- register uchar_t *pr;
- register uchar_t *pt;
- register long x;
- register long y;
- register long wold;
- register long w2;
- register long h2;
-
-
- /*
- * check for bad coords...
- */
- if ((x1 >= x2) || (y1 >= y2))
- return (0);
- if ((x1 < 0) || (x2 < 0) || (y1 < 0) || (y2 < 0))
- return (0);
- if ((x2 >= w) || (y2 >= h))
- return (0);
- #if 0
- if ((x2 > 639) || (y2 > 399))
- return (0);
- if ((x2 - x1) > w) /* don't fail just limit the cut */
- x2 = x1 + w;
- if ((y2 - y1) > h)
- y2 = y1 + h;
- #endif
-
-
- /*
- * set up pointers...
- */
- if (pras == ptrans)
- {
- /*
- * do in place...
- */
- pr = pras;
- pt = pras;
- }
- else
- {
- /*
- * copy to new image
- */
- pr = pras;
- pt = ptrans;
- }
-
-
- /*
- * do it...
- */
- wold = w;
- w2 = x2 - x1 + 1;
- h2 = y2 - y1 + 1;
- for (y = 0; y < h2; y++)
- {
- for (x = 0; x < w2; x++)
- {
- pt[y*w2 + x] = pr[(y + y1)*wold + (x + x1)];
- }
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* rotate */
- /*------------------------------*/
- int rotate (pras, w, h, angle, ptrans)
- uchar_t *pras;
- int w;
- int h;
- int angle; /* +90, -90, -180 or +180 */
- uchar_t *ptrans;
- {
-
- /*
- * rotate an image +/-90 or +/-180. does NOT work in place (yet)
- *
- * based on (rotating about center):
- *
- * xnew = (x * cos(angle)) + (y * sin(angle))
- * ynew = (y * cos(angle)) - (x * sin(angle))
- *
- * note: 45's should be relatively simple:
- *
- * +45: xnew = (.707 * x) + (.707 * y)
- * ynew = (.707 * y) - (.707 * x)
- *
- * -45: xnew = (.707 * x) - (.707 * y)
- * ynew = (.707 * y) + (.707 * x)
- */
-
- register uchar_t *pr;
- register uchar_t *pt;
- register long xnew;
- register long ynew;
- register long wold;
- register long hold;
-
-
- /*
- * set up pointers...
- */
- if (pras == ptrans)
- {
- /*
- * can't do in place (yet)...
- */
- return (0);
- }
-
-
- /*
- * copy to new image
- */
- pr = pras;
- pt = ptrans;
-
-
- /*
- * do it...
- */
- wold = (long) w;
- hold = (long) h;
- switch (angle)
- {
- case 90:
- /*
- * counter clockwise:
- *
- * xnew = y -> y = xnew
- * ynew = wold - x - 1 x = wold - ynew - 1
- * wnew = hold
- * hnew = wold
- */
- for (ynew = 0L; ynew < wold; ynew++)
- {
- for (xnew = 0L; xnew < hold; xnew++)
- {
- pt[ynew*hold + xnew] = pr[xnew*wold + (wold-ynew-1)];
- }
- }
- break;
-
- case -90:
- /*
- * clockwise...
- *
- * xnew = hold - y - 1 -> y = hold - xnew - 1
- * ynew = x x = ynew
- * wnew = hold
- * hnew = wold
- */
- for (ynew = 0L; ynew < wold; ynew++)
- {
- for (xnew = 0L; xnew < hold; xnew++)
- {
- pt[ynew*hold + xnew] = pr[(hold-xnew-1)*wold + ynew];
- }
- }
- break;
-
- case 180:
- case -180:
- /*
- * clockwise or counter clockwise...
- *
- * xnew = wold - x - 1 -> x = wold - xnew - 1
- * ynew = hold - y - 1 y = hold - ynew - 1
- * wnew = wold
- * hnew = hold
- */
- for (ynew = 0L; ynew < hold; ynew++)
- {
- for (xnew = 0L; xnew < wold; xnew++)
- {
- pt[ynew*wold + xnew] = pr[(hold-ynew-1)*wold + (wold-xnew-1)];
- }
- }
- break;
-
- default:
- /*
- * undefined angle, fail...
- */
- return (0);
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* mirror */
- /*------------------------------*/
- int mirror (pras, w, h, opt, ptrans)
- uchar_t *pras;
- int w;
- int h;
- int opt; /* 0=vert mirror, 1=horiz mirror */
- uchar_t *ptrans;
- {
-
- /*
- * mirror image.
- *
- * vert mirror is:
- *
- * _______|_______
- * | | |
- * | | |
- * | | |
- * |_______|_______|
- * |
- *
- * horiz mirror is:
- *
- * _______________
- * | |
- * __|_______________|__
- * | |
- * |_______________|
- */
-
- register uchar_t *pr;
- register uchar_t *pt;
- register long x;
- register long y;
- register uchar_t ctemp;
-
-
- /*
- * set up pointers...
- */
- if (pras == ptrans)
- {
- /*
- * do in place...
- */
- pr = pras;
- pt = pras;
-
- if (opt)
- {
- /*
- * horizontal mirror
- */
- for (y = 0L; y < h/2; y++)
- {
- for (x = 0L; x < w; x++)
- {
- ctemp = pt[y*w + x];
- pt[y*w + x] = pt[(h-y)*w + x];
- pt[(h-y)*w + x] = ctemp;
- }
- }
- }
- else
- {
- /*
- * vertical mirror
- */
- for (y = 0L; y < h; y++)
- {
- for (x = 0L; x < w/2; x++)
- {
- ctemp = pt[y*w + x];
- pt[y*w + x] = pt[y*w + (w-x)];
- pt[y*w + (w-x)] = ctemp;
- }
- }
- }
- }
- else
- {
- /*
- * copy to new image
- */
- pr = pras;
- pt = ptrans;
-
- if (opt)
- {
- /*
- * horizontal mirror
- */
- for (y = 0L; y < h; y++)
- {
- for (x = 0L; x < w; x++)
- {
- pt[y*w + x] = pr[(h-y-1)*w + x];
- }
- }
- }
- else
- {
- /*
- * vertical mirror
- */
- for (y = 0L; y < h; y++)
- {
- for (x = 0L; x < w; x++)
- {
- pt[y*w + x] = pr[y*w + (w-x-1)];
- }
- }
- }
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* convolve */
- /*------------------------------*/
-
- /*
- * built-in convolution kernels
- *
- * k[0..8] is kernel (always 3x3)
- * k[9] is scaling flag: -1=divide, 1=multiply, 0=no scaling
- * k[10] is scale
- *
- * example:
- * for lp1 with flag -1 (divide) and scale 9, use
- *
- * p = ((p0 * k0) +...+ (p8 * k8)) / 9
- *
- * for hp2 with flag 0 (no scaling), use
- *
- * p = (p0 * k0) +...+ (p8 * k8)
- */
- int lp1[11] = { 1, 1, 1, /* low pass */
- 1, 1, 1,
- 1, 1, 1, -1, 9};
- int lp2[11] = { 1, 1, 1,
- 1, 2, 1,
- 1, 1, 1, -1, 10};
- int lp3[11] = { 1, 2, 1,
- 2, 4, 2,
- 1, 2, 1, -1, 16};
-
- int hp1[11] = {-1,-1,-1, /* hi pass */
- -1, 9,-1,
- -1,-1,-1, 0, 1};
- int hp2[11] = { 0,-1, 0,
- -1, 5,-1,
- 0,-1, 0, 0, 1};
- int hp3[11] = { 1,-2, 1,
- -2, 5,-2,
- 1,-2, 1, 0, 1};
-
- /* shift edge */
- int se1[11] = { 0, 0, 0, /* vertical */
- -1, 1, 0,
- 0, 0, 0, 0, 1};
- int se2[11] = { 0,-1, 0, /* horizontal */
- 0, 1, 0,
- 0, 0, 0, 0, 1};
- int se3[11] = {-1, 0, 0, /* hor and vert */
- 0, 1, 0,
- 0, 0, 0, 0, 1};
-
- /* gradient edge */
- int ge1[11] = { 1, 1, 1, /* north */
- 1,-2, 1,
- -1,-1,-1, 0, 1};
- int ge2[11] = { 1, 1, 1, /* northeast */
- -1,-2, 1,
- -1,-1, 1, 0, 1};
- int ge3[11] = {-1, 1, 1, /* east */
- -1,-2, 1,
- -1, 1, 1, 0, 1};
- int ge4[11] = {-1,-1, 1, /* southeast */
- -1,-2, 1,
- 1, 1, 1, 0, 1};
- int ge5[11] = {-1,-1,-1, /* south */
- 1,-2, 1,
- 1, 1, 1, 0, 1};
- int ge6[11] = { 1,-1,-1, /* southwest */
- 1,-2,-1,
- 1, 1, 1, 0, 1};
- int ge7[11] = { 1, 1,-1, /* west */
- 1,-2,-1,
- 1, 1,-1, 0, 1};
- int ge8[11] = { 1, 1, 1, /* northwest */
- 1,-2,-1,
- 1,-1,-1, 0, 1};
-
- int le1[11] = { 0, 1, 0, /* laplace edge */
- 1,-4, 1,
- 0, 1, 0, 0, 1};
- int le2[11] = {-1,-1,-1,
- -1, 8,-1,
- -1,-1,-1, 0, 1};
- int le3[11] = {-1,-1,-1,
- -1, 9,-1,
- -1,-1,-1, 0, 1};
- int le4[11] = { 1,-2, 1,
- -2, 4,-2,
- 1,-2, 1, 0, 1};
-
- int convolve (pras, w, h, opt, kernel, ptrans)
- uchar_t *pras;
- register int w;
- int h;
- int opt; /* 0=user, 1,2,...=built-in */
- int *kernel; /* user kernel, if any */
- uchar_t *ptrans;
- {
-
- /*
- * convolute an image (3x3). return 1 if successful, else 0.
- *
- * the basic algorithm is:
- *
- * new[i] = sum (k * p ) for i pixels in 3x3 neighborhood
- * i i
- */
-
- uchar_t *pr;
- uchar_t *pt;
- register int val;
- register long x;
- register long y;
- register uchar_t *ps;
- register int *pk;
-
-
- pr = pras;
- pt = ptrans;
-
- if (pras != ptrans)
- {
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- }
-
-
- /*
- * set pointer to user or built-in kernels, depending on opt
- */
- switch (opt)
- {
- case USER_KERN: pk = kernel; break;
-
- case LP1_KERN: pk = lp1; break;
- case LP2_KERN: pk = lp2; break;
- case LP3_KERN: pk = lp3; break;
-
- case HP1_KERN: pk = hp1; break;
- case HP2_KERN: pk = hp2; break;
- case HP3_KERN: pk = hp3; break;
-
- case SE1_KERN: pk = se1; break;
- case SE2_KERN: pk = se2; break;
- case SE3_KERN: pk = se3; break;
-
- case GE1_KERN: pk = ge1; break;
- case GE2_KERN: pk = ge2; break;
- case GE3_KERN: pk = ge3; break;
- case GE4_KERN: pk = ge4; break;
- case GE5_KERN: pk = ge5; break;
- case GE6_KERN: pk = ge6; break;
- case GE7_KERN: pk = ge7; break;
- case GE8_KERN: pk = ge8; break;
-
- case LE1_KERN: pk = le1; break;
- case LE2_KERN: pk = le2; break;
- case LE3_KERN: pk = le3; break;
- case LE4_KERN: pk = le4; break;
-
- default: return (0);
- }
-
-
- /*
- * do it...
- */
- ps = pt;
- for (y = 1; y < h-1; y++)
- {
- for (x = 1; x < w-1; x++)
- {
- val = ((uint_t) ps[(y-1)*w+(x-1)]) * pk[0];
- val += ((uint_t) ps[(y-1)*w+(x )]) * pk[1];
- val += ((uint_t) ps[(y-1)*w+(x+1)]) * pk[2];
- val += ((uint_t) ps[(y )*w+(x-1)]) * pk[3];
- val += ((uint_t) ps[(y )*w+(x )]) * pk[4];
- val += ((uint_t) ps[(y )*w+(x+1)]) * pk[5];
- val += ((uint_t) ps[(y+1)*w+(x-1)]) * pk[6];
- val += ((uint_t) ps[(y+1)*w+(x )]) * pk[7];
- val += ((uint_t) ps[(y+1)*w+(x+1)]) * pk[8];
-
- if ((pk[9] < 0) && pk[10])
- val /= pk[10];
- else if (pk[9] > 0)
- val *= pk[10];
-
- if (val < 0)
- val = 0;
- else if (val > 255)
- val = 255;
-
- ps[(y*w) + x] = (uchar_t) val;
- }
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* blur */
- /*------------------------------*/
- int blur (pras, w, h, ptrans)
- uchar_t *pras;
- register int w;
- int h;
- uchar_t *ptrans;
- {
-
- /*
- * blur an image. return 1 if successful, else 0.
- *
- * the basic algorithm is:
- *
- * new[i] = average of neighboring cells (3x3)
- */
-
- uchar_t *pr;
- uchar_t *pt;
- register long x;
- register long y;
- register uchar_t *ps;
-
-
-
- pr = pras;
- pt = ptrans;
-
- if (pras != ptrans)
- {
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- }
-
-
- /*
- * do it...
- */
- ps = pt;
- for (y = 1; y < h-1; y++)
- {
- for (x = 1; x < w-1; x++)
- {
- ps[(y*w) + x] = (uchar_t) (
- ( (uint_t) ps[(y-1)*w + (x-1)]
- + (uint_t) ps[(y-1)*w + (x )]
- + (uint_t) ps[(y-1)*w + (x+1)]
- + (uint_t) ps[(y )*w + (x-1)]
- + (uint_t) ps[(y )*w + (x )]
- + (uint_t) ps[(y )*w + (x+1)]
- + (uint_t) ps[(y+1)*w + (x-1)]
- + (uint_t) ps[(y+1)*w + (x )]
- + (uint_t) ps[(y+1)*w + (x+1)]) / 9);
- }
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* median */
- /*------------------------------*/
- int median (pras, w, h, ptrans)
- uchar_t *pras;
- int w;
- int h;
- uchar_t *ptrans;
- {
-
- /*
- * median filter an image. return 1 if successful, else 0.
- *
- * the basic algorithm is:
- *
- * new[i] = median of neighboring cells
- */
-
- uchar_t *pr;
- register uchar_t *pt;
- register long x;
- register long y;
- #ifdef INL_SORT
- register int i;
- register uint_t a;
- #endif
- register uint_t *pl;
- uint_t l[9];
-
-
- pr = pras;
- pt = ptrans;
-
- if (pras != ptrans)
- {
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- }
-
-
- /*
- * do it...
- */
- pl = l;
- for (y = 1; y < h-1; y++)
- {
- for (x = 1; x < w-1; x++)
- {
- pl[0] = (uint_t) pt[(y-1)*w + (x-1)];
- pl[1] = (uint_t) pt[(y-1)*w + (x )];
- pl[2] = (uint_t) pt[(y-1)*w + (x+1)];
- pl[3] = (uint_t) pt[(y )*w + (x-1)];
- pl[4] = (uint_t) pt[(y )*w + (x )];
- pl[5] = (uint_t) pt[(y )*w + (x+1)];
- pl[6] = (uint_t) pt[(y+1)*w + (x-1)];
- pl[7] = (uint_t) pt[(y+1)*w + (x )];
- pl[8] = (uint_t) pt[(y+1)*w + (x+1)];
- #ifdef INL_SORT
- /* unroll j loop, too... */
- for (a=pl[1], i=0; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
- pl[i+1] = a;
- for (a=pl[2], i=1; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
- pl[i+1] = a;
- for (a=pl[3], i=2; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
- pl[i+1] = a;
- for (a=pl[4], i=3; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
- pl[i+1] = a;
- for (a=pl[5], i=4; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
- pl[i+1] = a;
- for (a=pl[6], i=5; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
- pl[i+1] = a;
- for (a=pl[7], i=6; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
- pl[i+1] = a;
- for (a=pl[8], i=7; i>=0 && pl[i]>a; i--) pl[i+1]=pl[i];
- pl[i+1] = a;
- #else
- piksrt (9, l);
- #endif
- pt[(y*w) + x] = pl[4];
- }
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* piksrt */
- /*------------------------------*/
- piksrt (num, arr)
- int num;
- uint_t *arr;
- {
-
- /*
- * straight insertion sort (num. rec. in C, pp 243). is N^2 sort,
- * probably ok for N=9. shell sort is 3x faster for N=9.
- */
-
- register uint_t *parr;
- register int n;
- register int i;
- register int j;
- register uint_t a;
-
- n = num;
- parr = arr;
- for (j = 1; j < n; j++)
- {
- for (a=parr[j], i=j-1; i>=0 && parr[i]>a; i--)
- parr[i+1] = parr[i];
-
- parr[i+1] = a;
- }
- }
-
-
-
-
- /*------------------------------*/
- /* findmedian */
- /*------------------------------*/
- uint_t findmedian (num, arr)
- int num;
- uint_t *arr;
- {
-
- /*
- * find median of an array of numbers. this should be faster than sort.
- * there are pathalogical cases: if all are the same or all but 1 or 2
- * are the same...
- */
-
- register uint_t *parr;
- register int n;
- register int i;
- register int j;
- register int count;
- register uint_t a;
-
- parr = arr;
- n = num;
- for (j = 0; j < n; j++)
- {
- for (a = parr[j], count = 0, i = 0; i < n; i++)
- {
- if (i == j)
- continue;
- if (a > parr[i])
- count++;
- }
- if (count == (n>>1))
- return (a);
- }
-
- }
-
-
-
-
- /*------------------------------*/
- /* logscale */
- /*------------------------------*/
- int logscale (pras, w, h, ptrans)
- uchar_t *pras;
- int w;
- int h;
- uchar_t *ptrans;
- {
-
- /*
- * apply log scaling to an image. return 1 if successful, else 0.
- *
- * the basic algorithm is:
- *
- * new[i] = maxval * log(old[i]) / log(maxval)
- * or
- * new[i] = maxval * log2(old[i]) / log2(maxval)
- */
-
- uchar_t *pr;
- uchar_t *pt;
- register ulong_t maxval;
- register ulong_t l2maxval;
- register ulong_t l2pr;
- uchar_t uctmp;
- long x;
- long y;
- long val;
- register long ii;
- register long lim;
- register uchar_t *ps;
-
-
-
- pr = pras;
- pt = ptrans;
-
- if (pras != ptrans)
- {
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- }
-
-
- /*
- * find maxval. here it is max value a pixel can have, 255.
- */
- #if 1
- maxval = 0L;
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- uctmp = pt[(y*w) + x];
- if (uctmp > maxval)
- maxval = (ulong_t) uctmp;
- }
- }
- #endif
- /*!!! maxval = 255L;*/
-
-
- /*
- * do it...
- */
- #if 1
- l2maxval = (ulong_t) Log2x10 ((uint_t) maxval);
- if (l2maxval == 0)
- return (0);
- #endif
- /*!!! l2maxval = 80;*/ /* approx 10 times log2(255) */
-
-
- #ifdef DBL_LOOP
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- l2pr = (ulong_t) Log2x10 ((uint_t) pt[(y*w)+x]);
- pt[(y*w) + x] = (uchar_t) ((maxval * l2pr) / l2maxval);
- }
- }
- #else
- lim = (long) w * (long) h;
- for (ps = pt, ii = 0L; ii < lim; ii++)
- {
- l2pr = (ulong_t) Log2x10 ((uint_t) *ps);
- *ps++ = (uchar_t) ((maxval * l2pr) / l2maxval);
- }
- #endif
-
- return (1);
- }
-
-
-
-
-
- /*------------------------------*/
- /* Log2x10 */
- /*------------------------------*/
- int Log2x10(x)
- uint_t x;
- {
- /*
- * VERY approximate log base 2 times 10. basically finds MS bit...
- */
- if (x < 256) goto lobyte;
- if (x & 0x8000) return (150);
- if (x & 0x4000) return (140);
- if (x & 0x2000) return (130);
- if (x & 0x1000) return (120);
- if (x & 0x0800) return (110);
- if (x & 0x0400) return (100);
- if (x & 0x0200) return (90);
- if (x & 0x0100) return (80);
- lobyte:
- if (x == 0x00ff)
- return (80);
- if (x == 0x0000)
- return (1);
- if (x & 0x0080)
- {
- if (x & 0x0040)
- return (78);
- else if (x & 0x0020)
- return (75);
- else
- return (71);
- }
- if (x & 0x0040)
- {
- if (x & 0x0020)
- return (68);
- else if (x & 0x0010)
- return (65);
- else
- return (61);
- }
- if (x & 0x0020)
- {
- if (x & 0x0010)
- return (58);
- else if (x & 0x0008)
- return (55);
- else
- return (51);
- }
- if (x & 0x0010)
- {
- if (x & 0x0008)
- return (48);
- else if (x & 0x0004)
- return (45);
- else
- return (41);
- }
- if (x & 0x0008)
- {
- if (x & 0x0004)
- return (38);
- else if (x & 0x0002)
- return (35);
- else
- return (31);
- }
- if (x & 0x0004)
- {
- if (x & 0x0002)
- return (28);
- else if (x & 0x0001)
- return (25);
- else
- return (21);
- }
- if (x & 0x0002)
- {
- if (x & 0x0001)
- return (18);
- else
- return (13);
- }
- if (x & 0x0001) return (10);
- return (0);
- }
-
-
-
-
- /*------------------------------*/
- /* contrast */
- /*------------------------------*/
- int contrast (pras, w, h, thresh, hist, ptrans)
- uchar_t *pras;
- int w;
- int h;
- long thresh;
- long *hist;
- uchar_t *ptrans;
- {
-
- /*
- * apply contrast expansion to an image. return 1 if successful, else 0.
- *
- * the basic algorithm is:
- *
- * new[i] = maxval * (old[i] - lo) / (hi - lo)
- *
- * where lo to hi is new contrast range
- */
-
- uchar_t *pr;
- uchar_t *pt;
- ulong_t maxval;
- uchar_t uctmp;
- long x;
- long y;
- long hi_lo;
- long newlo;
- long newhi;
- int i;
- register long val;
- register long rng;
- register long lim;
- register long ii;
- register uchar_t *ps;
-
-
- pr = pras;
- pt = ptrans;
-
- if (pras != ptrans)
- {
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- }
-
-
- /*
- * get current histogram...
- */
- if (do_hist (pt, w, h, hist) == 0)
- return (0);
-
-
- /*
- * find intensities on either side of hist where pixel count
- * exceeds thresh
- */
- for (i = 0; i < HISTSIZ; i++)
- {
- if (hist[i] > thresh)
- break;
- }
- newlo = i;
- for (i = HISTSIZ-1; i > newlo; i--)
- {
- if (hist[i] > thresh)
- break;
- }
- newhi = i;
-
-
- /*
- * do it. set pixels below lower threshold 0 and those above to 255.
- * contrast expand pixels between...
- */
- #ifdef DBL_LOOP
- rng = newhi - newlo + 1;
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- val = (ulong_t) pt[(y*w) + x];
- if (val < newlo)
- pt[(y*w) + x] = 0;
- else if (val > newhi)
- pt[(y*w) + x] = 255;
- else
- {
- pt[(y*w) + x] = (uchar_t) ((255L * (val - newlo)) / rng);
- }
- }
- }
- #else
- rng = newhi - newlo + 1;
- lim = (long) w * (long) h;
- for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
- {
- val = (ulong_t) *ps;
- if (val < newlo)
- *ps = 0;
- else if (val > newhi)
- *ps = 255;
- else
- *ps = (uchar_t) ((255L * (val - newlo)) / rng);
- }
- #endif
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* brighten */
- /*------------------------------*/
- int brighten (pras, w, h, brite, ptrans)
- uchar_t *pras;
- int w;
- int h;
- register int brite;
- uchar_t *ptrans;
- {
-
- /*
- * brighten an image. return 1 if successful, else 0.
- *
- * the basic algorithm is:
- *
- * new[i] = old[i] + brite
- */
-
- uchar_t *pr;
- uchar_t *pt;
- long x;
- long y;
- int sign;
- register uint_t val;
- register long ii;
- register long lim;
- register uchar_t *ps;
-
-
-
- pr = pras;
- pt = ptrans;
-
- if (pras != ptrans)
- {
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- }
-
-
- sign = 0;
- if (brite < 0)
- {
- sign = 1;
- brite = -brite;
- }
-
-
- /*
- * do it...
- */
- if (sign)
- {
- #ifdef DBL_LOOP
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- val = (uint_t) pt[y*w + x];
- if (val < brite)
- val = 0;
- else
- val -= brite;
- pt[(y*w) + x] = (uchar_t) val;
- }
- }
- #else
- lim = (long) w * (long) h;
- for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
- {
- if ((uint_t) *ps < brite)
- *ps = 0;
- else
- *ps -= brite;
- }
- #endif
- }
- else
- {
- #ifdef DBL_LOOP
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- val = (uint_t) ((uint_t) pt[y*w + x] + brite);
- if (val > 255)
- val = 255;
- pt[(y*w) + x] = (uchar_t) val;
- }
- }
- #else
- lim = (long) w * (long) h;
- for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
- {
- val = (uint_t) ((uint_t) *ps + brite);
- if (val > 255)
- val = 255;
- *ps = (uchar_t) val;
- }
- #endif
- }
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* invert */
- /*------------------------------*/
- int invert (pras, w, h, thresh, ptrans)
- uchar_t *pras;
- int w;
- int h;
- int thresh;
- uchar_t *ptrans;
- {
-
- /*
- * invert (negate) an image. return 1 if successful, else 0.
- *
- * the basic algorithm is:
- *
- * new[i] = 255 - old[i]
- */
-
- uchar_t *pr;
- uchar_t *pt;
- long x;
- long y;
- int sign;
- register long lim;
- register long ii;
- register int thr;
- register uchar_t *ps;
-
-
- pr = pras;
- pt = ptrans;
-
- if (pras != ptrans)
- {
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- }
-
-
- sign = 0;
- if (thresh < 0)
- {
- sign = 1;
- thresh = -thresh;
- }
-
-
- /*
- * do it...
- */
- #ifdef DBL_LOOP
- if (thresh == 0)
- {
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- pt[(y*w) + x] = 255 - pt[(y*w) + x];
- }
- }
- }
- else if (sign)
- {
- /*
- * invert only below thresh
- */
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- if ((uint_t) pt[(y*w) + x] < thresh)
- pt[(y*w) + x] = 255 - pt[(y*w) + x];
- }
- }
- }
- else
- {
- /*
- * invert only above thresh
- */
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- if ((uint_t) pt[(y*w) + x] > thresh)
- pt[(y*w) + x] = 255 - pt[(y*w) + x];
- }
- }
- }
- #else
- lim = (long) h * (long) w;
- thr = thresh;
- if (thr == 0)
- {
- for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
- {
- *ps = 255 - *ps;
- }
- }
- else if (sign)
- {
- /*
- * invert only below thresh
- */
- for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
- {
- if ((uint_t) *ps < thr)
- *ps = 255 - *ps;
- }
- }
- else
- {
- /*
- * invert above below thresh
- */
- for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
- {
- if ((uint_t) *ps > thr)
- *ps = 255 - *ps;
- }
- }
- #endif
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* threshold */
- /*------------------------------*/
- int threshold (pras, w, h, thresh, ptrans)
- uchar_t *pras;
- int w;
- int h;
- int thresh;
- uchar_t *ptrans;
- {
-
- /*
- * threshold an image. return 1 if successful, else 0.
- *
- * the basic algorithm is:
- *
- * new[i] = 0 if old[i] <= thresh
- * new[i] = 255 if old[i] > thresh
- */
-
- uchar_t *pr;
- uchar_t *pt;
- long x;
- long y;
- uint_t val;
- register long ii;
- register long lim;
- register uchar_t *ps;
-
-
- pr = pras;
- pt = ptrans;
-
- if (pras != ptrans)
- {
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- }
-
-
- /*
- * do it...
- */
- #ifdef DBL_LOOP
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- val = (uint_t) pt[(y*w) + x];
- if (val > thresh)
- pt[(y*w) + x] = 255;
- else
- pt[(y*w) + x] = 0;
- }
- }
- #else
- lim = (long) h * (long) w;
- for (ps = pt, ii = 0L; ii < lim; ii++, ps++)
- {
- if ((uint_t) *ps > thresh)
- *ps = 255;
- else
- *ps = 0;
- }
- #endif
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* histeq */
- /*------------------------------*/
- int histeq (pras, w, h, hist, ptrans)
- uchar_t *pras;
- int w;
- int h;
- long *hist;
- uchar_t *ptrans;
- {
-
- /*
- * histogram equalization of image. return 1 if successful, else 0.
- */
-
- long p_r[HISTSIZ];
- long s_k[HISTSIZ];
- long s_kapprx[HISTSIZ];
- uchar_t *pr;
- uchar_t *pt;
- int i;
- long count;
-
-
-
- pr = pras;
- pt = ptrans;
-
- if (pras != ptrans)
- {
- /*
- * first copy orig image to transform image
- */
- copyrast (pr, w, h, pt);
- }
-
-
- /*
- * get current histogram...
- */
- if (do_hist (pt, w, h, hist) == 0)
- return (0);
-
-
- /*
- * find prob density function (p_r), transformation function (s_k),
- * and new distribution. note the 1000 to avoid floats...
- */
- count = (long) w * (long) h;
- for (i = 0; i < HISTSIZ; i++)
- {
- p_r[i] = (hist[i] * 1000L) / count;
- }
- for (s_k[0] = p_r[0], i = 1; i < HISTSIZ; i++)
- {
- s_k[i] = s_k[i-1] + p_r[i];
- }
- for (i = 0; i < HISTSIZ; i++)
- {
- /* the 500 is for rounding to nearest int... */
- s_kapprx[i] = ((s_k[i] * 255L) + 500L) / 1000L;
- }
-
- #if 0
- printf ("\n i hist p_r s_k s_kapprx\n");
- for (count = 0, i = 0; i < HISTSIZ; i++)
- {
- printf ("%5d%10ld%10ld%10ld%10ld\n",
- i,hist[i],p_r[i],s_k[i],s_kapprx[i]);
- }
- #endif
-
- /*
- * now redistribute. s_kapprx will contain the new value for
- * a given pixel intensity
- */
- redistribute (pt, w, h, s_kapprx);
-
- return (1);
- }
-
-
-
-
- /*------------------------------*/
- /* redistribute */
- /*------------------------------*/
- int redistribute (pras, w, h, s_kapprx)
- uchar_t *pras;
- int w;
- int h;
- register long *s_kapprx;
- {
-
- /*
- * redistribute pixels. each pixel set to value given by s_kapprx
- */
-
- register uchar_t *pr;
- register long ii;
- register long lim;
-
-
- lim = (long) w * (long) h;
- for (pr = pras, ii = 0L; ii < lim; ii++, pr++)
- {
- *pr = (uchar_t) s_kapprx[(uint_t) *pr];
- }
- }
-
-
-
-
- /*------------------------------*/
- /* copyrast */
- /*------------------------------*/
- int copyrast (ps, w, h, pd)
- uchar_t *ps; /* source */
- int w;
- int h;
- uchar_t *pd; /* dest */
- {
-
- /*
- * copy an image. return 1 if successful, else 0.
- */
-
- #ifdef DBL_LOOP
- long x;
- long y;
-
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- pd[(y*w) + x] = ps[(y*w) + x];
- }
- }
- #else
- register long ii;
- register long lim;
-
- lim = (long) w * (long) h;
- for (ii = 0L; ii < lim; ii++)
- *pd++ = *ps++;
- #endif
- return (1);
- }
-
-