From c20210594e4929d3803517cbe185b6696ddb5775 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Tue, 14 Aug 2007 18:24:45 +0200 Subject: [PATCH] Imported PTViewer 0.4 as received from . --- src/Makefile | 23 ++ src/filter.h | 894 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/jpeg.c | 199 +++++++++++++ src/panolib.c | 549 +++++++++++++++++++++++++++++++++++ src/panorama.h | 265 +++++++++++++++++ src/version.h | 23 ++ src/viewer.c | 510 ++++++++++++++++++++++++++++++++ 7 files changed, 2463 insertions(+) create mode 100644 src/Makefile create mode 100644 src/filter.h create mode 100644 src/jpeg.c create mode 100644 src/panolib.c create mode 100644 src/panorama.h create mode 100644 src/version.h create mode 100644 src/viewer.c diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..df86dea --- /dev/null +++ b/src/Makefile @@ -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 index 0000000..b9a1a1a --- /dev/null +++ b/src/filter.h @@ -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 +#include +#include +#include +#include +#include +#include + +#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 + #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 index 0000000..dbeaf27 --- /dev/null +++ b/src/jpeg.c @@ -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 +#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; ibytesPerLine); + } + + 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 index 0000000..58d190b --- /dev/null +++ b/src/panolib.c @@ -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 + #define fullPath FSSpec + #undef PATH_SEP + #define PATH_SEP ':' + +#else // __Mac__, use ANSI-filefunctions + + #ifdef __Win__ + // #include ; 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 index 0000000..25fcaaa --- /dev/null +++ b/src/version.h @@ -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 index 0000000..55cc106 --- /dev/null +++ b/src/viewer.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#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; + +} + -- 2.11.0