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)))
138 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 ximage->data = (char *) malloc (img->width * img->height * depth_g / 8);
153 if (ximage->data == NULL)
155 XDestroyImage (ximage);
161 copy_rgb_to_zpixmap (ximage, img);
162 XPutImage(disp_g, window_g, gc, ximage, 0, 0,
163 0, 0, ximage->width, ximage->height);
166 } /* int draw_window */
168 #define ZOOM_SPEED 1.03
170 static void zoom_in (double *fov)
172 *fov = *fov / ZOOM_SPEED;
177 static void zoom_out (double *fov)
179 *fov = *fov * ZOOM_SPEED;
182 } /* void zoom_out */
184 int main( int argc, char** argv )
186 unsigned long color_fg, color_bg;
188 static Atom proto_atom= None, delete_atom= None;
196 /* Detect mouse movement direction */
197 unsigned int btn_current_pressed = 0;
198 int btn_reference_pos_x = 0;
199 int btn_reference_pos_y = 0;
200 int btn_current_pos_x = 0;
201 int btn_current_pos_y = 0;
208 disp_g = XOpenDisplay("");
209 screen_g = DefaultScreen(disp_g);
210 depth_g = DefaultDepth(disp_g, screen_g);
212 color_bg = WhitePixel(disp_g,screen_g);
213 color_fg = BlackPixel(disp_g,screen_g);
215 // Load panoramic image
218 PrintError("No image file supplied");
222 if( strcmp( argv[1], "-h" ) == 0 ) /* FIXME: Use getopt */
224 PrintError( "%s\n %s\nUsage: PTViewer Imagefile", "PTViewer", LONGVERSION );
228 pano = ui_create_file (argv[1]);
231 PrintError ("Unable to read pano file.");
235 printf ("Panorama `%s', %ux%u pixels, loaded.\n",
236 argv[1], pano->width, pano->height);
238 view = ui_create (DEF_VIEW_WIDTH, DEF_VIEW_HEIGHT); /* FIXME: Possibly chose another size */
241 PrintError ("Unable to create view.");
245 window_g = XCreateSimpleWindow(disp_g,
246 DefaultRootWindow(disp_g),
248 view->width, view->height,
255 memset (&hint, '\0', sizeof (hint));
256 hint.width = view->width;
257 hint.height = view->height;
260 XSetStandardProperties(disp_g,
270 gc = XCreateGC(disp_g,window_g,0,0);
271 XSetBackground(disp_g,gc,color_bg);
272 XSetForeground(disp_g,gc,color_fg);
274 event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
275 | KeyPressMask | KeyReleaseMask | StructureNotifyMask
276 | EnterWindowMask | LeaveWindowMask| ExposureMask;
278 XSelectInput(disp_g, window_g, event_mask);
279 XMapRaised(disp_g,window_g);
281 proto_atom = XInternAtom(disp_g, "WM_PROTOCOLS", False);
282 delete_atom = XInternAtom(disp_g, "WM_DELETE_WINDOW", False);
283 if ((proto_atom != None) && (delete_atom != None))
284 XChangeProperty(disp_g, window_g, proto_atom, XA_ATOM, 32,
285 PropModeReplace, (unsigned char *)&delete_atom,
287 visual_g = DefaultVisual(disp_g, screen_g);
289 pl_extract_view (view, pano, pitch, yaw, fov, BILINEAR);
298 memset (&event, '\0', sizeof (event));
300 if (btn_current_pressed == 0)
302 /* No button is pressed -> block */
303 XMaskEvent (disp_g, event_mask, &event);
307 /* A button is pressed -> do not block */
308 XCheckMaskEvent (disp_g, event_mask, &event);
313 case 0: /* XCheckMaskEvent didn't return an event */
318 XExposeEvent *eev = (XExposeEvent *) &event;
320 while (eev->count != 0)
322 if (!XCheckTypedEvent (disp_g, Expose, &event))
341 case ConfigureNotify:
343 XConfigureEvent *cev = (XConfigureEvent *) &event;
346 view = ui_create (cev->width, cev->height);
353 XKeyEvent *kev = (XKeyEvent *) &event;
355 int buffer_len = sizeof (buffer);
358 buffer_len = XLookupString(kev, buffer, sizeof (buffer), &ks, NULL);
360 if (buffer_len >= sizeof (buffer))
361 buffer_len = sizeof (buffer) - 1;
362 buffer[buffer_len] = '\0';
411 printf ("Unhandeled KeySym 0x%02llx, buffer = %s\n", (uint64_t) ks, buffer);
418 printf ("Ignoring KeyRelease event.\n");
423 /* case ButtonRelease: */
425 XButtonEvent *bev = (XButtonEvent *) &event;
427 btn_current_pressed = bev->button;
428 btn_current_pos_x = btn_reference_pos_x = bev->x;
429 btn_current_pos_y = btn_reference_pos_y = bev->y;
434 btn_current_pressed = 0;
435 /* Re-draw the image (when no button is pressed better interpolation is
442 XMotionEvent *mev = (XMotionEvent *) &event;
446 btn_current_pos_x = mev->x;
447 btn_current_pos_y = mev->y;
449 while (XCheckTypedEvent (disp_g, MotionNotify, &event));
454 printf ("Unhandled event type: 0x%02x\n",
456 } /* switch (event.type) */
459 * Check for pressed buttons and change view accordingly
461 if (btn_current_pressed == Button1)
463 double yaw_diff = (btn_current_pos_x - btn_reference_pos_x) / 24.0;
466 else if (yaw_diff < -90.0)
472 else if (yaw <= -180.0)
475 pitch -= (btn_current_pos_y - btn_reference_pos_y) / 24.0;
478 else if (pitch < -90.0)
483 else if (btn_current_pressed == Button3)
485 double zoom_diff = (btn_current_pos_y - btn_reference_pos_y) / 64.0;
486 double zoom_ratio = pow (ZOOM_SPEED, zoom_diff);
491 else if (fov > 165.0)
499 pl_extract_view (view, pano, pitch, yaw, fov,
500 (btn_current_pressed == 0) ? BILINEAR : NNEIGHBOUR);
503 } /* while (done == 0) */
506 XDestroyWindow(disp_g, window_g);
507 XCloseDisplay(disp_g);
519 void PrintError( char* fmt, ...)
525 vsprintf(message, fmt, ap);
528 printf("%s\n", message);
531 void** mymalloc( long numBytes ) // Memory allocation, use Handles
535 mem = (char**)malloc( sizeof(char*) ); // Allocate memory for pointer
540 (*mem) = (char*) malloc( numBytes ); // Allocate numBytes
551 void myfree( void** Hdl ) // free Memory, use Handles
553 free( (char*) *Hdl );
554 free( (char**) Hdl );
558 void SetImageDefaults(Image *im)
561 im->bytesPerLine = 0;
565 im->bitsPerPixel = 0;
567 im->dataformat = _RGB;
572 // SetCorrectDefaults( &(im->cP) );
576 // expand image from 3 to 4 bits per pixel. No pad bytes allowed.
577 // Memory must be allocated
578 void ThreeToFourBPP( Image *im )
580 register int x,y,c1,c2;
582 if( im->bitsPerPixel == 32 || im->bitsPerPixel == 64) // Nothing to do
587 if( im->bitsPerPixel == 24 ) // Convert to 4byte / pixel
589 for( y = im->height-1; y>=0; y--)
591 for( x= im->width-1; x>=0; x--)
593 c1 = (y * im->width + x) * 4;
594 c2 = y * im->bytesPerLine + x * 3;
595 (*(im->data))[c1++] = UCHAR_MAX;
596 (*(im->data))[c1++] = (*(im->data))[c2++];
597 (*(im->data))[c1++] = (*(im->data))[c2++];
598 (*(im->data))[c1++] = (*(im->data))[c2++];
601 im->bitsPerPixel = 32;
602 im->bytesPerLine = im->width * 4;
604 else if( im->bitsPerPixel == 48 ) // Convert to 8byte / pixel
606 for( y = im->height-1; y>=0; y--)
608 for( x= im->width-1; x>=0; x--)
610 c1 = (y * im->width + x) * 4;
611 c2 = y * im->bytesPerLine/2 + x * 3;
612 ((USHORT*)(*(im->data)))[c1++] = USHRT_MAX;
613 ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
614 ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
615 ((USHORT*)(*(im->data)))[c1++] = ((USHORT*)(*(im->data)))[c2++];
618 im->bitsPerPixel = 64;
619 im->bytesPerLine = im->width * 8;
621 im->dataSize = im->height * im->bytesPerLine;
625 * vim: set shiftwidth=2 tabstop=8 softtabstop=2 :