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>
32 #include "utils_image.h"
34 #define DEF_VIEW_WIDTH 400
35 #define DEF_VIEW_HEIGHT 300
37 char text[] = "PTViewer";
47 static int copy_rgb_to_zpixmap (XImage *dest, const ui_image_t *src)
58 uint32_t dest_pixel_value;
64 uint32_t dest_r_maxval;
65 uint32_t dest_g_maxval;
66 uint32_t dest_b_maxval;
68 uint32_t dest_r_offset;
69 uint32_t dest_g_offset;
70 uint32_t dest_b_offset;
75 dest_r_maxval = dest->red_mask;
76 dest_g_maxval = dest->green_mask;
77 dest_b_maxval = dest->blue_mask;
78 for (x = 0; x < dest->depth; x++)
80 if ((dest_r_maxval & 0x01) == 0)
85 if ((dest_g_maxval & 0x01) == 0)
90 if ((dest_b_maxval & 0x01) == 0)
97 src_data = (uint32_t *) *src->data;
100 for (y = 0; y < dest->height; y++)
102 for (x = 0; x < dest->width; x++, pixel++)
106 src_r = src->data[0][pixel];
107 src_g = src->data[1][pixel];
108 src_b = src->data[2][pixel];
110 dest_r = dest_r_maxval * src_r / 255;
111 dest_g = dest_g_maxval * src_g / 255;
112 dest_b = dest_b_maxval * src_b / 255;
115 | ((dest_r << dest_r_offset) & dest->red_mask)
116 | ((dest_g << dest_g_offset) & dest->green_mask)
117 | ((dest_b << dest_b_offset) & dest->blue_mask);
119 for (bytenum = 0; bytenum < (dest->depth / 8); bytenum++)
121 dest->data[(pixel * dest->bits_per_pixel / 8) + bytenum] =
122 (dest_pixel_value >> (dest->bits_per_pixel - (8 * (bytenum + 1)))) & 0xFF;
128 } /* int copy_rgb_to_zpixmap */
130 static int draw_window (const ui_image_t *img)
132 static XImage *ximage = NULL;
134 if ((ximage != NULL) && ((img->width != ximage->width) || (img->height != ximage->height)))
137 XDestroyImage (ximage);
144 ximage = XCreateImage(disp_g, visual_g, depth_g, ZPixmap, 0,
145 NULL, img->width, img->height,
150 ximage->byte_order= MSBFirst;
152 data = (char *) malloc (img->width * img->height * depth_g / 8);
154 if (ximage->data == NULL)
156 XDestroyImage (ximage);
162 copy_rgb_to_zpixmap (ximage, img);
163 XPutImage(disp_g, window_g, gc, ximage, 0, 0,
164 0, 0, ximage->width, ximage->height);
167 } /* int draw_window */
169 #define ZOOM_SPEED 1.03
171 static void zoom_in (double *fov)
173 *fov = *fov / ZOOM_SPEED;
178 static void zoom_out (double *fov)
180 *fov = *fov * ZOOM_SPEED;
183 } /* void zoom_out */
185 int main( int argc, char** argv )
188 unsigned long color_fg, color_bg;
190 static Atom proto_atom= None, delete_atom= None;
198 /* Detect mouse movement direction */
209 disp_g = XOpenDisplay("");
210 screen_g = DefaultScreen(disp_g);
211 depth_g = DefaultDepth(disp_g, screen_g);
213 color_bg = WhitePixel(disp_g,screen_g);
214 color_fg = BlackPixel(disp_g,screen_g);
216 // Load panoramic image
219 PrintError("No image file supplied");
223 if( strcmp( argv[1], "-h" ) == 0 ) /* FIXME: Use getopt */
225 PrintError( "%s\n %s\nUsage: PTViewer Imagefile", "PTViewer", LONGVERSION );
229 pano = ui_create_file (argv[1]);
232 PrintError ("Unable to read pano file.");
236 printf ("Panorama `%s', %ux%u pixels, loaded.\n",
237 argv[1], pano->width, pano->height);
239 view = ui_create (DEF_VIEW_WIDTH, DEF_VIEW_HEIGHT); /* FIXME: Possibly chose another size */
242 PrintError ("Unable to create view.");
246 hint.width = view->width;
247 hint.height = view->height;
250 window_g = XCreateSimpleWindow(disp_g,
251 DefaultRootWindow(disp_g),
253 view->width, view->height,
257 XSetStandardProperties(disp_g,
265 gc = XCreateGC(disp_g,window_g,0,0);
266 XSetBackground(disp_g,gc,color_bg);
267 XSetForeground(disp_g,gc,color_fg);
269 event_mask = ButtonPressMask | ButtonReleaseMask | Button1MotionMask
270 | KeyPressMask | KeyReleaseMask | StructureNotifyMask
271 | EnterWindowMask | LeaveWindowMask| ExposureMask;
273 XSelectInput(disp_g, window_g, event_mask);
274 XMapRaised(disp_g,window_g);
276 proto_atom = XInternAtom(disp_g, "WM_PROTOCOLS", False);
277 delete_atom = XInternAtom(disp_g, "WM_DELETE_WINDOW", False);
278 if ((proto_atom != None) && (delete_atom != None))
279 XChangeProperty(disp_g, window_g, proto_atom, XA_ATOM, 32,
280 PropModeReplace, (unsigned char *)&delete_atom,
282 visual_g = DefaultVisual(disp_g, screen_g);
284 pl_extract_view (view, pano, pitch, yaw, fov);
293 XMaskEvent (disp_g, event_mask, &event);
301 case ConfigureNotify:
303 XConfigureEvent *cev = (XConfigureEvent *) &event;
304 printf ("XConfigureEvent received: width = %i; height = %i;\n",
305 cev->width, cev->height);
308 view = ui_create (cev->width, cev->height);
315 XKeyEvent *kev = (XKeyEvent *) &event;
316 KeySym ks = XLookupKeysym (kev, 0);
364 printf ("Ignoring KeyRelease event.\n");
370 XButtonEvent *bev = (XButtonEvent *) &event;
371 pos_x_old = pos_x_new = bev->x;
372 pos_y_old = pos_y_new = bev->y;
378 XMotionEvent *mev = (XMotionEvent *) &event;
380 pos_x_old = pos_x_new;
381 pos_y_old = pos_y_new;
388 while (XCheckTypedEvent (disp_g, MotionNotify, &event));
390 printf ("XMotionEvent received: [%u,%u] -> [%u,%u]\n",
391 pos_x_old, pos_y_old, pos_x_new, pos_y_new);
393 if (mev->state & Button1Mask)
395 double yaw_diff = (pos_x_new - pos_x_old) / 24.0;
398 else if (yaw_diff < -90.0)
404 else if (yaw <= -180.0)
407 pitch -= (pos_y_new - pos_y_old) / 24.0;
410 else if (pitch < -90.0)
419 printf ("Unhandled event type: 0x%02x\n",
421 } /* switch (event.type) */
425 pl_extract_view (view, pano, pitch, yaw, fov);
428 } /* while (done == 0) */
431 XDestroyWindow(disp_g, window_g);
432 XCloseDisplay(disp_g);
444 void PrintError( char* fmt, ...)
450 vsprintf(message, fmt, ap);
453 printf("%s\n", message);
456 void** mymalloc( long numBytes ) // Memory allocation, use Handles
460 mem = (char**)malloc( sizeof(char*) ); // Allocate memory for pointer
465 (*mem) = (char*) malloc( numBytes ); // Allocate numBytes
476 void myfree( void** Hdl ) // free Memory, use Handles
478 free( (char*) *Hdl );
479 free( (char**) Hdl );
483 void SetImageDefaults(Image *im)
486 im->bytesPerLine = 0;
490 im->bitsPerPixel = 0;
492 im->dataformat = _RGB;
497 // SetCorrectDefaults( &(im->cP) );
501 // expand image from 3 to 4 bits per pixel. No pad bytes allowed.
502 // Memory must be allocated
503 void ThreeToFourBPP( Image *im )
505 register int x,y,c1,c2;
507 if( im->bitsPerPixel == 32 || im->bitsPerPixel == 64) // Nothing to do
512 if( im->bitsPerPixel == 24 ) // Convert to 4byte / pixel
514 for( y = im->height-1; y>=0; y--)
516 for( x= im->width-1; x>=0; x--)
518 c1 = (y * im->width + x) * 4;
519 c2 = y * im->bytesPerLine + x * 3;
520 (*(im->data))[c1++] = UCHAR_MAX;
521 (*(im->data))[c1++] = (*(im->data))[c2++];
522 (*(im->data))[c1++] = (*(im->data))[c2++];
523 (*(im->data))[c1++] = (*(im->data))[c2++];
526 im->bitsPerPixel = 32;
527 im->bytesPerLine = im->width * 4;
529 else if( im->bitsPerPixel == 48 ) // Convert to 8byte / pixel
531 for( y = im->height-1; y>=0; y--)
533 for( x= im->width-1; x>=0; x--)
535 c1 = (y * im->width + x) * 4;
536 c2 = y * im->bytesPerLine/2 + x * 3;
537 ((USHORT*)(*(im->data)))[c1++] = USHRT_MAX;
538 ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
539 ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
540 ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
543 im->bitsPerPixel = 64;
544 im->bytesPerLine = im->width * 8;
546 im->dataSize = im->height * im->bytesPerLine;
550 * vim: set shiftwidth=2 tabstop=8 softtabstop=2 :