--- a
+++ b/panTools.cpp
@@ -0,0 +1,276 @@
+
+// PTLens, Copyright (C) 2004, Thomas Niemann
+// email: thomasn@epaperpress.com, subject=ptlens
+// 
+// This program is free software; you can redistribute 
+// it and/or modify it under the terms of the GNU
+// General Public License as published by the Free 
+// Software Foundation; either version 2 of the 
+// License, or (at your option) any later version. 
+//
+// This program is distributed in the hope that it will 
+// be useful, but WITHOUT ANY WARRANTY; without even 
+// the implied warranty of MERCHANTABILITY or FITNESS 
+// FOR A PARTICULAR PURPOSE. See the GNU General Public 
+// License for more details. 
+// 
+// You should have received a copy of the GNU General 
+// Public License along with this program; if not, 
+// write to the Free Software Foundation, Inc., 675 
+// Mass Ave, Cambridge, MA 02139, USA.
+
+#include "main.h"
+
+typedef void (*dllEntry)();
+extern int tool;
+
+static dllEntry getAddr(char *func) {
+	dllEntry addr = (dllEntry) GetProcAddress(DLL.hPano12, func); 
+    if (addr == NULL) {
+        FreeLibrary(DLL.hPano12);
+        display("Pano12.dll is invalid (%s).", func);
+    }
+	return addr;
+}
+
+#define SETFUNC(x)\
+	DLL. ## x = (x ## _proc)getAddr(#x);\
+	if (DLL. ## x == NULL) goto err_exit
+    
+
+static int loadLibrary() {
+	// Get a handle to the DLL module.
+    DLL.hPano12 = LoadLibrary("pano12.dll");
+    if (DLL.hPano12 == NULL)
+        return display("File pano12.dll is not correctly installed.");
+
+	// initialize all function pointers
+#if 0  // unused functions
+	SETFUNC(ConvFileName);
+	SETFUNC(PrintError);
+	SETFUNC(SetAdjustDefaults);
+	SETFUNC(addLayerToFile);
+	SETFUNC(mymalloc);
+	SETFUNC(readPrefs);
+	SETFUNC(writePSDwithLayer);
+	SETFUNC(writeTIFF);
+#endif
+
+	SETFUNC(FourToThreeBPP);	
+	SETFUNC(SetWindowOwner);
+	SETFUNC(CopyImageData);
+	SETFUNC(SetImageDefaults);
+	SETFUNC(filter_main);
+	SETFUNC(writePSD);
+	SETFUNC(myfree);
+
+	return 0;
+
+err_exit:
+	FreeLibrary(DLL.hPano12);	
+	return 1;
+}
+
+static void fileName(char *buf) {
+	int pre;
+
+	switch(tool) {
+	case _perspective:	pre = 0; break;
+	case _correct:      pre = 1; break;
+	case _remap:        pre = 2; break;
+	case _adjust:       pre = 3; break;
+	}
+    
+	// find filename
+	int i = 0;
+	while(1) {
+		sprintf(buf, "%s%d.%d.psd", PAN.sprefs.sFile.name, pre, i++);
+
+		HANDLE hFile = CreateFile(
+			buf,				      // file name
+			GENERIC_READ,             // access mode
+			FILE_SHARE_READ,          // share mode
+			NULL,                     // security
+			OPEN_EXISTING,            // how to create
+			0,                        // flags & attributes
+			NULL);                    // template file
+
+		if (hFile == INVALID_HANDLE_VALUE) return;
+		CloseHandle(hFile);
+	}
+}
+
+int panTools() {
+	void *buf, *alpha;
+	PlatformData* platform = NULL;
+
+	if (!DLL.initDLL) {
+		if (loadLibrary()) return 1;
+		DLL.initDLL = true;
+	}
+	
+	platform = (PlatformData*)(gFr->platformData);
+
+	// initialize PHOtoshop settings
+	PHO.imageWidth = gFr->imageSize.h;
+	PHO.imageHeight = gFr->imageSize.v;	
+	PHO.imageDepth = gFr->depth;
+	
+	// PSP sets depth to zero!
+	if (PHO.imageDepth != 16) PHO.imageDepth = 8;
+
+	PHO.imageChannelSize = PHO.imageWidth * PHO.imageHeight * (PHO.imageDepth/8);
+	PHO.imageSize = PHO.imageChannelSize * 3;
+
+	// initialize images
+	DLL.SetImageDefaults(&PAN.image1);
+	DLL.SetImageDefaults(&PAN.image2);
+
+	// assume no alpha channel needed
+	PAN.image1.width = PHO.imageWidth;
+	PAN.image1.height = PHO.imageHeight;
+	PAN.image1.bitsPerPixel = PHO.imageDepth * 3;
+	PAN.image1.bytesPerLine = PHO.imageWidth * PAN.image1.bitsPerPixel/8;
+	PAN.image1.dataSize = PHO.imageHeight * PAN.image1.bytesPerLine;
+	PAN.image1.dataformat = _RGB;
+	PAN.image1.format = _rectilinear;
+	PAN.image1.data = (unsigned char **)&buf;
+
+	// setup tr
+    memset(&PAN.tr, 0, sizeof(TrformStr));
+    PAN.tr.tool = tool;
+    PAN.tr.success = 1;
+	PAN.tr.data = &PAN.prefs;
+	PAN.tr.src = &PAN.image1;
+	PAN.tr.dest = &PAN.image2;
+
+	if (!PAN.initPrefs) {
+		// 1st call to filter_main
+		PAN.tr.mode = _setprefs;
+		DLL.SetWindowOwner((HWND)platform->hwnd);
+		DLL.filter_main(&PAN.tr, &PAN.sprefs);
+		if (!PAN.tr.success) {
+			*gResult = userCanceledErr;
+			return 1;
+		}
+		PAN.initPrefs = true;
+	}
+
+	// update tr info
+	PAN.tr.gamma = PAN.sprefs.gamma;
+	PAN.tr.interpolator = PAN.sprefs.interpolator;
+
+	// get image from photoshop
+	buf = memAlloc(memDynamic, PHO.imageSize);
+	if (buf == NULL) goto err_exit;
+	if (cpyPsToBuf(buf)) goto err_exit;
+
+	// convert add alpha channel to image1
+	if (tool == _adjust) {
+		PAN.image2 = PAN.image1;
+
+		// add alpha channel to image1
+		PAN.image1.bitsPerPixel = PHO.imageDepth * 4;
+		PAN.image1.bytesPerLine = PHO.imageWidth * PAN.image1.bitsPerPixel/8;
+		PAN.image1.dataSize = PHO.imageHeight * PAN.image1.bytesPerLine;
+
+		// allocate buffer
+		alpha = memAlloc(memDynamic, PAN.image1.dataSize);
+		if (alpha == NULL) goto err_exit;
+		PAN.image1.data = (unsigned char **)α
+
+		DLL.CopyImageData(&PAN.image1, &PAN.image2);
+		memFree(memDynamic, *PAN.image2.data);
+	}	
+
+	// 2nd call to filter_main
+	// for compability with 2.6b1, don't use _destSupplied
+	PAN.tr.mode = _useprefs | _show_progress;
+	DLL.SetWindowOwner((HWND)platform->hwnd);
+    DLL.filter_main(&PAN.tr, &PAN.sprefs);
+
+	// don't call myfree... PT cleans up after itself
+	if (!PAN.tr.success) return 1;
+	
+	// restore image1 for return to PS
+	PAN.image1.bitsPerPixel = PHO.imageDepth * 3;
+	PAN.image1.bytesPerLine = PHO.imageWidth * PAN.image1.bitsPerPixel/8;
+	PAN.image1.dataSize = PHO.imageHeight * PAN.image1.bytesPerLine;
+	
+	// determine images for file and display
+	Image *imageFile, *imageDisplay;
+	if (tool == _adjust) {
+
+		// resize for display, removing alpha channel
+		DLL.CopyImageData(&PAN.image1, &PAN.image2);
+		if (PAN.sprefs.noAlpha)
+			DLL.FourToThreeBPP(&PAN.image2);
+		imageFile = &PAN.image2;
+        imageDisplay = &PAN.image1;
+
+	} else {
+		imageFile = &PAN.image2;
+		
+		if (PAN.tr.src->width != PAN.tr.dest->width ||
+			PAN.tr.src->height != PAN.tr.dest->height) {
+
+			// resize for display
+			DLL.CopyImageData(&PAN.image1, &PAN.image2);
+			imageDisplay = &PAN.image1;
+		} else {
+			imageDisplay = &PAN.image2;
+		}
+	}
+
+	// if change in file size, we've got extra processing to do
+	if (PAN.tr.src->width == PAN.tr.dest->width &&
+		PAN.tr.src->height == PAN.tr.dest->height) {
+		if (cpyBufToPs(*imageDisplay->data)) goto err_exit;
+	} else {
+		if (PAN.sprefs.displayPart) {
+			if (cpyBufToPs(*imageDisplay->data)) goto err_exit;
+		}
+		if (PAN.sprefs.saveFile) {
+			fullPath path;
+			fileName(path.name);
+			DLL.writePSD(imageFile, &path);
+
+			if (PAN.sprefs.launchApp) {
+				char command[300];
+				STARTUPINFO si;
+				PROCESS_INFORMATION pi;
+
+				memset(&si, 0, sizeof(STARTUPINFO));
+				si.cb = sizeof(STARTUPINFO);
+
+				// build command-line
+				sprintf(command, "%s \"%s\"", PAN.sprefs.lApp.name, path.name);
+
+				CreateProcess(
+					NULL,					// name of executable module
+					command,                // command line string
+					NULL,					// process security attributes
+					NULL,					// thread security attributes
+					FALSE,					// handle inheritance
+					0,						// creation flags
+					NULL,					// new environment block
+					NULL,					// current directory name
+					&si,					// startup information
+					&pi);					// process information
+			}
+		}	
+	}
+
+	// believe it or not, image2 still has pano12's allocated memory
+	DLL.myfree((void **)PAN.image2.data);
+
+	return 0;
+
+err_exit:
+	if (PAN.image2.data)
+		DLL.myfree((void **)PAN.image2.data);
+	
+	FreeLibrary(DLL.hPano12);
+	DLL.initDLL = false;
+    return 1;
+}