Imported PTViewer 0.4 as received from <http://www.all-in-one.ee/~dersch/>.
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Tue, 14 Aug 2007 16:24:45 +0000 (18:24 +0200)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Tue, 14 Aug 2007 16:24:45 +0000 (18:24 +0200)
src/Makefile [new file with mode: 0644]
src/filter.h [new file with mode: 0644]
src/jpeg.c [new file with mode: 0644]
src/panolib.c [new file with mode: 0644]
src/panorama.h [new file with mode: 0644]
src/version.h [new file with mode: 0644]
src/viewer.c [new file with mode: 0644]

diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..df86dea
--- /dev/null
@@ -0,0 +1,23 @@
+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)
diff --git a/src/filter.h b/src/filter.h
new file mode 100644 (file)
index 0000000..b9a1a1a
--- /dev/null
@@ -0,0 +1,894 @@
+/* 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
+
+
+
+
+
+
diff --git a/src/jpeg.c b/src/jpeg.c
new file mode 100644 (file)
index 0000000..dbeaf27
--- /dev/null
@@ -0,0 +1,199 @@
+/* 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;
+
+
+}
+
diff --git a/src/panolib.c b/src/panolib.c
new file mode 100644 (file)
index 0000000..58d190b
--- /dev/null
@@ -0,0 +1,549 @@
+/* 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;
+}
+               
+
diff --git a/src/panorama.h b/src/panorama.h
new file mode 100644 (file)
index 0000000..39628bc
--- /dev/null
@@ -0,0 +1,265 @@
+/* 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
diff --git a/src/version.h b/src/version.h
new file mode 100644 (file)
index 0000000..25fcaaa
--- /dev/null
@@ -0,0 +1,23 @@
+/* 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
diff --git a/src/viewer.c b/src/viewer.c
new file mode 100644 (file)
index 0000000..55cc106
--- /dev/null
@@ -0,0 +1,510 @@
+/* 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;
+       
+}
+