With the addition of the **Algorithms** menu in the *xv
controls* window, *xv* can now perform standard
image-processing algorithms. However, I'm not really into the
whole image-processing *scene*, so I've only implemented a
few algorithms.

Please! Feel free to add your own algorithms, it's easy, and
if you'd care to donate them, they may find their way into future
official releases of *xv*, and eternal fame and glory will
be yours, in the form of a credit in the "Hall of Fame"
listing..

For the purposes of this example, I'll be adding a new
algorithm called 'Noise' which will simply add (or subtract) a
small random amount from each pixel in the image. I can't see
that this would be a very useful algorithm (which is why it's not
already *in xv* ), but then again, what do I know about such
things...

Edit `xv.h` , and find the block that starts with:

#define ALG_NONE 0 #define ALG_SEP1 1 /* separator */ #define ALG_BLUR3 2

and add an additional definition at the end of the list (right
before `ALG_MAX` ) for your algorithm. Don't forget to
increment `ALG_MAX` to reflect the additional algorithm:

#define ALG_TINF 6 #define ALG_OIL 7 #define ALG_NOISE 8 #define ALG_MAX 9

Edit `xvctrl.c` , and find where the array `algMList[]`
is initialized. Add a string for your new algorithm. The string's
position in the list must match the number that you assigned to
the `ALG_*` value in `xv.h` :

static char *algMList[] = { "Undo All", MBSEP, "Blur (3x3)", "Blur (7x7)", "Edge Detection", "Emboss", "Oil Painting", "Add Noise"};

Edit `xvalg.c` , and find the `DoAlg()`
function. This function is called with an `ALG_*` value
whenever something is selected from the **Algorithms** menu.
Add a case for the new `ALG_NOISE` value, and have it call
your top-level function, with no parameters:

case ALG_TINF: EdgeDetect(1); break; case ALG_OIL: OilPaint(); break; case ALG_NOISE: Noise(); break; }

Write your top-level function:

/************************/ static void Noise() { byte *pic24, *tmpPic; /* turn on flapping fish cursor */ WaitCursor(); /* mention progress... */ SetISTR(ISTR_INFO, "Running Noise algorithm..."); /* generates a 24-bit version ofpic, if necessary. also generates a w*h*3 buffer (tmpPic) to hold intermediate results */ if (start24bitAlg(&pic24, &tmpPic)) return; /* do the noise algorithm */ doNoise(pic24, pWIDE,pHIGH, tmpPic); /* if we're in PIC8 mode, convert pic24 back to PIC8. free pic24 & tmppic */ end24bitAlg(pic24, tmpPic); }

`Now write the
function that does the work of your algorithm. It will be passed
a 24-bit RGB source image ``srcpic``, its
dimensions ``w,h,`` and a destination 24-bit
image ``dstpic`` of the same size. If your
algorithm is normally meant to be run on greyscale images (as so
many image algorithms are), you should simply run it separately
for each of the ``Red, Green, ``and ``Blue``
planes, and glue the results back together at the end of the
algorithm.`

/************************/ static void doNoise(srcpic, w, h, dstpic) byte *srcpic, *dstpic; int w, h; { byte *sp, *dp; int x,y,newr,newg,newb; printUTime("start of doNoise"); /* print timing info */ for (y=0; y<h; y++) { if ((y & 15) == 0) WaitCursor(); sp = srcpic + y*w*3; /* position sp,dp at start of line #y */ dp = dstpic + y*w*3; for (x=0; x<w; x++) { newr = sp[0] + (random()&0x3f)-0x20; /* add noise to red component */ newg = sp[1] + (random()&0x3f)-0x20; /* add noise to green component */ newb = sp[2] + (random()&0x3f)-0x20; /* add noise to blue component */ RANGE(newr, 0, 255); /* clip values to range[0..255] inclusive */ RANGE(newg, 0, 255); /* RANGE() is defined in xv.h */ RANGE(newb, 0, 255); dp[0] = (byte) newr; /* store new values in dstpic */ dp[1] = (byte) newg; dp[2] = (byte) newb; sp += 3; dp += 3; /* advance to next 3-byte pixel in images */ } } printUTime("end of doConvolv"); }

`Note that this
algorithm is written in about as non-optimal a way as possible,
for the sake of clarity.`

`Also note that if
you define`` ``TIMING_TEST`
at the beginning of `xvalg.c` , it will turn on code that
will let you measure the CPU time your algorithm requires. Once
you have a working algorithm, you may find this useful if you
wish to try to optimize your algorithm for increased performance.

And that's all there is to it!