--- /dev/null
+PTVIEWER_SOURCES = viewer.c jpeg.c panolib.c
+
+X11_INC_DIR=-I/usr/X11R6/include
+X11_LIB_DIR=-L/usr/X11R6/lib
+X11_LIB_NAME=-lX11
+
+
+CC=cc
+
+
+# define BIGENDIAN=1 for Linuxppc
+# CFLAGS= -DBIGENDIAN=1
+
+OBJS = viewer.o jpeg.o panolib.o
+
+
+LIBS=$(X11_LIB_DIR) $(X11_LIB_NAME) -ljpeg -lm
+
+.c.o: $(PTVIEWER_SOURCES)
+ $(CC) -O -c $(CFLAGS) $*.c
+
+PTViewer: $(OBJS)
+ $(CC) -o PTViewer $(CFLAGS) $(OBJS) $(LIBS)
--- /dev/null
+/* Panorama_Tools - Generate, Edit and Convert Panoramic Images
+ Copyright (C) 1998,1999 - Helmut Dersch der@fh-furtwangen.de
+
+ 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, 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. */
+
+/*------------------------------------------------------------*/
+
+#ifndef FILTER_H
+#define FILTER_H
+
+
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "panorama.h"
+
+#ifndef TRUE
+ #define TRUE 1
+#endif
+
+#ifndef FALSE
+ #define FALSE 0
+#endif
+
+
+//---------------------- Types ---------------------------------------------
+
+#define UCHAR unsigned char
+#define USHORT unsigned short
+#define ULONG unsigned long
+
+enum{
+ _UCHAR,
+ _USHORT,
+ _ULONG
+ };
+
+//---------------------- Some useful math defines --------------------------
+
+#ifndef PI
+ #define PI 3.14159265358979323846
+#endif
+
+// Normalize an angle to +/-180degrees
+
+#define NORM_ANGLE( x ) while( x >180.0 ) x -= 360.0; while( x < -180.0 ) x += 360.0;
+
+// Convert degree to radian
+
+#define DEG_TO_RAD( x ) ( (x) * 2.0 * PI / 360.0 )
+
+// and reverse
+
+#define RAD_TO_DEG( x ) ( (x) * 360.0 / ( 2.0 * PI ) )
+
+// Convert double x to unsigned char/short c
+
+
+
+#define DBL_TO_UC( c, x ) if(x>255.0) c=255U; \
+ else if(x<0.0) c=0; \
+ else c=(unsigned char)floor(x+0.5);
+
+#define DBL_TO_US( c, x ) if(x>65535.0) c=65535U; \
+ else if(x<0.0) c=0; \
+ else c=(unsigned short)floor(x+0.5);
+
+
+
+
+
+
+
+// A large rectangle
+
+typedef struct{
+ long top;
+ long bottom;
+ long left;
+ long right;
+ } PTRect;
+
+
+struct PTPoint
+{
+ double x;
+ double y;
+};
+
+typedef struct PTPoint PTPoint;
+
+#define CopyPTPoint( to, from ) memcpy( &to, &from, sizeof( PTPoint ))
+#define SamePTPoint( p, s ) ((p).x == (s).x && (p).y == (s).y)
+
+struct PTLine
+{
+ PTPoint v[2];
+};
+
+typedef struct PTLine PTLine;
+
+
+struct PTTriangle
+{
+ PTPoint v[3];
+};
+
+typedef struct PTTriangle PTTriangle;
+
+
+
+
+// Maximum number of controlpoints in a pair of images, which can be read
+// via Barcodes
+
+#define NUMPTS 21
+
+// Randomization of feather in stitching tools
+
+#define BLEND_RANDOMIZE 0.1
+
+
+
+
+//----------------------- Structures -------------------------------------------
+
+struct remap_Prefs{ // Preferences Structure for remap
+ long magic; // File validity check, must be 30
+ int from; // Image format source image
+ int to; // Image format destination image
+ double hfov; // horizontal field of view /in degrees
+ double vfov; // vertical field of view (usually ignored)
+ } ;
+
+typedef struct remap_Prefs rPrefs;
+
+struct perspective_Prefs{ // Preferences structure for tool perspective
+ long magic; // File validity check, must be 40
+ int format; // rectilinear or fisheye?
+ double hfov; // Horizontal field of view (in degree)
+ double x_alpha; // New viewing direction (x coordinate or angle)
+ double y_beta; // New viewing direction (y coordinate or angle)
+ double gamma; // Angle of rotation
+ int unit_is_cart; // true, if viewing direction is specified in coordinates
+ int width; // new width
+ int height; // new height
+ } ;
+
+typedef struct perspective_Prefs pPrefs;
+
+
+struct optVars{ // Indicate to optimizer which variables to optimize
+ int hfov; // optimize hfov? 0-no 1-yes , etc
+ int yaw;
+ int pitch;
+ int roll;
+ int a;
+ int b;
+ int c;
+ int d;
+ int e;
+ };
+
+typedef struct optVars optVars;
+
+
+enum{ // Enumerates for stBuf.seam
+ _middle, // seam is placed in the middle of the overlap
+ _dest // seam is places at the edge of the image to be inserted
+ };
+
+enum{ // Enumerates for colcorrect
+ _colCorrectImage = 1,
+ _colCorrectBuffer = 2,
+ _colCorrectBoth = 3,
+ };
+
+struct stitchBuffer{ // Used describe how images should be merged
+ char srcName[256]; // Buffer should be merged to image; 0 if not.
+ char destName[256]; // Converted image (ie pano) should be saved to buffer; 0 if not
+ int feather; // Width of feather
+ int colcorrect; // Should the images be color corrected?
+ int seam; // Where to put the seam (see above)
+ };
+
+typedef struct stitchBuffer stBuf;
+
+struct panControls{ // Structure for realtime Panoeditor
+ double panAngle; // The amount by which yaw/pitch are changed per click
+ double zoomFactor; // The percentage for zoom in/out
+ };
+
+
+typedef struct panControls panControls;
+
+
+
+enum{ // Enumerates for aPrefs.mode
+ _readControlPoints,
+ _runOptimizer,
+ _insert,
+ _extract,
+ _useScript = 8, // else use options
+ };
+
+struct adjust_Prefs{ // Preferences structure for tool adjust
+ long magic; // File validity check, must be 50
+ long mode; // What to do: create Panorama etc?
+ Image im; // Image to be inserted/extracted
+ Image pano; // Panorama to be created/ used for extraction
+
+ stBuf sBuf;
+ fullPath scriptFile; // On Mac: Cast to FSSpec; else: full path to scriptFile
+ };
+
+
+typedef struct adjust_Prefs aPrefs;
+
+
+
+union panoPrefs{
+ cPrefs cP;
+ pPrefs pP;
+ rPrefs rP;
+ aPrefs aP;
+ panControls pc;
+ };
+
+typedef union panoPrefs panoPrefs;
+
+
+struct size_Prefs{ // Preferences structure for 'pref' dialog
+ long magic; // File validity check; must be 70
+ int displayPart; // Display cropped/framed image ?
+ int saveFile; // Save to tempfile? 0-no, 1-yes
+ fullPath sFile; // Full path to file (short name)
+ int launchApp; // Open sFile ?
+ fullPath lApp; // the Application to launch
+ int interpolator; // Which interpolator to use
+ double gamma; // Gamma correction value
+ int noAlpha; // If new file is created: Don't save mask (Photoshop LE)
+ int optCreatePano; // Optimizer creates panos? 0 no/ 1 yes
+ } ;
+
+typedef struct size_Prefs sPrefs;
+
+
+
+#if 0
+struct controlPoint{ // Control Points to adjust images
+ int num[2]; // Indices of Images
+ int x[2]; // x - Coordinates
+ int y[2]; // y - Coordinates
+ int type; // What to optimize: 0-r, 1-x, 2-y
+ } ;
+#endif
+struct controlPoint{ // Control Points to adjust images
+ int num[2]; // Indices of Images
+ double x[2]; // x - Coordinates
+ double y[2]; // y - Coordinates
+ int type; // What to optimize: 0-r, 1-x, 2-y
+ } ;
+
+typedef struct controlPoint controlPoint;
+
+struct CoordInfo{ // Real World 3D coordinates
+ int num; // auxilliary index
+ double x[3];
+ int set[3];
+ };
+
+typedef struct CoordInfo CoordInfo;
+
+// Some useful macros for vectors
+
+#define SCALAR_PRODUCT( v1, v2 ) ( (v1)->x[0]*(v2)->x[0] + (v1)->x[1]*(v2)->x[1] + (v1)->x[2]*(v2)->x[2] )
+#define ABS_SQUARED( v ) SCALAR_PRODUCT( v, v )
+#define ABS_VECTOR( v ) sqrt( ABS_SQUARED( v ) )
+#define CROSS_PRODUCT( v1, v2, r ) { (r)->x[0] = (v1)->x[1] * (v2)->x[2] - (v1)->x[2]*(v2)->x[1]; \
+ (r)->x[1] = (v1)->x[2] * (v2)->x[0] - (v1)->x[0]*(v2)->x[2]; \
+ (r)->x[2] = (v1)->x[0] * (v2)->x[1] - (v1)->x[1]*(v2)->x[0]; }
+#define DIFF_VECTOR( v1, v2, r ) { (r)->x[0] = (v1)->x[0] - (v2)->x[0]; \
+ (r)->x[1] = (v1)->x[1] - (v2)->x[1]; \
+ (r)->x[2] = (v1)->x[2] - (v2)->x[2]; }
+#define DIST_VECTOR( v1, v2 ) sqrt( ((v1)->x[0] - (v2)->x[0]) * ((v1)->x[0] - (v2)->x[0]) + \
+ ((v1)->x[1] - (v2)->x[1]) * ((v1)->x[1] - (v2)->x[1]) + \
+ ((v1)->x[2] - (v2)->x[2]) * ((v1)->x[2] - (v2)->x[2]) )
+
+struct transformCoord{ //
+ int nump; // Number of p-coordinates
+ CoordInfo *p; // Coordinates "as is"
+ int numr; // Number of r-coordinates
+ CoordInfo *r; // Requested values for coordinates
+ } ;
+
+typedef struct transformCoord transformCoord;
+
+struct tMatrix{
+ double alpha;
+ double beta;
+ double gamma;
+ double x_shift[3];
+ double scale;
+ };
+
+typedef struct tMatrix tMatrix;
+
+
+
+
+
+
+
+struct MakeParams{ // Actual parameters used by Xform functions for pano-creation
+ double scale[2]; // scaling factors for resize;
+ double shear[2]; // shear values
+ double rot[2]; // horizontal rotation params
+ void *perspect[2]; // Parameters for perspective control functions
+ double rad[6]; // coefficients for polynomial correction (0,...3) and source width/2 (4) and correction radius (5)
+ double mt[3][3]; // Matrix
+ double distance;
+ double horizontal;
+ double vertical;
+ };
+
+struct LMStruct{ // Parameters used by the Levenberg Marquardt-Solver
+ int m;
+ int n;
+ double *x;
+ double *fvec;
+ double ftol;
+ double xtol;
+ double gtol;
+ int maxfev;
+ double epsfcn;
+ double *diag;
+ int mode;
+ double factor;
+ int nprint;
+ int info;
+ int nfev;
+ double *fjac;
+ int ldfjac;
+ int *ipvt;
+ double *qtf;
+ double *wa1;
+ double *wa2;
+ double *wa3;
+ double *wa4;
+ };
+
+// function to minimize in Levenberg-Marquardt solver
+
+typedef int (*lmfunc)();
+
+struct triangle
+{
+ int vert[3]; // Three vertices from list
+ int nIm; // number of image for texture mapping
+};
+
+typedef struct triangle triangle;
+
+
+
+
+struct AlignInfo{ // Global data structure used by alignment optimization
+ Image *im; // Array of Pointers to Image Structs
+ optVars *opt; // Mark variables to optimize
+ int numIm; // Number of images
+ controlPoint *cpt; // List of Control points
+ triangle *t; // List of triangular faces
+ int nt; // Number of triangular faces
+ int numPts; // Number of Control Points
+ int numParam; // Number of parameters to optimize
+ Image pano; // Panoramic Image decription
+ stBuf st; // Info on how to stitch the panorama
+ void *data;
+ lmfunc fcn;
+ sPrefs sP;
+ CoordInfo *cim; // Real World coordinates
+ };
+
+typedef struct AlignInfo AlignInfo;
+
+struct OptInfo{
+ int numVars; // Number of variables to fit
+ int numData; // Number of data to fit to
+ int (*SetVarsToX)(double *x); // Translate variables to x-values
+ int (*SetXToVars)(double *x); // and reverse
+ lmfunc fcn; // Levenberg Marquardt function measuring quality
+ char message[256]; // info returned by LM-optimizer
+ };
+
+typedef struct OptInfo OptInfo;
+
+
+
+struct VRPanoOptions
+{
+ int width;
+ int height;
+ double pan;
+ double tilt;
+ double fov;
+ int codec;
+ int cquality;
+ int progressive;
+};
+
+typedef struct VRPanoOptions VRPanoOptions;
+
+
+struct MultiLayerImage
+{
+ Image im;
+ int numLayers;
+ Image *Layer;
+ PTRect *LayerRect;
+};
+
+typedef struct MultiLayerImage MultiLayerImage;
+
+
+
+
+
+
+// Transformation function type (we have only one...)
+
+typedef void (*trfn)( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+
+
+// Function descriptor to be executed by exec_function
+struct fDesc {
+ trfn func; // The function to be called
+ void *param; // The parameters to be used
+ };
+
+typedef struct fDesc fDesc;
+
+#define SetDesc(fD,f,p) fD.func = f; fD.param = p
+
+// Panorama tool type
+
+typedef void (*fnPtr)(TrformStr *TrPtr);
+
+
+// Filter function type
+
+typedef unsigned char (*flfn)( unsigned char srcPixel, int xc, int yc, void *params );
+
+
+// Interpolating functions for resampler
+
+typedef void (*intFunc)( unsigned char *dst, unsigned char **rgb,
+ register double Dx,
+ register double Dy,
+ int color, int SamplesPerPixel);
+
+
+
+
+
+// Gamma Correction
+
+struct PTGamma{
+ double *DeGamma;
+ unsigned short *Gamma;
+ int ChannelSize;
+ int ChannelStretch;
+ int GammaSize;
+ };
+
+typedef struct PTGamma PTGamma;
+
+extern PTGamma glu;
+
+
+// Some macros to find out more about images
+
+#define GetBitsPerChannel( im, x ) switch( (im)->bitsPerPixel ) \
+ { \
+ case 24: x = 8; break; \
+ case 32: x = 8; break; \
+ case 48: x = 16; break; \
+ case 64: x = 16; break; \
+ default: x = 8; break; \
+ }
+
+#define GetChannels( im, x ) switch( (im)->bitsPerPixel ) \
+ { \
+ case 24: x = 3; break; \
+ case 32: x = 4; break; \
+ case 48: x = 3; break; \
+ case 64: x = 4; break; \
+ default: x = 3; break; \
+ }
+
+
+
+//---------------------------------- Functions identical in all platforms ------------------------
+
+
+void dispatch (TrformStr *TrPtr, sPrefs *s); // Entry into platform independent code
+void DoTransForm (TrformStr *TrPtr, panoPrefs *p );
+
+void setLibToResFile ( void ); // MacOS: Get resources from shared lib
+void unsetLibToResFile( void ); // MacOS: Don't get resources from shared lib
+
+enum{ // Enumerates used by Progress and infoDlg
+ _initProgress, // display message "argument"
+ _setProgress, // display progress (argument is percentage converted to string)
+ _disposeProgress, // dispose progress indicator
+ _idleProgress // do nothing; on Mac: call waitnextevent;
+ };
+
+int Progress( int command, char* argument ); // Progress Reporting
+int infoDlg ( int command, char* argument ); // Display info: same argumenmts as progress
+void PrintError( char* fmt, ...); // Error Reporting
+
+int ccommand( char ***argvPtr); // Shell for standalone programs
+
+
+// Panorama Tool functions
+
+
+void perspective (TrformStr *TrPtr, pPrefs *p);
+void correct (TrformStr *TrPtr, cPrefs *c);
+void remap (TrformStr *TrPtr, rPrefs *r);
+void adjust (TrformStr *TrPtr, aPrefs *a);
+void pan (TrformStr *TrPtr, panControls *pc);
+
+
+
+
+// Set Struct defaults
+
+void SetPrefDefaults (panoPrefs *prPtr, int selector);
+void SetCorrectDefaults ( cPrefs *p );
+void SetAdjustDefaults ( aPrefs *p );
+void SetRemapDefaults ( rPrefs *p );
+void SetPerspectiveDefaults ( pPrefs *p );
+void SetImageDefaults ( Image *im);
+void SetOptDefaults ( optVars *opt );
+void SetPanDefaults ( panControls *pc);
+void SetSizeDefaults ( sPrefs *pref);
+void SetStitchDefaults ( stBuf *sbuf);
+void SetVRPanoOptionsDefaults( VRPanoOptions *v);
+void SettMatrixDefaults ( tMatrix *t );
+void SetCoordDefaults ( CoordInfo *c, int num);
+
+int SetAlignParams ( double *x );
+int SetLMParams ( double *x );
+void SetGlobalPtr ( AlignInfo *p );
+
+
+
+// Dialogs
+int SetPrefs ( panoPrefs *p );
+int SetPanPrefs ( panControls *p );
+int SetCorrectPrefs ( cPrefs *p );
+int SetRadialOptions ( cPrefs *p );
+int SetHorizontalOptions( cPrefs *p );
+int SetVerticalOptions ( cPrefs *p );
+int SetShearOptions ( cPrefs *p );
+int SetScaleOptions ( cPrefs *p );
+int SetLumOptions ( cPrefs *p );
+int setSizePrefs ( sPrefs *p, int can_resize );
+int SetRemapPrefs ( rPrefs *p );
+int SetPerspectivePrefs ( pPrefs *p );
+int SetAdjustPrefs ( aPrefs *p );
+int SetInterpolator ( sPrefs *p );
+int SetCreateOptions ( aPrefs *p );
+int SetCutOptions ( cPrefs *p );
+int SetFourierOptions ( cPrefs *p );
+
+
+
+// File I/O
+
+int readPrefs (char* p, int selector ); // Preferences, same selector as dispatch
+void writePrefs (char* p, int selector ); // Preferences, same selector as dispatch
+
+int LoadBufImage ( Image *image, char *fname, int mode);
+int SaveBufImage ( Image *image, char *fname );
+int writeTIFF ( Image *im, fullPath* fname); // On Mac: fname is FSSpec*
+void SaveOptions ( struct correct_Prefs * thePrefs );
+int LoadOptions ( struct correct_Prefs * thePrefs );
+void FindScript ( struct adjust_Prefs *thePrefs );
+char* LoadScript ( fullPath* scriptFile );
+int WriteScript ( char* res, fullPath* scriptFile, int launch );
+int writePSD ( Image *im, fullPath* fname); // On Mac: fname is FSSpec*
+int readPSD ( Image *im, fullPath* fname, int mode);
+int FindFile ( fullPath *fname );
+int SaveFileAs ( fullPath *fname, char *prompt, char *name );
+void ConvFileName ( fullPath *fname,char *string);
+int writePSDwithLayer ( Image *im, fullPath *fname);
+int addLayerToFile ( Image *im, fullPath* sfile, fullPath* dfile, stBuf *sB);
+void showScript ( fullPath* scriptFile );
+void MakeTempName ( fullPath *fspec, char *fname );
+void makePathForResult ( fullPath *path );
+int makePathToHost ( fullPath *path );
+void open_selection ( fullPath *path );
+int readPSDMultiLayerImage( MultiLayerImage *mim, fullPath* sfile);
+int GetFullPath (fullPath *path, char *filename); // Somewhat confusing, for compatibility easons
+int StringtoFullPath (fullPath *path, char *filename);
+int IsTextFile ( char* fname );
+int readPositions ( char* script, transformCoord *tP );
+int readImage ( Image *im, fullPath *sfile );
+int writeImage ( Image *im, fullPath *sfile );
+int writeJPEG ( Image *im, fullPath *sfile, int quality, int progressive );
+int makeTempPath ( fullPath *path );
+int writePNG ( Image *im, fullPath *sfile );
+int readPNG ( Image *im, fullPath *sfile );
+
+#define FullPathtoString( path, string ) GetFullPath( path, string)
+
+
+
+
+// Image manipulation
+
+void addAlpha ( Image *im );
+void transForm ( TrformStr *TrPtr, fDesc *fD, int color);
+void filter ( TrformStr *TrPtr, flfn func, void* params, int color);
+void CopyImageData ( Image *dest, Image *src );
+void laplace ( Image *im );
+void blurr ( Image *im );
+void MakePano ( TrformStr *TrPtr, aPrefs *aP, int nt, PTTriangle *ts, PTTriangle *td);
+void ExtractStill ( TrformStr *TrPtr , aPrefs *p );
+int HaveEqualSize ( Image *im1, Image *im2 );
+int merge ( Image *dst, Image *src, int feather, int showprogress, int seam );
+void mergeAlpha ( Image *im, unsigned char *alpha, int feather, PTRect *theRect );
+void SetEquColor ( cPrefs *p );
+void CopyPosition ( Image *to, Image *from );
+int isColorSpecific ( cPrefs *p );
+void ThreeToFourBPP ( Image *im );
+void FourToThreeBPP ( Image *im );
+int SetUpGamma ( double pgamma, int psize);
+int cutTheFrame ( Image *dest, Image *src, int width, int height, int showprogress );
+int PositionCmp ( Image *im1, Image *im2 );
+int MorphImage ( Image *src, Image *dst, PTTriangle *ts, PTTriangle *td, int nt );
+int MorphImageFile ( fullPath *sfile, fullPath *dfile, AlignInfo *g,int nIm );
+int blendImages ( fullPath *f0, fullPath *f1, fullPath *result, double s );
+int InterpolateImage ( Image *src, Image *dst, PTTriangle *ts, PTTriangle *td, int nt );
+int InterpolateTrianglesPerspective( AlignInfo *g, int nIm, double s, PTTriangle** t );
+int InterpolateImageFile( fullPath *sfile, fullPath *dfile, AlignInfo *g,int nIm );
+void OneToTwoByte ( Image *im );
+void TwoToOneByte ( Image *im );
+void SetMakeParams ( struct fDesc *stack, struct MakeParams *mp, Image *im , Image *pn, int color );
+void SetInvMakeParams ( struct fDesc *stack, struct MakeParams *mp, Image *im , Image *pn, int color );
+void GetControlPointCoordinates(int i, double *x, double *y, AlignInfo *gl );
+
+
+// Script Reading/Parsing/Writing
+
+int ParseScript ( char* script, AlignInfo *gl );
+void WriteResults ( char* script, fullPath *sfile, AlignInfo *g, double ds( int i) , int launch);
+int readAdjust ( aPrefs *p, fullPath* sfile , int insert);
+void readControlPoints (char* script, controlPoint *c );
+int getVRPanoOptions ( VRPanoOptions *v, char *line );
+void nextWord ( register char* word, char** ch );
+void nextLine ( register char* line, char** ch );
+int numLines ( char* script, char first );
+
+// Memory
+
+void DisposeAlignInfo ( AlignInfo *g );
+void** mymalloc ( long numBytes ); // Memory allocation, use Handles
+void myfree ( void** Hdl ); // free Memory, use Handles
+int SetDestImage ( TrformStr *TrPtr, int width, int height) ;
+void DisposeMultiLayerImage( MultiLayerImage *mim );
+
+
+// Math
+
+void RunLMOptimizer ( OptInfo *g);
+void RunBROptimizer ( OptInfo *g, double minStepWidth);
+void RunOverlapOptimizer ( AlignInfo *g);
+
+void SetMatrix ( double a, double b, double c , double m[3][3], int cl );
+void matrix_mult ( double m[3][3], double vector[3] );
+void matrix_inv_mult ( double m[3][3], double vector[3] );
+double smallestRoot ( double *p );
+void SetCorrectionRadius ( cPrefs *cP );
+int lmdif ();
+void fourier ( TrformStr *TrPtr, cPrefs *cP );
+unsigned short gamma_correct( double pix );
+int EqualCPrefs( cPrefs *c1, cPrefs *c2 );
+double OverlapRMS ( MultiLayerImage *mim );
+double distSquared ( int num );
+int fcnPano();
+void doCoordinateTransform( CoordInfo *c, tMatrix *t );
+void findOptimumtMatrix( transformCoord *tP, tMatrix *tM, lmfunc f);
+int SolveLinearEquation2( double a[2][2], double b[2], double x[2] );
+void SortControlPoints( AlignInfo *g , int nIm);
+void noisefilter ( Image *dest, Image *src );
+void fwiener ( TrformStr *TrPtr, Image *nf, Image *psf, double gamma, double frame );
+
+
+// Triangulation
+int PointInTriangle( double x, double y, PTTriangle *T, double c[2] );
+int SetSourceTriangles( AlignInfo *g, int nIm, PTTriangle** t );
+int SetDestTriangles( AlignInfo *g, int nIm, PTTriangle** t );
+int InterpolateTriangles( AlignInfo *g, int nIm, double s, PTTriangle** t );
+int DelaunayIteration( AlignInfo *g, int nIm );
+int PointInCircumcircle( double x, double y, PTTriangle *tC );
+int TriangulatePoints( AlignInfo *g, int nIm );
+int AddTriangle( triangle *t, AlignInfo *g );
+int RemoveTriangle( int nt, AlignInfo *g );
+void OrderVerticesInTriangle( int nt, AlignInfo *g );
+void SetTriangleCoordinates( triangle *t, PTTriangle *tC, AlignInfo *g );
+int TrianglesOverlap( PTTriangle *t0, PTTriangle *t1 );
+int LinesIntersect( PTLine *s0, PTLine *s1) ;
+double PTDistance( PTPoint *s0, PTPoint *s1 );
+int PTPointInRectangle( PTPoint *p, PTLine *r );
+int PTElementOf( double x, double a, double b );
+int PTNormal( double *a, double *b, double *c, PTLine *s );
+int PTGetLineCrossing( PTLine *s0, PTLine *s1, PTPoint *ps );
+int ReduceTriangles( AlignInfo *g, int nIm );
+double PTAreaOfTriangle( PTTriangle *t );
+int normalToTriangle( CoordInfo *n, CoordInfo *v, triangle *t );
+
+
+
+
+double GetBlendfactor( int d, int s, int feather );
+
+
+
+
+
+void execute_stack ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+
+void resize ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void shear ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void horiz ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void vert ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void radial ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+
+
+void persp_sphere ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void persp_rect ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+
+
+void rect_pano ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void pano_rect ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void pano_erect ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void erect_pano ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void sphere_cp_erect ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void sphere_tp_erect ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void erect_sphere_cp ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void rect_sphere_tp ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void sphere_tp_rect ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void sphere_cp_pano ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void rect_erect ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void erect_rect ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void erect_sphere_tp ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void mirror_erect ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void mirror_sphere_cp ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void mirror_pano ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void sphere_cp_mirror ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+void sphere_tp_pano ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+
+void pano_sphere_tp ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+
+void rotate_erect ( double x_dest, double y_dest, double* x_src, double* y_src, void* params );
+void inv_radial ( double x_dest, double y_dest, double* x_src, double* y_src, void* params );
+
+void vertical ( double x_dest, double y_dest, double* x_src, double* y_src, void* params );
+void inv_vertical ( double x_dest, double y_dest, double* x_src, double* y_src, void* params );
+void deregister ( double x_dest, double y_dest, double* x_src, double* y_src, void* params );
+void tmorph ( double x_dest,double y_dest, double* x_src, double* y_src, void* params );
+
+
+
+unsigned char radlum ( unsigned char srcPixel, int xc, int yc, void *params );
+
+
+extern TrformStr *gTrPtr;
+extern sPrefs *gsPrPtr;
+
+
+
+
+// Endian stuff: Read and write numbers from and to memory (ptr)
+
+#ifdef BIGENDIAN
+ #define LONGNUMBER( number, ptr ) *ptr++ = ((char*)(&number))[0]; \
+ *ptr++ = ((char*)(&number))[1]; \
+ *ptr++ = ((char*)(&number))[2]; \
+ *ptr++ = ((char*)(&number))[3];
+
+ #define NUMBERLONG( number, ptr ) ((char*)(&number))[0] = *ptr++; \
+ ((char*)(&number))[1] = *ptr++; \
+ ((char*)(&number))[2] = *ptr++; \
+ ((char*)(&number))[3] = *ptr++;
+
+ #define SHORTNUMBER( number, ptr ) *ptr++ = ((char*)(&number))[0]; \
+ *ptr++ = ((char*)(&number))[1]; \
+
+ #define NUMBERSHORT( number, ptr ) ((char*)(&number))[0] = *ptr++; \
+ ((char*)(&number))[1] = *ptr++; \
+
+#else
+ #define LONGNUMBER( number, ptr ) *ptr++ = ((char*)(&number))[3]; \
+ *ptr++ = ((char*)(&number))[2]; \
+ *ptr++ = ((char*)(&number))[1]; \
+ *ptr++ = ((char*)(&number))[0];
+
+ #define NUMBERLONG( number, ptr ) ((char*)(&number))[3] = *ptr++; \
+ ((char*)(&number))[2] = *ptr++; \
+ ((char*)(&number))[1] = *ptr++; \
+ ((char*)(&number))[0] = *ptr++;
+
+ #define SHORTNUMBER( number, ptr ) *ptr++ = ((char*)(&number))[1]; \
+ *ptr++ = ((char*)(&number))[0]; \
+
+ #define NUMBERSHORT( number, ptr ) ((char*)(&number))[1] = *ptr++; \
+ ((char*)(&number))[0] = *ptr++; \
+
+
+
+#endif // BIGENDIAN
+
+// Cross platform file functions
+
+#ifdef __Mac__
+
+ #include <Files.h>
+ #include "sys_mac.h"
+
+ #define file_spec short
+ #define myopen( path, perm, fspec ) ( FSpOpenDF( path, perm, &fspec ) != noErr )
+ #define mywrite( fspec, count, data ) FSWrite (fspec, &count, data)
+ #define myread( fspec, count, data ) FSRead (fspec, &count, data)
+ #define myclose( fspec ) FSClose (fspec )
+ #define mycreate( path, creator, type ) FSpCreate( path, creator, type,0)
+ #define mydelete( path ) FSpDelete( path )
+ #define myrename( path, newpath ) FSpRename (path, (newpath)->name)
+ #define write_text fsWrPerm
+ #define write_bin fsWrPerm
+ #define read_text fsRdPerm
+ #define read_bin fsRdPerm
+ #define read_write_text fsRdWrPerm
+
+#else // __Mac__, use ANSI-filefunctions
+ #define file_spec FILE*
+ #define myopen( path, perm, fspec ) ( (fspec = fopen( (path)->name, perm )) == NULL)
+ #define mywrite( fspec, count, data ) count = fwrite( data, 1, count, fspec)
+ #define myread( fspec, count, data ) count = fread( data, 1, count, fspec )
+ #define myclose( fspec ) fclose (fspec )
+ #define mycreate( path, creator, type )
+ #define mydelete( path ) remove((path)->name )
+ #define myrename( path, newpath ) rename ((path)->name, (newpath)->name)
+ #define write_text "w"
+ #define write_bin "wb"
+ #define read_text "r"
+ #define read_bin "rb"
+ #define read_write_text "rw"
+ #define p2cstr( x )
+ #define c2pstr( x )
+
+
+#endif
+
+
+
+
+#endif
+
+
+
+
+
+
--- /dev/null
+/* Panorama_Tools - Generate, Edit and Convert Panoramic Images
+ Copyright (C) 1998,1999 - Helmut Dersch der@fh-furtwangen.de
+
+ 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, 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 <stdio.h>
+#include "jpeglib.h"
+#include "filter.h"
+
+
+
+
+int writeJPEG( Image *im, fullPath *sfile, int quality, int progressive )
+{
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ FILE * outfile;
+ char filename[512];
+ int scanlines_written;
+ unsigned char *data,*buf;
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+// if( GetFullPath (sfile, filename))
+// return -1;
+ strcpy(filename, sfile->name);
+ if ((outfile = fopen(filename, "wb")) == NULL)
+ {
+ PrintError("can't open %s", filename);
+ return -1;
+ }
+// TwoToOneByte( im );
+
+ jpeg_stdio_dest(&cinfo, outfile);
+
+
+
+ cinfo.image_width = im->width; /* image width and height, in pixels */
+ cinfo.image_height = im->height;
+ cinfo.input_components = 3; /* # of color components per pixel */
+ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+
+ jpeg_set_defaults(&cinfo);
+
+ jpeg_set_quality (&cinfo, quality, TRUE);
+
+ if( progressive )
+ jpeg_simple_progression (&cinfo);
+
+
+ jpeg_start_compress(&cinfo, TRUE);
+
+ scanlines_written = 0;
+ data = *(im->data);
+ buf = (unsigned char*)malloc( im->bytesPerLine );
+ if(buf == NULL)
+ {
+
+ PrintError("Not enough memory");
+ fclose( outfile );
+ return -1;
+ }
+
+
+ while ( scanlines_written < im->height )
+ {
+ memcpy(buf, data, im->bytesPerLine );
+ if( im->bitsPerPixel == 32 ) // Convert 4->3 samples
+ {
+ int x;
+ unsigned char *c1=buf, *c2=buf;
+ for(x=0; x < im->width; x++)
+ {
+ c2++;
+ *c1++ = *c2++;
+ *c1++ = *c2++;
+ *c1++ = *c2++;
+ }
+
+ }
+
+ if( jpeg_write_scanlines(&cinfo, (JSAMPARRAY) &buf, 1) )
+ {
+ scanlines_written++;
+ data += im->bytesPerLine;
+ }
+ }
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+ fclose( outfile );
+ free( buf );
+ return 0;
+
+
+}
+
+
+
+int readJPEG ( Image *im, fullPath *sfile )
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ FILE * infile;
+ char filename[256];
+ int scan_lines_to_be_read, i, scanheight, scan_lines_read;
+ unsigned char*data;
+ JSAMPARRAY sarray;
+
+ //PrintError("%s", sfile->name);
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+
+
+// if( GetFullPath (sfile, filename))
+// return -1;
+
+ strcpy(filename, sfile->name);
+ if ((infile = fopen(filename, "rb")) == NULL)
+ {
+ PrintError("can't open %s", filename);
+ return -1;
+ }
+
+ jpeg_stdio_src(&cinfo, infile);
+
+ jpeg_read_header(&cinfo, TRUE);
+
+ jpeg_start_decompress(&cinfo);
+
+ SetImageDefaults( im );
+ im->width = cinfo.output_width;
+ im->height = cinfo.output_height;
+ if( cinfo.output_components != 3 )
+ {
+ PrintError("Image must be rgb");
+ fclose( infile );
+ return -1;
+ }
+
+
+ im->bitsPerPixel = 24;
+ im->bytesPerLine = im->width*3 ;
+ //im->bytesPerLine *= 12;
+ im->dataSize = im->width * 4 * im->height;
+ im->data = (unsigned char**)mymalloc( im->dataSize );
+ if( im->data == NULL )
+ {
+ PrintError("Not enough memory");
+ fclose( infile );
+ return -1;
+ }
+
+ scanheight = cinfo.rec_outbuf_height;
+ sarray = (JSAMPARRAY) malloc( scanheight * sizeof( JSAMPROW ) );
+
+ scan_lines_to_be_read = im->height;
+ data = *(im->data);
+
+ while (scan_lines_to_be_read)
+ {
+ for(i=0; i<scanheight; i++)
+ {
+ sarray[i] = (JSAMPROW) (data + i*im->bytesPerLine);
+ }
+
+ scan_lines_read = jpeg_read_scanlines(&cinfo, sarray, scanheight);
+
+ scan_lines_to_be_read -= scan_lines_read;
+ data += scan_lines_read * im->bytesPerLine;
+ }
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+
+ ThreeToFourBPP( im );
+ free( sarray );
+
+ fclose( infile );
+
+ return 0;
+
+
+}
+
--- /dev/null
+/* Panorama_Tools - Generate, Edit and Convert Panoramic Images
+ Copyright (C) 1998,1999 - Helmut Dersch der@fh-furtwangen.de
+
+ 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, 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 "filter.h"
+
+
+// Lookup Tables for Trig-functions and interpolator
+
+#define NATAN 2048
+#define NSQRT 2048
+
+int *atan_LU;
+int *sqrt_LU;
+int *mweights[256];
+
+
+void matrix_matrix_mult ( double m1[3][3],double m2[3][3],double result[3][3]);
+void PV_transForm( TrformStr *TrPtr, int dist_r, int dist_e, int mt[3][3]);
+int PV_atan2(int y, int x);
+int PV_sqrt( int x1, int x2 );
+
+
+// Bilinear interpolator
+
+static void bil( unsigned char *dst, unsigned char **rgb,
+ int dx,int dy)
+{
+ int yr, yg, yb,weight;
+ int rd, gd, bd ;
+ register unsigned char *r;
+ int *w1, *w2;
+
+
+ w1 = mweights[dx]; w2 = mweights[255 - dx];
+
+ r = rgb[0] + 1;
+
+ rd = w2[*r++]; gd = w2[*r++]; bd = w2[*r++];
+ //weight = 255 - dx; rd = weight * *r++; gd = weight * *r++; bd = weight * *r++;
+
+ r++;
+ rd += w1[*r++]; gd += w1[*r++]; bd += w1[*r];
+ //rd += dx * *r++; gd += dx * *r++; bd += dx * *r;
+
+
+ r = rgb[1] + 1;
+
+ yr = w2[*r++]; yg = w2[*r++]; yb = w2[*r++];
+ //rd = weight * *r++; gd = weight * *r++; bd = weight * *r++;
+
+ r++;
+ yr += w1[*r++]; yg += w1[*r++]; yb += w1[*r];
+ //rd += dx * *r++; gd += dx * *r++; bd += dx * *r;
+
+ weight = 255 - dy;
+ rd = rd * weight + yr * dy;
+ gd = gd * weight + yg * dy;
+ bd = bd * weight + yb * dy;
+
+ *dst++ = rd >> 16;
+ *dst++ = gd >> 16;
+ *dst = bd >> 16;
+}
+
+
+
+// Extract image from pano in TrPtr->src
+// using parameters in prefs (ignore image parameters
+// in TrPtr)
+
+void PV_ExtractStill( TrformStr *TrPtr )
+{
+ double a,b; // field of view in rad
+ double p[2];
+ double mt[3][3];
+ int mi[3][3],i,k;
+
+ TrPtr->success = 1;
+
+ a = DEG_TO_RAD( TrPtr->dest->hfov ); // field of view in rad
+ b = DEG_TO_RAD( TrPtr->src->hfov );
+
+ SetMatrix( DEG_TO_RAD( TrPtr->dest->pitch ),
+ DEG_TO_RAD( TrPtr->dest->yaw ),
+ 0.0 ,
+ mt,
+ 1 );
+
+
+ p[0] = (double)TrPtr->dest->width/ (2.0 * tan( a / 2.0 ) );
+ p[1] = (double)TrPtr->src->width/ b;
+
+ for(i=0; i<3; i++){
+ for(k=0; k<3; k++){
+ mi[i][k] = 256 * mt[i][k];
+ }
+ }
+
+
+ PV_transForm( TrPtr, (int)(p[0]+.5), (int)(p[1]+.5), mi);
+ return;
+}
+
+
+
+
+
+// Main transformation function. Destination image is calculated using transformation
+// Function "func". Either all colors (color = 0) or one of rgb (color =1,2,3) are
+// determined. If successful, TrPtr->success = 1. Memory for destination image
+// must have been allocated and locked!
+
+void PV_transForm( TrformStr *TrPtr, int dist_r, int dist_e, int mt[3][3])
+{
+ register int x, y; // Loop through destination image
+ unsigned char *dest,*src,*sry, *dst;// Source and destination image data
+ long cy; // rownum in destimage
+ int dx,dy;
+
+ int xc; // Cartesian Coordinates of point ("target") in Destination image
+ int xs, ys;
+
+ unsigned char *rgb[2] ,
+ cdata[16]; // Image data handed to sampler
+
+
+ int mix = TrPtr->src->width - 1; // maximum x-index src
+ int miy = TrPtr->src->height - 1;// maximum y-index src
+
+ // Variables used to convert screen coordinates to cartesian coordinates
+
+
+ int w2 = TrPtr->dest->width / 2 ;
+ int h2 = TrPtr->dest->height / 2 ;
+ int sw2 = TrPtr->src->width / 2 ;
+ int sh2 = TrPtr->src->height / 2 ;
+
+ int BytesPerLine = TrPtr->src->bytesPerLine;
+ int v[3];
+ int x_min, x_max, y_min, y_max;
+
+ int dr1, dr2, dr3;
+
+ dr1 = mt[2][0] * dist_r;
+ dr2 = mt[2][1] * dist_r;
+ dr3 = mt[2][2] * dist_r;
+
+
+
+
+
+ dest = *TrPtr->dest->data;
+ src = *TrPtr->src->data; // is locked
+
+ x_min = -w2; x_max = TrPtr->dest->width - w2;
+ y_min = -h2; y_max = TrPtr->dest->height - h2;
+
+ cy = 0;
+
+ if( TrPtr->interpolator == _bilinear )
+ {
+ for(y = y_min; y < y_max; y++, cy+=TrPtr->dest->bytesPerLine)
+ {
+ dst = dest + cy + 1;
+ for(x = x_min; x < x_max; x++, dst+=4)
+ {
+ v[0] = mt[0][0] * x + mt[1][0] * y + dr1;
+ v[1] = mt[0][1] * x + mt[1][1] * y + dr2;
+ v[2] = mt[0][2] * x + mt[1][2] * y + dr3;
+
+ v[0] = v[0] >> 8; v[2] = v[2] >> 8;
+
+ xs = dist_e * PV_atan2( v[0], v[2] ) / NATAN ;
+
+ ys = dist_e * PV_atan2( v[1], PV_sqrt( abs(v[2]), abs(v[0]) ) ) / NATAN ;
+
+ dx = xs & 255; dy = ys & 255; // fraction
+
+
+ xs = (xs >> 8) + sw2;
+ ys = (ys >> 8) + sh2;
+
+
+ if( ys >= 0 && ys < miy && xs >= 0 && xs < mix ) // all interpolation pixels inside image
+ // (most pixels)
+ {
+ sry = src + ys * BytesPerLine + xs * 4;
+ rgb[0] = sry;
+ rgb[1] = sry + BytesPerLine;
+ }
+ else // edge pixels
+ {
+ xc = xs;
+
+ rgb[0] = cdata;
+ if( ys < 0 )
+ sry = src;
+ else if( ys > miy )
+ sry = src + miy * BytesPerLine;
+ else
+ sry = src + ys * BytesPerLine;
+
+ if( xs < 0 ) xs = mix;
+ if( xs > mix) xs = 0;
+ *(long*)rgb[0] = *(long*)(sry + xs*4);
+
+ xs = xc+1;
+ if( xs < 0 ) xs = mix;
+ if( xs > mix) xs = 0;
+ *(long*)(rgb[0]+4) = *(long*)(sry + xs*4);
+
+
+
+ rgb[1] = cdata+8;
+ ys+=1;
+ if( ys < 0 )
+ sry = src;
+ else if( ys > miy )
+ sry = src + miy * BytesPerLine;
+ else
+ sry = src + ys * BytesPerLine;
+ xs = xc;
+ if( xs < 0 ) xs = mix;
+ if( xs > mix) xs = 0;
+ *(long*)rgb[1] = *(long*)(sry + xs*4);
+ xs = xc+1;
+ if( xs < 0 ) xs = mix;
+ if( xs > mix) xs = 0;
+ *(long*)(rgb[1]+4) = *(long*)(sry + xs*4);
+
+
+ }
+ bil( dst, rgb, dx, dy );
+ }
+ }
+ }
+ else if( TrPtr->interpolator == _nn )
+ {
+ for(y = y_min; y < y_max; y++, cy+=TrPtr->dest->bytesPerLine)
+ {
+ dst = dest + cy;
+ for(x = x_min; x < x_max; x++, dst+=4)
+ {
+ v[0] = mt[0][0] * x + mt[1][0] * y + dr1;
+ v[1] = mt[0][1] * x + mt[1][1] * y + dr2;
+ v[2] = mt[0][2] * x + mt[1][2] * y + dr3;
+
+ v[0] = v[0] >> 8; v[2] = v[2] >> 8;
+
+ xs = dist_e * PV_atan2( v[0], v[2] ) / NATAN ;
+
+ ys = dist_e * PV_atan2( v[1], PV_sqrt( abs(v[2]), abs(v[0]) ) ) / NATAN ;
+
+ dx = xs & 255; dy = ys & 255; // fraction
+
+
+ xs = (xs >> 8) + sw2;
+ ys = (ys >> 8) + sh2;
+
+ if( xs < 0 ) xs = 0;
+ if( xs > mix ) xs = mix;
+ if( ys < 0) ys = 0;
+ if( ys > miy ) ys = miy;
+
+ *(long*)dst = *(long*)(src + ys * BytesPerLine + xs * 4);
+ }
+ }
+ }
+
+ TrPtr->success = 1;
+ return;
+}
+
+
+void matrix_inv_mult( double m[3][3], double vector[3] )
+{
+ register int i;
+ register double v0 = vector[0];
+ register double v1 = vector[1];
+ register double v2 = vector[2];
+
+ for(i=0; i<3; i++)
+ {
+ vector[i] = m[0][i] * v0 + m[1][i] * v1 + m[2][i] * v2;
+ }
+}
+
+// Set matrix elements based on Euler angles a, b, c
+
+void SetMatrix( double a, double b, double c , double m[3][3], int cl )
+{
+ double mx[3][3], my[3][3], mz[3][3], dummy[3][3];
+
+
+ // Calculate Matrices;
+
+ mx[0][0] = 1.0 ; mx[0][1] = 0.0 ; mx[0][2] = 0.0;
+ mx[1][0] = 0.0 ; mx[1][1] = cos(a) ; mx[1][2] = sin(a);
+ mx[2][0] = 0.0 ; mx[2][1] =-mx[1][2] ; mx[2][2] = mx[1][1];
+
+ my[0][0] = cos(b); my[0][1] = 0.0 ; my[0][2] =-sin(b);
+ my[1][0] = 0.0 ; my[1][1] = 1.0 ; my[1][2] = 0.0;
+ my[2][0] = -my[0][2]; my[2][1] = 0.0 ; my[2][2] = my[0][0];
+
+ mz[0][0] = cos(c) ; mz[0][1] = sin(c) ; mz[0][2] = 0.0;
+ mz[1][0] =-mz[0][1] ; mz[1][1] = mz[0][0] ; mz[1][2] = 0.0;
+ mz[2][0] = 0.0 ; mz[2][1] = 0.0 ; mz[2][2] = 1.0;
+
+ if( cl )
+ matrix_matrix_mult( mz, mx, dummy);
+ else
+ matrix_matrix_mult( mx, mz, dummy);
+ matrix_matrix_mult( dummy, my, m);
+}
+
+void matrix_matrix_mult( double m1[3][3],double m2[3][3],double result[3][3])
+{
+ register int i,k;
+
+ for(i=0;i<3;i++)
+ {
+ for(k=0; k<3; k++)
+ {
+ result[i][k] = m1[i][0] * m2[0][k] + m1[i][1] * m2[1][k] + m1[i][2] * m2[2][k];
+ }
+ }
+}
+
+
+
+int PV_atan2(int y, int x)
+{
+ // return atan2(y,x) * 256*NATAN;
+ if( x > 0 )
+ {
+ if( y > 0 )
+ {
+ return atan_LU[(int)( NATAN * y / ( x + y ))];
+ }
+ else
+ {
+ return -atan_LU[ (int)(NATAN * (-y) / ( x - y ))];
+ }
+ }
+
+ if( x == 0 )
+ {
+ if( y > 0 )
+ return (int)(256*NATAN*PI / 2.0);
+ else
+ return -(int)(256*NATAN*PI / 2.0);
+ }
+
+ if( y < 0 )
+ {
+ return atan_LU[(int)( NATAN * y / ( x + y ))] - (int)(PI*256*NATAN);
+ }
+ else
+ {
+ return -atan_LU[ (int)(NATAN * (-y) / ( x - y ))] + (int)(PI*256*NATAN);
+ }
+
+}
+
+
+
+int SetUpAtan()
+{
+ int i;
+ double dz = 1.0 / (double)NATAN;
+ double z = 0.0;
+
+ atan_LU = (int*) malloc( (NATAN+1) * sizeof( int ));
+
+ if( atan_LU == NULL )
+ return -1;
+
+ for( i=0; i< NATAN; i++, z+=dz )
+ atan_LU[i] = atan( z / (1.0 - z ) ) * NATAN * 256;
+
+ atan_LU[NATAN] = PI/4.0 * NATAN * 256;
+
+ // Print a test
+#if 0
+ for(i = -10; i< 10; i++)
+ {
+ int k;
+ for(k=-10; k<10; k++)
+ {
+ printf("i = %d k = %d atan2(i,k) = %g LUatan(i,k) = %g diff = %g\n", i,k,atan2(i,k),
+ (double)PV_atan2(i,k) / (256*NATAN) , atan2(i,k) - (double)PV_atan2(i,k) / (256*NATAN));
+ }
+ }
+ exit(0);
+#endif
+ return 0;
+}
+
+int SetUpSqrt()
+{
+ int i;
+ double dz = 1.0 / (double)NSQRT;
+ double z = 0.0;
+
+ sqrt_LU = (int*) malloc( (NSQRT+1) * sizeof( int ));
+
+ if( sqrt_LU == NULL )
+ return -1;
+
+ for( i=0; i< NSQRT; i++, z+=dz )
+ sqrt_LU[i] = sqrt( 1.0 + z*z ) * 256 * NSQRT;
+
+ sqrt_LU[NSQRT] = sqrt(2.0) * 256 * NSQRT;
+
+ return 0;
+}
+
+int SetUpMweights()
+{
+ int i,k;
+
+ for(i=0; i<256; i++)
+ {
+ mweights[i] = (int*)malloc( 256 * sizeof(int) );
+ if( mweights[i] == NULL ) return -1;
+ }
+ for(i=0; i<256; i++)
+ {
+ for(k=0; k<256; k++)
+ {
+ mweights[i][k] = i*k;
+ }
+ }
+
+ return 0;
+}
+
+
+int PV_sqrt( int x1, int x2 )
+{
+ if( x1 > x2 )
+ {
+ return x1 * sqrt_LU[ NSQRT * x2 / x1 ] / NSQRT;
+ }
+ else
+ {
+ if( x2 == 0 ) return 0;
+ return x2 * sqrt_LU[ NSQRT * x1 / x2 ] / NSQRT;
+ }
+}
+
+
+#define ID_0 0xff
+#define ID_1 0xd8
+#define ID_2 0xff
+#define ID_3 0xe0
+#define ID_4 0x00
+#define ID_5 0x10
+#define ID_6 0x4a
+#define ID_7 0x46
+#define ID_8 0x49
+#define ID_9 0x46
+#define ID_10 0x00
+
+#define ID_LENGTH 11
+
+// Find last jpeg inside image; create and copy to file jpeg
+int extractJPEG( fullPath *image, fullPath *jpeg )
+{
+ file_spec fnum;
+ long count;
+ unsigned char* im;
+ int i, idx = -1;
+ unsigned char ch;
+
+ if( myopen( image, read_bin, fnum ) )
+ return -1;
+
+
+ count = 1; i=0; // Get file length
+
+ while( count == 1 )
+ {
+ myread( fnum, count, &ch );
+ if(count==1) i++;
+ }
+ myclose(fnum);
+
+ count = i;
+
+ im = (UCHAR*)malloc( count );
+ if( im == NULL )
+ {
+ PrintError("Not enough memory");
+ return -1;
+ }
+
+ if( myopen( image, read_bin, fnum ) )
+ return -1;
+
+ myread(fnum,count,im);
+ myclose(fnum);
+
+ if( i != count )
+ return -1;
+
+ count -= ID_LENGTH;
+
+ for(i=0; i<count; i++)
+ {
+ if( im[i] == ID_0 && im[i+1] == ID_1 && im[i+2] == ID_2 && im[i+3] == ID_3
+ && im[i+4] == ID_4 && im[i+5] == ID_5 && im[i+6] == ID_6 && im[i+7] == ID_7
+ && im[i+8] == ID_8 && im[i+9] == ID_9 && im[i+10] == ID_10)
+ idx = i;
+ }
+
+ if( idx == -1 ) // No jpeg found
+ {
+ free(im);
+ return -1;
+ }
+
+ count = count + ID_LENGTH - idx;
+
+ mycreate( jpeg, 'GKON','JPEG');
+ if( myopen( jpeg, write_bin, fnum ) )
+ return -1;
+ mywrite( fnum, count, im+idx );
+ free( im );
+ myclose( fnum );
+ return 0;
+}
+
+
--- /dev/null
+/* Panorama_Tools - Generate, Edit and Convert Panoramic Images
+ Copyright (C) 1998,1999 - Helmut Dersch der@fh-furtwangen.de
+
+ 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, 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. */
+
+/*------------------------------------------------------------*/
+
+
+
+#ifndef PANORAMA_H
+#define PANORAMA_H
+
+
+#include "version.h"
+
+
+// Determine which machine we are using. Macs are set to BIGENDIAN, all others not
+
+// If you need BIGENDIAN, and don't use MacOS, define it here:
+// #define BIGENDIAN 1
+
+
+// Create a definition if we're on a Windows machine:
+#ifndef __Win__
+ #if (defined(MSDOS) || defined(WIN32) || defined(__INTEL__))
+ #define __Win__ 1
+ #endif
+#endif
+
+
+// Create a definition if we're on a Macintosh:
+#ifndef __Mac__
+ #if (defined(macintosh) || defined(__MC68K__) || defined(__POWERPC__) || defined(__powerc))
+ #define __Mac__ 1
+ #define BIGENDIAN 1
+ #endif
+#endif
+
+
+
+// Use FSSpec on Macs as Path-specifyers, else strings
+#define PATH_SEP '/'
+
+#ifdef __Mac__
+
+ #include <Files.h>
+ #define fullPath FSSpec
+ #undef PATH_SEP
+ #define PATH_SEP ':'
+
+#else // __Mac__, use ANSI-filefunctions
+
+ #ifdef __Win__
+ // #include <windows.h>; including this causes problems with libjpeg
+ #define MAX_PATH_LENGTH 260
+ // was MAX_PATH
+ #undef PATH_SEP
+ #define PATH_SEP '\\'
+ #else
+ #define MAX_PATH_LENGTH 512
+ #endif
+
+ typedef struct{char name[MAX_PATH_LENGTH];} fullPath;
+
+#endif
+
+
+
+
+
+// Enumerates for TrFormStr.tool
+
+enum{ // Panorama Tools
+ _perspective,
+ _correct,
+ _remap,
+ _adjust,
+ _interpolate,
+ _sizep, // dummy for size-preferences
+ _version, // dummy for version
+ _panright, // Pan Controls
+ _panleft,
+ _panup,
+ _pandown,
+ _zoomin,
+ _zoomout,
+ _apply,
+ _getPano,
+ _increment
+ };
+
+// Enumerates for TrFormStr.mode
+
+enum{ // Modes
+ _interactive, // display dialogs and do Xform
+ _useprefs, // load saved prefs and do Xform/ no dialogs
+ _setprefs, // display dialogs and set preferences, no Xform
+ _usedata, // use supplied data in TrFormStr.data, do Xform
+ _honor_valid = 8, // Use only pixels with alpha channel set
+ _show_progress = 16, // Interpolator displays progress bar
+ _hostCanResize = 32, // o-no; 1-yes (Photoshop: no; GraphicConverter: yes)
+ _destSupplied = 64, // Destination image allocated by plug-in host
+ _wrapX =128 // Wrap image horizontally (if HFOV==360 degrees)
+ };
+
+
+// Enumerates for Image.dataformat
+
+enum{
+ _RGB,
+ _Lab,
+ _Grey
+ };
+
+// Enumerates for TrFormStr.interpolator
+
+enum{ // Interpolators
+ _poly3 = 0, // Third order polynomial fitting 16 nearest pixels
+ _spline16 = 1, // Cubic Spline fitting 16 nearest pixels
+ _spline36 = 2, // Cubic Spline fitting 36 nearest pixels
+ _sinc256 = 3, // Sinc windowed to 8 pixels
+ _spline64, // Cubic Spline fitting 64 nearest pixels
+ _bilinear, // Bilinear interpolation
+ _nn , // Nearest neighbor
+ _sinc1024
+ };
+
+// Corrections
+
+struct correct_Prefs{ // Preferences structure for tool correct
+ unsigned long magic; // File validity check, must be 20
+ int radial; // Radial correction requested?
+ double radial_params[3][5]; // 3 colors x (4 coeffic. for 3rd order polys + correction radius)
+ int vertical; // Vertical shift requested ?
+ double vertical_params[3]; // 3 colors x vertical shift value
+ int horizontal; // horizontal tilt ( in screenpoints)
+ double horizontal_params[3]; // 3 colours x horizontal shift value
+ int shear; // shear correction requested?
+ double shear_x; // horizontal shear values
+ double shear_y; // vertical shear values
+ int resize; // scaling requested ?
+ long width; // new width
+ long height; // new height
+ int luminance; // correct luminance variation?
+ double lum_params[3]; // parameters for luminance corrections
+ int correction_mode; // 0 - radial correction;1 - vertical correction;2 - deregistration
+ int cutFrame; // remove frame? 0 - no; 1 - yes
+ int fwidth;
+ int fheight;
+ int frame;
+ int fourier; // Fourier filtering requested?
+ int fourier_mode; // _faddBlurr vs _fremoveBlurr
+ fullPath psf; // Point Spread Function, full path/fsspec to psd-file
+ int fourier_nf; // Noise filtering: _nf_internal vs _nf_custom
+ fullPath nff; // noise filtered file: full path/fsspec to psd-file
+ double filterfactor; // Hunt factor
+ double fourier_frame; // To correct edge errors
+ } ;
+
+typedef struct correct_Prefs cPrefs;
+
+enum{
+ correction_mode_radial = 0,
+ correction_mode_vertical = 1,
+ correction_mode_deregister = 2,
+ correction_mode_morph = 4
+ };
+
+
+enum{
+ _faddBlurr,
+ _fremoveBlurr,
+ _nf_internal,
+ _nf_custom,
+ _fresize
+ };
+
+
+enum{ // Enumerates for Image.format
+ _rectilinear = 0,
+ _panorama = 1,
+ _fisheye_circ = 2,
+ _fisheye_ff = 3,
+ _equirectangular= 4,
+ _spherical_cp = 5,
+ _spherical_tp = 6,
+ _mirror = 7,
+ _orthographic = 8
+ };
+
+
+
+struct Image
+ {
+ // Pixel data
+ long width;
+ long height;
+ long bytesPerLine;
+ long bitsPerPixel; // Must be 24 or 32
+ long dataSize;
+ unsigned char** data;
+ long dataformat; // rgb, Lab etc
+ long format; // Projection: rectilinear etc
+ double hfov;
+ double yaw;
+ double pitch;
+ double roll;
+ cPrefs cP; // How to correct the image
+ char name[256];
+ };
+
+typedef struct Image Image;
+
+
+struct TrformStr // This structure holds all image information
+ {
+ Image *src; // Source image, must be supplied on entry
+ Image *dest; // Destination image data, valid if success = 1
+ long success; // 0 - no, 1 - yes
+
+
+ long tool; // Panorama Tool requested
+ long mode; // how to run transformation
+ void *data; // data for tool requested.
+ // Required only if mode = _usedata; then it
+ // must point to valid preferences structure
+ // for requested tool (see filter.h).
+
+ long interpolator; // Select interpolator
+ double gamma; // Gamma value for internal gamma correction
+ };
+
+typedef struct TrformStr TrformStr;
+
+
+// Useful for looping through images
+
+#define LOOP_IMAGE( image, action ) { int x,y,bpp=(image)->bitsPerPixel/8; \
+ unsigned char *idata; \
+ for(y=0; y<(image)->height; y++){ \
+ idata = *((image)->data) + y * (image)->bytesPerLine; \
+ for(x=0; x<(image)->width;x++, idata+=bpp){ \
+ action;} } }
+
+
+
+
+
+
+void filter_main();
+
+
+#endif // PANORAMA_H
--- /dev/null
+/* Panorama_Tools - Generate, Edit and Convert Panoramic Images
+ Copyright (C) 1998,1999 - Helmut Dersch der@fh-furtwangen.de
+ 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, 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. */
+/*------------------------------------------------------------*/
+
+#ifndef VERSION
+#define VERSION "0.4 "
+#endif
+
+#ifndef LONGVERSION
+#define LONGVERSION "0.4 , Copyright © 1998-2000, H. Dersch, der@fh-furtwangen.de"
+#endif
--- /dev/null
+/* Panorama_Tools - Generate, Edit and Convert Panoramic Images
+ Copyright (C) 1998,1999,2000 - Helmut Dersch der@fh-furtwangen.de
+
+ 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, 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 <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "filter.h"
+
+void PV_ExtractStill( TrformStr *TrPtr );
+void PV_SetInvMakeParams( struct fDesc *stack, struct MakeParams *mp, Image *im , Image *pn );
+int SetUpAtan();
+int SetUpSqrt();
+int SetUpMweights();
+
+void DrawWindow();
+void DrawView(int InterPolator);
+
+int panning = FALSE;
+int zooming_in = FALSE;
+int zooming_out = FALSE;
+
+#define VIEW_WIDTH 400
+#define VIEW_HEIGHT 300
+
+
+char text[] = "PTViewer";
+
+Image view, pano;
+Display *disp;
+Window win;
+int screen;
+XImage *ximage = NULL;
+GC gc;
+Visual *visual;
+unsigned int depth;
+int oldposx, oldposy;
+
+
+int main( int argc, char** argv )
+{
+ KeySym key;
+ XSizeHints hint;
+ unsigned long fg, bg;
+ int done;
+ union
+ {
+ XEvent event;
+ XAnyEvent any;
+ XButtonEvent button;
+ XKeyEvent key;
+ XConfigureEvent configure;
+ XExposeEvent expose;
+ XMotionEvent motion;
+ XResizeRequestEvent resize;
+ XClientMessageEvent message;
+ } event;
+ int newposx, newposy;
+ static Atom proto_atom= None, delete_atom= None;
+
+
+ // Set up display
+
+
+
+ disp = XOpenDisplay("");
+ screen = DefaultScreen(disp);
+ depth = DefaultDepth(disp, screen);
+
+ if( depth != 24 )
+ {
+ PrintError("Depth = %d, must be 24 pixels", (int)depth);
+ exit(0);
+ }
+ bg = WhitePixel(disp,screen);
+ fg = BlackPixel(disp,screen);
+
+ // Load panoramic image
+ if( argc < 2 )
+ {
+ PrintError("No image file supplied");
+ exit(0);
+ }
+
+ if( strcmp( argv[1], "-h" ) == 0 )
+ {
+ PrintError( "%s\n %s\nUsage: PTViewer Imagefile", "PTViewer", LONGVERSION );
+ exit(0);
+ }
+ if( readJPEG( &pano, (fullPath*)argv[1] ) != 0 )
+ {
+ PrintError("Could not read panoramic image");
+ exit(0);
+ }
+ pano.hfov = 360.0;
+ pano.format = _equirectangular;
+
+ // Initialize Look-up tables
+
+ if( SetUpAtan() || SetUpSqrt() || SetUpMweights() )
+ {
+ PrintError("Could not set up LU Tables");
+ exit(0);
+ }
+
+ // Set up viewer window
+
+ SetImageDefaults( &view );
+
+ view.hfov = 70.0;
+ view.width = VIEW_WIDTH;
+ view.height = VIEW_HEIGHT;
+ view.bitsPerPixel = 32;
+ view.bytesPerLine = view.width * view.bitsPerPixel / 8;
+ view.dataSize = view.bytesPerLine * view.height;
+ view.format = 1;
+ view.data = (unsigned char**)mymalloc( view.dataSize );
+ if(view.data == NULL)
+ {
+ PrintError("Not enough memory");
+ exit(0);
+ }
+
+
+ hint.x = 200;
+ hint.y = 200;
+ hint.width = view.width;
+ hint.height = view.height;
+ hint.flags=PPosition | PSize;
+
+ win = XCreateSimpleWindow(disp,
+ DefaultRootWindow(disp),
+ hint.x,
+ hint.y,
+ hint.width,
+ hint.height,
+ 5,
+ fg,
+ bg);
+
+ XSetStandardProperties(disp,
+ win,
+ text,
+ text,
+ None,
+ argv,
+ argc,
+ &hint);
+ gc = XCreateGC(disp,win,0,0);
+ XSetBackground(disp,gc,bg);
+ XSetForeground(disp,gc,fg);
+
+ XSelectInput(disp,
+ win,
+ ButtonPressMask | ButtonReleaseMask | Button1MotionMask | KeyPressMask | KeyReleaseMask |
+ StructureNotifyMask | EnterWindowMask | LeaveWindowMask| ExposureMask);
+ XMapRaised(disp,win);
+
+ proto_atom = XInternAtom(disp, "WM_PROTOCOLS", False);
+ delete_atom = XInternAtom(disp, "WM_DELETE_WINDOW", False);
+ if ((proto_atom != None) && (delete_atom != None))
+ XChangeProperty(disp, win, proto_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&delete_atom, 1);
+
+
+
+ visual = DefaultVisual(disp, screen);
+
+ ximage = XCreateImage(disp, visual, depth, ZPixmap, 0,
+ NULL, view.width, view.height,
+ 8, 0);
+ memset( *(view.data), 0, view.dataSize);
+ ximage->data = (char *)*(view.data);
+ ximage->byte_order= MSBFirst;
+
+
+
+ done = 0;
+ while( done==0)
+ {
+ int isChanged = 0;
+
+ // No XNextEvent
+
+ if( XCheckTypedEvent(disp, Expose, (XEvent*)&event) ) DrawWindow();
+
+ if( XCheckTypedEvent(disp, KeyPress, (XEvent*)&event) )
+ {
+ char buf[128];
+ KeySym ks;
+ XComposeStatus status;
+ int nkey = XLookupString(&event.key,buf,128,&ks,&status);
+
+ if( nkey == 0 )
+ {
+ switch(ks)
+ {
+ case XK_Shift_L:
+ case XK_Shift_R: zooming_in = TRUE;
+ break;
+
+ case XK_Control_L:
+ case XK_Control_R: zooming_out = TRUE;
+ break;
+ }
+ }
+ else if( nkey == 1 && buf[0] == 'q')
+ done = 1;
+
+ goto _EventLoop;
+ }
+
+ if( XCheckTypedEvent(disp, KeyRelease, (XEvent*)&event) )
+ {
+ char buf[128];
+ KeySym ks;
+ XComposeStatus status;
+
+ if (XLookupString(&event.key,buf,128,&ks,&status) == 0)
+ {
+ switch(ks)
+ {
+ case XK_Shift_L:
+ case XK_Shift_R: zooming_in = FALSE;
+ view.format = 1;
+ DrawWindow();
+ break;
+ case XK_Control_L:
+ case XK_Control_R: zooming_out = FALSE;
+ view.format = 1;
+ DrawWindow();
+ break;
+ }
+ }
+ goto _EventLoop;
+ }
+
+ if( XCheckTypedEvent(disp, MotionNotify, (XEvent*)&event) )
+ {
+ newposx = event.button.x;
+ newposy = event.button.y;
+ while (XCheckTypedEvent(disp, MotionNotify, (XEvent*)&event) == True)
+ {
+ newposx= event.button.x;
+ newposy= event.button.y;
+ }
+ }
+
+ if( XCheckTypedEvent(disp, ButtonPress, (XEvent*)&event) )
+ {
+ if (event.button.button == 1)
+ {
+ panning = TRUE;
+ oldposx = newposx = event.button.x;
+ oldposy = newposy = event.button.y;
+ }
+ }
+
+ if( XCheckTypedEvent(disp, ButtonRelease, (XEvent*)&event) )
+ {
+ if (event.button.button == 1)
+ {
+ panning = FALSE;
+ view.format = 1;
+ DrawWindow();
+ }
+ }
+
+ if( XCheckTypedEvent(disp, DestroyNotify, (XEvent*)&event) )
+ done = 1;
+
+ if( XCheckTypedEvent(disp,ClientMessage , (XEvent*)&event) )
+ {
+ if ((event.message.window == win) && (event.message.data.l[0] == delete_atom))
+ done = 1;
+ }
+
+
+_EventLoop:
+ if( panning )
+ {
+ double yaw, pitch;
+
+ yaw = view.yaw + (newposx - oldposx)/20.0;
+ NORM_ANGLE( yaw );
+
+ pitch = view.pitch - (newposy - oldposy)/20.0;
+ if( pitch > 90.0 ) pitch = 90.0;
+ if( pitch < -90.0 ) pitch = -90.0;
+
+ if( pitch != view.pitch || yaw != view.yaw )
+ {
+ view.pitch = pitch;
+ view.yaw = yaw;
+ isChanged = 1;
+ }
+ }
+ if( zooming_in && view.hfov > 10.5)
+ {
+ view.hfov /= 1.03;
+ isChanged = 1;
+ }
+ if( zooming_out && view.hfov < 165.0)
+ {
+ view.hfov *= 1.03;
+ isChanged = 1;
+ }
+ if( zooming_in || zooming_out || panning )
+ {
+ if( isChanged )
+ {
+ view.format = 1;
+ DrawWindow();
+ }
+ }
+
+
+ }
+ XFreeGC(disp,gc);
+ XDestroyWindow(disp, win);
+ XCloseDisplay(disp);
+}
+
+
+
+
+
+
+// Error reporting
+
+void PrintError( char* fmt, ...)
+{
+ va_list ap;
+ char message[257];
+
+ va_start(ap, fmt);
+ vsprintf(message, fmt, ap);
+ va_end(ap);
+
+ printf("%s\n", message);
+}
+
+void** mymalloc( long numBytes ) // Memory allocation, use Handles
+{
+ char **mem;
+
+ mem = (char**)malloc( sizeof(char*) ); // Allocate memory for pointer
+ if(mem == NULL)
+ return (void**)NULL;
+ else
+ {
+ (*mem) = (char*) malloc( numBytes ); // Allocate numBytes
+ if( *mem == NULL )
+ {
+ free( mem );
+ return (void**)NULL;
+ }
+ else
+ return (void**)mem;
+ }
+}
+
+void myfree( void** Hdl ) // free Memory, use Handles
+{
+ free( (char*) *Hdl );
+ free( (char**) Hdl );
+}
+
+
+void SetImageDefaults(Image *im)
+{
+ im->data = NULL;
+ im->bytesPerLine = 0;
+ im->width = 0;
+ im->height = 0;
+ im->dataSize = 0;
+ im->bitsPerPixel = 0;
+ im->format = 0;
+ im->dataformat = _RGB;
+ im->hfov = 0.0;
+ im->yaw = 0.0;
+ im->pitch = 0.0;
+ im->roll = 0.0;
+// SetCorrectDefaults( &(im->cP) );
+ *(im->name) = 0;
+}
+
+// expand image from 3 to 4 bits per pixel. No pad bytes allowed.
+// Memory must be allocated
+void ThreeToFourBPP( Image *im )
+{
+ register int x,y,c1,c2;
+
+ if( im->bitsPerPixel == 32 || im->bitsPerPixel == 64) // Nothing to do
+ return;
+
+
+
+ if( im->bitsPerPixel == 24 ) // Convert to 4byte / pixel
+ {
+ for( y = im->height-1; y>=0; y--)
+ {
+ for( x= im->width-1; x>=0; x--)
+ {
+ c1 = (y * im->width + x) * 4;
+ c2 = y * im->bytesPerLine + x * 3;
+ (*(im->data))[c1++] = UCHAR_MAX;
+ (*(im->data))[c1++] = (*(im->data))[c2++];
+ (*(im->data))[c1++] = (*(im->data))[c2++];
+ (*(im->data))[c1++] = (*(im->data))[c2++];
+ }
+ }
+ im->bitsPerPixel = 32;
+ im->bytesPerLine = im->width * 4;
+ }
+ else if( im->bitsPerPixel == 48 ) // Convert to 8byte / pixel
+ {
+ for( y = im->height-1; y>=0; y--)
+ {
+ for( x= im->width-1; x>=0; x--)
+ {
+ c1 = (y * im->width + x) * 4;
+ c2 = y * im->bytesPerLine/2 + x * 3;
+ ((USHORT*)(*(im->data)))[c1++] = USHRT_MAX;
+ ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
+ ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
+ ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
+ }
+ }
+ im->bitsPerPixel = 64;
+ im->bytesPerLine = im->width * 8;
+ }
+ im->dataSize = im->height * im->bytesPerLine;
+}
+
+
+
+void DrawWindow()
+{
+ XWindowAttributes xa;
+
+ XGetWindowAttributes( disp, win, &xa );
+
+ if( xa.width != view.width || xa.height != view.height )
+ {
+ myfree((void**)view.data);
+ view.width = xa.width;
+ view.height = xa.height;
+ view.bytesPerLine = view.width * view.bitsPerPixel / 8;
+ view.dataSize = view.bytesPerLine * view.height;
+ view.format = 1;
+ view.data = (unsigned char**)mymalloc( view.dataSize );
+ if(view.data == NULL)
+ {
+ PrintError("Not enough memory");
+ exit(0);
+ }
+
+ ximage = XCreateImage(disp, visual, depth, ZPixmap, 0,
+ NULL, view.width, view.height,
+ 8, 0);
+ ximage->data = (char *)*(view.data);
+ ximage->byte_order= MSBFirst;
+ }
+ if( view.format )
+ {
+ if( panning || zooming_in || zooming_out)
+ DrawView(_nn);
+ else
+ DrawView(_bilinear);
+ }
+
+ XPutImage(disp, win, gc, ximage, 0, 0, 0, 0, view.width, view.height);
+}
+
+void DrawView(int InterPolator)
+{
+ TrformStr Tr;
+
+ Tr.interpolator = InterPolator;
+
+ Tr.src = &pano;
+ Tr.dest = &view;
+
+ PV_ExtractStill( &Tr );
+
+ view.format = 0;
+ return;
+
+}
+