--- a/tiff.c
+++ b/tiff.c
@@ -23,6 +23,8 @@
 #include "filter.h"
 
 #include "tiffio.h"
+
+#include "ZComb.h"
 
 int readplanarTIFF(Image *im, TIFF* tif);
 void RGBAtoARGB(UCHAR* buf, int width, int bitsPerPixel);
@@ -64,7 +66,7 @@
 	   	return readplanarTIFF(im, tif);
 	}
 	
-	if (TIFFReadRGBAImage(tif, w, h, (unsigned long*)*(im->data), 0)) {
+	if (TIFFReadRGBAImage(tif, w, h, (void*)*(im->data), 0)) {
 		// Convert agbr to argb; flip image vertically
 		unsigned char *cline, *ct, *cb;
 		int h2 = im->height/2, y;
@@ -166,331 +168,6 @@
 
 }
 
-//begin Rik's mask-from-focus hacking (ZComb <stuff>)
-
-// This is experimental code introduced by Rik Littlefield,
-// rj.littlefield@computer.org .  See postings on ptX archives
-// http://www.email-lists.org/pipermail/ptx/
-// and Panorama Tools forum
-// http://groups.yahoo.com/group/PanoTools/
-// on 6/18/2004 and surrounding for more info. 
-
-#define ZCOMBLOGFILENAME "c:\\Rikslog.txt"
-
-static struct {  // ZComb parameters
-	int enabled;
-	int passNum;
-	int fnameSet;
-	int width;
-	int height;
-	int currentImageNum;
-	char firstFname[1024];   // name of first file
-	float *accumFocus;       // array width*height of estimated focus accumulated across all images
-	float *estFocus;         // array width*height of estimated focus for current image
-	int *bestLevel;          // array width*height of image number of best focus
-	int masktype;
-	int focusWindowHalfwidth;
-	int smoothingWindowHalfwidth;
-} ZComb;
-
-void ZCombSetDisabled() {
-	ZComb.enabled = 0;
-}
-
-void ZCombSetEnabled() {
-	ZComb.enabled = 1;
-	ZComb.masktype = 2;
-	ZComb.focusWindowHalfwidth = 4;
-	ZComb.smoothingWindowHalfwidth = 4;
-}
-
-void ZCombSetMaskType(int mt) {
-	ZComb.masktype = mt;
-}
-
-void ZCombSetFocusWindowHalfwidth(int fwh) {
-	ZComb.focusWindowHalfwidth = fwh;
-}
-
-void ZCombSetSmoothingWindowHalfwidth(int swh) {
-	ZComb.smoothingWindowHalfwidth = swh;
-}
-
-void ZCombLogMsg(char *fmt, char *sarg) {
-	FILE* logfile;
-	char* logfileName = ZCOMBLOGFILENAME;
-	if ((logfile = fopen(logfileName, "a")) == NULL) {
-		PrintError("can't open %s\n", logfileName);
-		return;
-	}
-	fprintf (logfile,fmt,sarg);
-	fclose (logfile);
-}
-
-void ZCombInit() {
-	ZComb.fnameSet = 0;
-	ZComb.passNum = 1;
-	ZComb.currentImageNum = 0;
-}
-
-int ZCombInitStats(int width, int height) {
-	int row, col;
-	ZComb.width = width;
-	ZComb.height = height;
-	if (ZComb.accumFocus != NULL) {
-		free(ZComb.accumFocus);
-		free(ZComb.estFocus);
-		free(ZComb.bestLevel);
-	}
-	ZComb.accumFocus = malloc(width*height*sizeof(float));
-	ZComb.estFocus   = malloc(width*height*sizeof(float));
-	ZComb.bestLevel  = malloc(width*height*sizeof(int));
-	if (ZComb.accumFocus == NULL || ZComb.estFocus == NULL || ZComb.bestLevel == NULL) {
-		PrintError("Not enough memory");
-		ZCombLogMsg("Insufficient memory in ZCombInitStats\n",NULL);
-		return -1;
-	}
-	for (row=0; row < height; row++) {
-		for (col=0; col < width; col++) {
-			ZComb.accumFocus[row*width+col] = 0.0;
-			ZComb.bestLevel[row*width+col] = 1;
-		}
-	}
-	return 0;
-}
-
-#define VARIANCEFUDGE 0.0 // increase in variance that we require to say that we have better focus.
-                          // early experiments show better results with variance fudge = 0,
-                          // so this is not (yet) brought out to be runtime settable
-void ZCombAccumEstFocus() {
-	int row, col;
-	int width = ZComb.width;
-	int height = ZComb.height;
-	for (row=0; row < height; row++) {
-		for (col=0; col < width; col++) {
-			if (ZComb.accumFocus[row*width+col] < ZComb.estFocus[row*width+col] - VARIANCEFUDGE) {
-				ZComb.accumFocus[row*width+col] = ZComb.estFocus[row*width+col];
-				ZComb.bestLevel[row*width+col] = ZComb.currentImageNum;
-			}
-		}
-	}
-}
-
-float ZCombGetSmoothedLevel(int row, int col) {
-	int n;             /* number of pixels used in kernel */
-	int sumLevels;
-	int kr, kc;
-	int height = ZComb.height;
-	int width = ZComb.width;
-	int khw = ZComb.smoothingWindowHalfwidth;
-
-	sumLevels = 0;
-	n = 0;
-	for (kr = row-khw; kr <= row+khw; kr++) {
-		for (kc = col-khw; kc <= col+khw; kc++) {
-			if (kr < 0 || kr >= height || kc < 0 || kc >= width) {
-				int junk = 0;  /* do nothing, allow place for breakpoint */
-			} else {
-				sumLevels += ZComb.bestLevel[kr*width+kc];
-				n++;
-			}
-		}
-	}
-	if (n == 0) {
-		PrintError("ZCombGetSmoothedLevel: n==0");
-		return 0.0;
-	}
-	return (float)sumLevels / (float)n;
-}
-
-/* Estimate focus for current image,
-   produce result as float array in ZComb.estFocus.
-   In this version, the estimated focus is computed from whatever
-   pixel values are sitting in "red" channel of the ARGB
-   input image.  These appear to actually be the red channel of
-   the RGB image, although the green and blue channels are not
-   those of the RGB data.  The estimate is the local variance.
-   */
-void ZCombEstimateFocus(Image *im) {
-	int row;
-	int col;
-#define KERNELSPARSENESS 1  // make larger than 1 to run faster but more approximate
-	int n;             /* number of pixels used in kernel */
-	UCHAR *pg;         /* pointer to gray (red) value */
-	UCHAR g;           /* gray value */
-	UCHAR *pa;         /* pointer to alpha value */
-	int sumg, sumgsq;  /* sum of gray values and gray values squared */
-	int ming, maxg;    /* minimum and maximum gray levels in each region */
-	int kr, kc;
-	int height = im->height;
-	int width = im->width;
-	int khw = ZComb.focusWindowHalfwidth;  /* kernel halfwidth */
-
-	for (row = 0; row < height; row++) {
-		for (col = 0; col < width; col++) {
-			sumg = 0;
-			sumgsq = 0;
-			n = 0;
-			ming = 256;
-			maxg = 0;
-			for (kr = row-khw; kr <= row+khw; kr+=KERNELSPARSENESS) {
-				for (kc = col-khw; kc <= col+khw; kc+=KERNELSPARSENESS) {
-					if (kr < 0 || kr >= height || kc < 0 || kc >= width) {
-						int junk = 0;  /* do nothing, allow place for breakpoint */
-					} else {
-						pg = *(im->data) + kr*(im->bytesPerLine) + kc*4 + 1;  /* ARGB */
-						g = *pg;    /* pixel value */
-						// if (g < ming) ming = g;
-						// if (g > maxg) maxg = g;
-						pa = *(im->data) + kr*(im->bytesPerLine) + kc*4 + 2;  /* ARGB */
-						if (*pa != 0) { // include only valid pixels in contrast estimate
-							sumg += g;
-							sumgsq += g*g;
-							n++;
-						}
-					}
-				}
-			}
-			pa = *(im->data) + row*(im->bytesPerLine) + col*4 + 2;  /* ARGB */
-			if (*pa == 0) { // do not store contrast estimate at invalid pixels
-				ZComb.estFocus[row*width+col] = 0.0;
-			}
-			else
-			if (n <= 1 || maxg == ming) {
-				ZComb.estFocus[row*width+col] = 0.0;
-			} else {
-				/* variance squared */
-				ZComb.estFocus[row*width+col] = ((n*sumgsq - sumg*sumg) / (float)(n*(n-1)));
-//											   /((maxg-ming)*(maxg-ming));
-			}
-		}
-	}
-}
-
-void ZCombCopyEstFocusToBlue(Image *im) {
-	int row;
-	int col;
-	UCHAR *pg;         /* pointer to gray (blue) value */
-	UCHAR g;           /* gray value */
-	int height = im->height;
-	int width = im->width;
-
-	float maxEst = 0.0;
-	for (row = 0; row < height; row++) {
-		for (col = 0; col < width; col++) {
-			if (ZComb.estFocus[row*width+col] > maxEst) {
-				maxEst = ZComb.estFocus[row*width+col];
-			}
-		}
-	}
-
-	for (row = 0; row < height; row++) {
-		for (col = 0; col < width; col++) {
-			pg = *(im->data) + row*(im->bytesPerLine) + col*4 + 3;  /* ARGB */
-			g = (int) (255.0*ZComb.estFocus[row*width+col]/maxEst);
-			*pg = g;
-		}
-	}
-}
-
-void ZCombSetMaskFromFocusData(Image *im) {
-	int row;
-	int col;
-	UCHAR *pg;         /* pointer to gray (blue) value */
-	UCHAR g;           /* gray value */
-	int height = im->height;
-	int width = im->width;
-	float flev;
-
-	for (row = 0; row < height; row++) {
-		for (col = 0; col < width; col++) {
-			pg = *(im->data) + row*(im->bytesPerLine) + col*4 + 0;  /* ARGB */
-			if (ZComb.masktype == 0 || ZComb.masktype == 1) {
-				// generate hard-edged masks using unsmoothed depth level -- select strictly pixels belonging to best-focused image
-				if ((ZComb.masktype == 0 && ZComb.currentImageNum == ZComb.bestLevel[row*width+col])  // generate non-nested masks
-				 || (ZComb.masktype == 1 && ZComb.currentImageNum <= ZComb.bestLevel[row*width+col])  // generate a stack of nested masks
-				) {
-					*pg = 255;
-				} else {
-					*pg = 0;
-				}
-			} else if (ZComb.masktype == 2) {
-				// generate blending masks using smoothed depth level -- typically makes much better looking images
-				flev =  ZCombGetSmoothedLevel(row,col);
-				if (ZComb.currentImageNum <= flev+0.01) {
-					*pg = 255;
-				} else if (ZComb.currentImageNum > flev+1.01) {
-					*pg = 0;
-				} else {
-					*pg = 255 - (UCHAR) (255.0*(ZComb.currentImageNum - (flev+0.01)));
-				}
-			} else {
-				*pg = 255;  // unrecognized masktype, just keep from crashing
-			}
-			// following is a hack that forces nominally binary masks to actually have a single
-			// intermediate value, which keeps Jim Watter's PSD modifications from incorrectly
-			// assigning shape mask = visibility mask.
-			if (row == 0 && col == 0) {
-				if (*pg == 0) *pg = 1;
-				if (*pg == 255) *pg = 254;
-			}
-		}
-	}
-}
-
-void ZCombSetGreenTo255(Image *im) {
-	int row;
-	int col;
-	UCHAR *pg;         /* pointer to gray (green) value */
-	int height = im->height;
-	int width = im->width;
-
-	for (row = 0; row < height; row++) {
-		for (col = 0; col < width; col++) {
-			pg = *(im->data) + row*(im->bytesPerLine) + col*4 + 2;  /* ARGB */
-			*pg = 255;
-		}
-	}
-}
-
-int ZCombSeeImage(Image *im, char *filename) {
-	if (!ZComb.enabled) {
-		// ZCombLogMsg ("Z-combining disabled\n",NULL);
-		return 0;
-	}
-	ZCombLogMsg ("Z-combining enabled\n",NULL);
-	ZCombLogMsg ("writeTIFF called on file %s\n",filename);
-	ZCombLogMsg ("   image name = %s\n",im->name);
-	if (ZComb.fnameSet && strcmp(ZComb.firstFname,filename) == 0) {
-		ZCombLogMsg ("Starting second pass\n",NULL);
-		ZComb.passNum = 2;
-		ZComb.currentImageNum = 0;
-	}
-	if (!ZComb.fnameSet) {
-		ZComb.fnameSet = 1;
-		ZComb.passNum = 1;
-		strcpy(ZComb.firstFname,filename);
-		ZCombLogMsg("   initialFname set to %s\n",ZComb.firstFname);
-		if (ZCombInitStats(im->width,im->height)) {
-			return -1;
-		}
-	}
-	ZComb.currentImageNum++;
-	if (ZComb.passNum == 1) {
-		ZCombEstimateFocus(im);
-		ZCombAccumEstFocus();
-		// ZCombCopyEstFocusToBlue(im); // for debugging purposes
-		// ZCombSetGreenTo255(im);
-	}
-	if (ZComb.passNum == 2) {
-		ZCombEstimateFocus(im);
-		ZCombSetMaskFromFocusData(im);
-	}
-	return 0;
-}
-
-// end Rik's mask-from-focus hacking
-
 int writeTIFF(Image *im, fullPath *sfile){
 	char string[512];
 	TIFF *tif;