1 /* Panorama_Tools - Generate, Edit and Convert Panoramic Images
2 Copyright (C) 1998,1999,2000 - Helmut Dersch der@fh-furtwangen.de
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /*------------------------------------------------------------*/
22 #include <X11/Xutil.h>
23 #include <X11/cursorfont.h>
24 #include <X11/keysym.h>
25 #include <X11/Xatom.h>
30 void PV_ExtractStill( TrformStr *TrPtr );
31 void PV_SetInvMakeParams( struct fDesc *stack, struct MakeParams *mp, Image *im , Image *pn );
37 void DrawView(int InterPolator);
40 int zooming_in = FALSE;
41 int zooming_out = FALSE;
43 #define VIEW_WIDTH 400
44 #define VIEW_HEIGHT 300
47 char text[] = "PTViewer";
53 XImage *ximage = NULL;
60 int main( int argc, char** argv )
72 XConfigureEvent configure;
75 XResizeRequestEvent resize;
76 XClientMessageEvent message;
79 static Atom proto_atom= None, delete_atom= None;
86 disp = XOpenDisplay("");
87 screen = DefaultScreen(disp);
88 depth = DefaultDepth(disp, screen);
92 PrintError("Depth = %d, must be 24 pixels", (int)depth);
95 bg = WhitePixel(disp,screen);
96 fg = BlackPixel(disp,screen);
98 // Load panoramic image
101 PrintError("No image file supplied");
105 if( strcmp( argv[1], "-h" ) == 0 )
107 PrintError( "%s\n %s\nUsage: PTViewer Imagefile", "PTViewer", LONGVERSION );
110 if( readJPEG( &pano, (fullPath*)argv[1] ) != 0 )
112 PrintError("Could not read panoramic image");
116 pano.format = _equirectangular;
118 // Initialize Look-up tables
120 if( SetUpAtan() || SetUpSqrt() || SetUpMweights() )
122 PrintError("Could not set up LU Tables");
126 // Set up viewer window
128 SetImageDefaults( &view );
131 view.width = VIEW_WIDTH;
132 view.height = VIEW_HEIGHT;
133 view.bitsPerPixel = 32;
134 view.bytesPerLine = view.width * view.bitsPerPixel / 8;
135 view.dataSize = view.bytesPerLine * view.height;
137 view.data = (unsigned char**)mymalloc( view.dataSize );
138 if(view.data == NULL)
140 PrintError("Not enough memory");
147 hint.width = view.width;
148 hint.height = view.height;
149 hint.flags=PPosition | PSize;
151 win = XCreateSimpleWindow(disp,
152 DefaultRootWindow(disp),
161 XSetStandardProperties(disp,
169 gc = XCreateGC(disp,win,0,0);
170 XSetBackground(disp,gc,bg);
171 XSetForeground(disp,gc,fg);
175 ButtonPressMask | ButtonReleaseMask | Button1MotionMask | KeyPressMask | KeyReleaseMask |
176 StructureNotifyMask | EnterWindowMask | LeaveWindowMask| ExposureMask);
177 XMapRaised(disp,win);
179 proto_atom = XInternAtom(disp, "WM_PROTOCOLS", False);
180 delete_atom = XInternAtom(disp, "WM_DELETE_WINDOW", False);
181 if ((proto_atom != None) && (delete_atom != None))
182 XChangeProperty(disp, win, proto_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&delete_atom, 1);
186 visual = DefaultVisual(disp, screen);
188 ximage = XCreateImage(disp, visual, depth, ZPixmap, 0,
189 NULL, view.width, view.height,
191 memset( *(view.data), 0, view.dataSize);
192 ximage->data = (char *)*(view.data);
193 ximage->byte_order= MSBFirst;
204 if( XCheckTypedEvent(disp, Expose, (XEvent*)&event) ) DrawWindow();
206 if( XCheckTypedEvent(disp, KeyPress, (XEvent*)&event) )
210 XComposeStatus status;
211 int nkey = XLookupString(&event.key,buf,128,&ks,&status);
218 case XK_Shift_R: zooming_in = TRUE;
222 case XK_Control_R: zooming_out = TRUE;
226 else if( nkey == 1 && buf[0] == 'q')
232 if( XCheckTypedEvent(disp, KeyRelease, (XEvent*)&event) )
236 XComposeStatus status;
238 if (XLookupString(&event.key,buf,128,&ks,&status) == 0)
243 case XK_Shift_R: zooming_in = FALSE;
248 case XK_Control_R: zooming_out = FALSE;
257 if( XCheckTypedEvent(disp, MotionNotify, (XEvent*)&event) )
259 newposx = event.button.x;
260 newposy = event.button.y;
261 while (XCheckTypedEvent(disp, MotionNotify, (XEvent*)&event) == True)
263 newposx= event.button.x;
264 newposy= event.button.y;
268 if( XCheckTypedEvent(disp, ButtonPress, (XEvent*)&event) )
270 if (event.button.button == 1)
273 oldposx = newposx = event.button.x;
274 oldposy = newposy = event.button.y;
278 if( XCheckTypedEvent(disp, ButtonRelease, (XEvent*)&event) )
280 if (event.button.button == 1)
288 if( XCheckTypedEvent(disp, DestroyNotify, (XEvent*)&event) )
291 if( XCheckTypedEvent(disp,ClientMessage , (XEvent*)&event) )
293 if ((event.message.window == win) && (event.message.data.l[0] == delete_atom))
303 yaw = view.yaw + (newposx - oldposx)/20.0;
306 pitch = view.pitch - (newposy - oldposy)/20.0;
307 if( pitch > 90.0 ) pitch = 90.0;
308 if( pitch < -90.0 ) pitch = -90.0;
310 if( pitch != view.pitch || yaw != view.yaw )
317 if( zooming_in && view.hfov > 10.5)
322 if( zooming_out && view.hfov < 165.0)
327 if( zooming_in || zooming_out || panning )
339 XDestroyWindow(disp, win);
350 void PrintError( char* fmt, ...)
356 vsprintf(message, fmt, ap);
359 printf("%s\n", message);
362 void** mymalloc( long numBytes ) // Memory allocation, use Handles
366 mem = (char**)malloc( sizeof(char*) ); // Allocate memory for pointer
371 (*mem) = (char*) malloc( numBytes ); // Allocate numBytes
382 void myfree( void** Hdl ) // free Memory, use Handles
384 free( (char*) *Hdl );
385 free( (char**) Hdl );
389 void SetImageDefaults(Image *im)
392 im->bytesPerLine = 0;
396 im->bitsPerPixel = 0;
398 im->dataformat = _RGB;
403 // SetCorrectDefaults( &(im->cP) );
407 // expand image from 3 to 4 bits per pixel. No pad bytes allowed.
408 // Memory must be allocated
409 void ThreeToFourBPP( Image *im )
411 register int x,y,c1,c2;
413 if( im->bitsPerPixel == 32 || im->bitsPerPixel == 64) // Nothing to do
418 if( im->bitsPerPixel == 24 ) // Convert to 4byte / pixel
420 for( y = im->height-1; y>=0; y--)
422 for( x= im->width-1; x>=0; x--)
424 c1 = (y * im->width + x) * 4;
425 c2 = y * im->bytesPerLine + x * 3;
426 (*(im->data))[c1++] = UCHAR_MAX;
427 (*(im->data))[c1++] = (*(im->data))[c2++];
428 (*(im->data))[c1++] = (*(im->data))[c2++];
429 (*(im->data))[c1++] = (*(im->data))[c2++];
432 im->bitsPerPixel = 32;
433 im->bytesPerLine = im->width * 4;
435 else if( im->bitsPerPixel == 48 ) // Convert to 8byte / pixel
437 for( y = im->height-1; y>=0; y--)
439 for( x= im->width-1; x>=0; x--)
441 c1 = (y * im->width + x) * 4;
442 c2 = y * im->bytesPerLine/2 + x * 3;
443 ((USHORT*)(*(im->data)))[c1++] = USHRT_MAX;
444 ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
445 ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
446 ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
449 im->bitsPerPixel = 64;
450 im->bytesPerLine = im->width * 8;
452 im->dataSize = im->height * im->bytesPerLine;
459 XWindowAttributes xa;
461 XGetWindowAttributes( disp, win, &xa );
463 if( xa.width != view.width || xa.height != view.height )
465 myfree((void**)view.data);
466 view.width = xa.width;
467 view.height = xa.height;
468 view.bytesPerLine = view.width * view.bitsPerPixel / 8;
469 view.dataSize = view.bytesPerLine * view.height;
471 view.data = (unsigned char**)mymalloc( view.dataSize );
472 if(view.data == NULL)
474 PrintError("Not enough memory");
478 ximage = XCreateImage(disp, visual, depth, ZPixmap, 0,
479 NULL, view.width, view.height,
481 ximage->data = (char *)*(view.data);
482 ximage->byte_order= MSBFirst;
486 if( panning || zooming_in || zooming_out)
492 XPutImage(disp, win, gc, ximage, 0, 0, 0, 0, view.width, view.height);
495 void DrawView(int InterPolator)
499 Tr.interpolator = InterPolator;
504 PV_ExtractStill( &Tr );