#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
-#include "filter.h"
-
-void PV_ExtractStill( TrformStr *TrPtr );
-void PV_SetInvMakeParams( struct fDesc *stack, struct MakeParams *mp, Image *im , Image *pn );
-
-void DrawWindow();
-void DrawView(int InterPolator);
-
-int readJPEG ( Image *im, fullPath *sfile );
-int panning = FALSE;
-int zooming_in = FALSE;
-int zooming_out = FALSE;
-
-#define VIEW_WIDTH 400
-#define VIEW_HEIGHT 300
+#include "filter.h"
+#include "panolib.h"
+#include "utils_image.h"
+#define DEF_VIEW_WIDTH 400
+#define DEF_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;
+Display *disp_g;
+Window window_g;
+int screen_g;
+GC gc;
+Visual *visual_g;
+unsigned int depth_g;
-int main( int argc, char** argv )
+static int copy_rgb_to_zpixmap (XImage *dest, const ui_image_t *src)
{
- 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);
- }
- bg = WhitePixel(disp,screen);
- fg = BlackPixel(disp,screen);
+ uint32_t *src_data;
- // 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;
-
- // 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);
- }
+ uint32_t src_r;
+ uint32_t src_g;
+ uint32_t src_b;
+ uint32_t dest_r;
+ uint32_t dest_g;
+ uint32_t dest_b;
+ uint32_t dest_pixel_value;
- 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;
+ uint32_t x;
+ uint32_t y;
+ uint32_t pixel;
+ uint32_t dest_r_maxval;
+ uint32_t dest_g_maxval;
+ uint32_t dest_b_maxval;
+ uint32_t dest_r_offset;
+ uint32_t dest_g_offset;
+ uint32_t dest_b_offset;
- done = 0;
- while( done==0)
+ dest_r_offset = 0;
+ dest_g_offset = 0;
+ dest_b_offset = 0;
+ dest_r_maxval = dest->red_mask;
+ dest_g_maxval = dest->green_mask;
+ dest_b_maxval = dest->blue_mask;
+ for (x = 0; x < dest->depth; x++)
{
- 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 ((dest_r_maxval & 0x01) == 0)
{
- if (event.button.button == 1)
- {
- panning = TRUE;
- oldposx = newposx = event.button.x;
- oldposy = newposy = event.button.y;
- }
+ dest_r_offset++;
+ dest_r_maxval >>= 1;
}
-
- if( XCheckTypedEvent(disp, ButtonRelease, (XEvent*)&event) )
+ if ((dest_g_maxval & 0x01) == 0)
{
- if (event.button.button == 1)
- {
- panning = FALSE;
- view.format = 1;
- DrawWindow();
- }
+ dest_g_offset++;
+ dest_g_maxval >>= 1;
}
-
- if( XCheckTypedEvent(disp, DestroyNotify, (XEvent*)&event) )
- done = 1;
-
- if( XCheckTypedEvent(disp,ClientMessage , (XEvent*)&event) )
+ if ((dest_b_maxval & 0x01) == 0)
{
- if ((event.message.window == win) && (event.message.data.l[0] == delete_atom))
- done = 1;
+ dest_b_offset++;
+ dest_b_maxval >>= 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 )
+ src_data = (uint32_t *) *src->data;
+
+ pixel = 0;
+ for (y = 0; y < dest->height; y++)
+ {
+ for (x = 0; x < dest->width; x++, pixel++)
{
- if( isChanged )
+ int32_t bytenum;
+
+ src_r = src->data[0][pixel];
+ src_g = src->data[1][pixel];
+ src_b = src->data[2][pixel];
+
+ dest_r = dest_r_maxval * src_r / 255;
+ dest_g = dest_g_maxval * src_g / 255;
+ dest_b = dest_b_maxval * src_b / 255;
+
+ dest_pixel_value = 0
+ | ((dest_r << dest_r_offset) & dest->red_mask)
+ | ((dest_g << dest_g_offset) & dest->green_mask)
+ | ((dest_b << dest_b_offset) & dest->blue_mask);
+
+ for (bytenum = 0; bytenum < (dest->depth / 8); bytenum++)
{
- view.format = 1;
- DrawWindow();
+ dest->data[(pixel * dest->bits_per_pixel / 8) + bytenum] =
+ (dest_pixel_value >> (dest->bits_per_pixel - (8 * (bytenum + 1)))) & 0xFF;
}
}
+ }
+
+ return (0);
+} /* int copy_rgb_to_zpixmap */
+
+static int draw_window (const ui_image_t *img)
+{
+ static XImage *ximage = NULL;
+
+ if ((ximage != NULL) && ((img->width != ximage->width) || (img->height != ximage->height)))
+ {
+ free (ximage->data);
+ XDestroyImage (ximage);
+ ximage = NULL;
+ }
+
+ if (ximage == NULL)
+ {
+ char *data;
+ ximage = XCreateImage(disp_g, visual_g, depth_g, ZPixmap, 0,
+ NULL, img->width, img->height,
+ 8, 0);
+ if (ximage == NULL)
+ return (-1);
+
+ ximage->byte_order= MSBFirst;
+ data = (char *) malloc (img->width * img->height * depth_g / 8);
+ ximage->data = data;
+ if (ximage->data == NULL)
+ {
+ XDestroyImage (ximage);
+ ximage = NULL;
+ return (-1);
+ }
+ }
+ copy_rgb_to_zpixmap (ximage, img);
+ XPutImage(disp_g, window_g, gc, ximage, 0, 0,
+ 0, 0, ximage->width, ximage->height);
+
+ return (0);
+} /* int draw_window */
+
+#define ZOOM_SPEED 1.03
+
+static void zoom_in (double *fov)
+{
+ *fov = *fov / ZOOM_SPEED;
+ if (*fov < 10.5)
+ *fov = 10.5;
+} /* void zoom_in */
+
+static void zoom_out (double *fov)
+{
+ *fov = *fov * ZOOM_SPEED;
+ if (*fov > 165.0)
+ *fov = 165.0;
+} /* void zoom_out */
+
+int main( int argc, char** argv )
+{
+ XSizeHints hint;
+ unsigned long color_fg, color_bg;
+ int done;
+ static Atom proto_atom= None, delete_atom= None;
+
+ long event_mask;
+ unsigned int button_state = 0;
+
+ double fov = 70.0;
+ double yaw = 0.0;
+ double pitch = 0.0;
+
+ /* Detect mouse movement direction */
+ int pos_x_new = 0;
+ int pos_y_new = 0;
+ int pos_x_old;
+ int pos_y_old;
+
+ ui_image_t *pano;
+ ui_image_t *view;
+
+
+ // Set up display
+ disp_g = XOpenDisplay("");
+ screen_g = DefaultScreen(disp_g);
+ depth_g = DefaultDepth(disp_g, screen_g);
+
+ color_bg = WhitePixel(disp_g,screen_g);
+ color_fg = BlackPixel(disp_g,screen_g);
+
+ // Load panoramic image
+ if( argc < 2 )
+ {
+ PrintError("No image file supplied");
+ exit(0);
+ }
+
+ if( strcmp( argv[1], "-h" ) == 0 ) /* FIXME: Use getopt */
+ {
+ PrintError( "%s\n %s\nUsage: PTViewer Imagefile", "PTViewer", LONGVERSION );
+ exit(0);
+ }
+
+ pano = ui_create_file (argv[1]);
+ if (pano == NULL)
+ {
+ PrintError ("Unable to read pano file.");
+ exit (0);
+ }
+
+ printf ("Panorama `%s', %ux%u pixels, loaded.\n",
+ argv[1], pano->width, pano->height);
+
+ view = ui_create (DEF_VIEW_WIDTH, DEF_VIEW_HEIGHT); /* FIXME: Possibly chose another size */
+ if (view == NULL)
+ {
+ PrintError ("Unable to create view.");
+ exit (0);
+ }
+
+ hint.width = view->width;
+ hint.height = view->height;
+ hint.flags = PSize;
+
+ window_g = XCreateSimpleWindow(disp_g,
+ DefaultRootWindow(disp_g),
+ 0, 0, /* Position */
+ view->width, view->height,
+ 5,
+ color_fg, color_bg);
+
+ XSetStandardProperties(disp_g,
+ window_g,
+ text,
+ text,
+ None,
+ argv,
+ argc,
+ &hint);
+ gc = XCreateGC(disp_g,window_g,0,0);
+ XSetBackground(disp_g,gc,color_bg);
+ XSetForeground(disp_g,gc,color_fg);
+
+ event_mask = ButtonPressMask | ButtonReleaseMask | Button1MotionMask
+ | KeyPressMask | KeyReleaseMask | StructureNotifyMask
+ | EnterWindowMask | LeaveWindowMask| ExposureMask;
+
+ XSelectInput(disp_g, window_g, event_mask);
+ XMapRaised(disp_g,window_g);
+
+ proto_atom = XInternAtom(disp_g, "WM_PROTOCOLS", False);
+ delete_atom = XInternAtom(disp_g, "WM_DELETE_WINDOW", False);
+ if ((proto_atom != None) && (delete_atom != None))
+ XChangeProperty(disp_g, window_g, proto_atom, XA_ATOM, 32,
+ PropModeReplace, (unsigned char *)&delete_atom,
+ 1);
+ visual_g = DefaultVisual(disp_g, screen_g);
+
+ pl_extract_view (view, pano, pitch, yaw, fov);
+ draw_window (view);
+
+ done = 0;
+ while (done == 0)
+ {
+ int isChanged = 0;
+ XEvent event;
+
+ XMaskEvent (disp_g, event_mask, &event);
+
+ switch (event.type)
+ {
+ case Expose:
+ draw_window (view);
+ break;
+
+ case ConfigureNotify:
+ {
+ XConfigureEvent *cev = (XConfigureEvent *) &event;
+ printf ("XConfigureEvent received: width = %i; height = %i;\n",
+ cev->width, cev->height);
+ /* TODO, FIXME: re-create `view' and `ximage' with cev->width, cev->height */
}
- XFreeGC(disp,gc);
- XDestroyWindow(disp, win);
- XCloseDisplay(disp);
+ break;
- return (0);
-}
+ case KeyPress:
+ {
+ XKeyEvent *kev = (XKeyEvent *) &event;
+ KeySym ks = XLookupKeysym (kev, 0);
+
+ switch (ks)
+ {
+ case XK_Shift_L:
+ case XK_Shift_R:
+ zoom_in (&fov);
+ isChanged = 1;
+ break;
+
+ case XK_Control_L:
+ case XK_Control_R:
+ zoom_out (&fov);
+ isChanged = 1;
+ break;
+ }
+ }
+ break;
+
+ case KeyRelease:
+ printf ("Ignoring KeyRelease event.\n");
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ {
+ XButtonEvent *bev = (XButtonEvent *) &event;
+ button_state = bev->state;
+ }
+ break;
+
+ case MotionNotify:
+ {
+ XMotionEvent *mev = (XMotionEvent *) &event;
+
+ pos_x_old = pos_x_new;
+ pos_y_old = pos_y_new;
+ pos_x_new = mev->x;
+ pos_y_new = mev->y;
+
+ if (button_state & Button1Mask)
+ {
+ double yaw_diff = (pos_x_new - pos_x_old) / 24.0;
+ if (yaw_diff > 90.0)
+ yaw_diff = 90.0;
+ else if (yaw_diff < -90.0)
+ yaw_diff = -90.0;
+
+ yaw += yaw_diff;
+ if (yaw > 180.0)
+ yaw -= 360.0;
+ else if (yaw <= -180.0)
+ yaw += 360.0;
+
+ pitch -= (pos_y_new - pos_y_old) / 24.0;
+ if (pitch > 90.0)
+ pitch = 90.0;
+ else if (pitch < -90.0)
+ pitch = -90.0;
+
+ isChanged = 1;
+ }
+ }
+ break;
+
+ default:
+ printf ("Unhandled event type: 0x%02x\n",
+ event.type);
+ } /* switch (event.type) */
+
+ if (isChanged != 0)
+ {
+ pl_extract_view (view, pano, pitch, yaw, fov);
+ draw_window (view);
+ }
+ } /* while (done == 0) */
+
+ XFreeGC(disp_g,gc);
+ XDestroyWindow(disp_g, window_g);
+ XCloseDisplay(disp_g);
+
+ return (0);
+} /* int main */
im->dataSize = im->height * im->bytesPerLine;
}
-static int copy_rgb_to_zpixmap (XImage *dest, const Image *src)
-{
- uint32_t *src_data;
-
- uint32_t src_r;
- uint32_t src_g;
- uint32_t src_b;
-
- uint32_t dest_r;
- uint32_t dest_g;
- uint32_t dest_b;
- uint32_t dest_pixel_value;
-
- uint32_t x;
- uint32_t y;
- uint32_t pixel;
-
- uint32_t dest_r_maxval;
- uint32_t dest_g_maxval;
- uint32_t dest_b_maxval;
-
- uint32_t dest_r_offset;
- uint32_t dest_g_offset;
- uint32_t dest_b_offset;
-
- dest_r_offset = 0;
- dest_g_offset = 0;
- dest_b_offset = 0;
- dest_r_maxval = dest->red_mask;
- dest_g_maxval = dest->green_mask;
- dest_b_maxval = dest->blue_mask;
- for (x = 0; x < dest->depth; x++)
- {
- if ((dest_r_maxval & 0x01) == 0)
- {
- dest_r_offset++;
- dest_r_maxval >>= 1;
- }
- if ((dest_g_maxval & 0x01) == 0)
- {
- dest_g_offset++;
- dest_g_maxval >>= 1;
- }
- if ((dest_b_maxval & 0x01) == 0)
- {
- dest_b_offset++;
- dest_b_maxval >>= 1;
- }
- }
-
- src_data = (uint32_t *) *src->data;
-
- pixel = 0;
- for (y = 0; y < dest->height; y++)
- {
- for (x = 0; x < dest->width; x++, pixel++)
- {
- int32_t bytenum;
-
- src_r = (src_data[pixel] >> 8) & 0xFF;
- src_g = (src_data[pixel] >> 16) & 0xFF;
- src_b = (src_data[pixel] >> 24) & 0xFF;
-
- dest_r = dest_r_maxval * src_r / 0xFF;
- dest_g = dest_g_maxval * src_g / 0xFF;
- dest_b = dest_b_maxval * src_b / 0xFF;
-
- dest_pixel_value = 0
- | ((dest_r << dest_r_offset) & dest->red_mask)
- | ((dest_g << dest_g_offset) & dest->green_mask)
- | ((dest_b << dest_b_offset) & dest->blue_mask);
-
- for (bytenum = 0; bytenum < (dest->depth / 8); bytenum++)
- {
- dest->data[(pixel * dest->bits_per_pixel / 8) + bytenum] =
- (dest_pixel_value >> (dest->bits_per_pixel - (8 * (bytenum + 1)))) & 0xFF;
- }
- }
- }
-
- return (0);
-} /* int copy_rgb_to_zpixmap */
-
-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);
- }
-
- ximage->data = (char *) malloc (view.dataSize);
- if (ximage->data == NULL)
- return;
- memcpy (ximage->data, *(view.data), view.dataSize);
-
- copy_rgb_to_zpixmap (ximage, &view);
-
- XPutImage(disp, win, gc, ximage, 0, 0, 0, 0, view.width, view.height);
-
- free (ximage->data);
- ximage->data = NULL;
-}
-
-void DrawView(int InterPolator)
-{
- TrformStr Tr;
-
- Tr.interpolator = InterPolator;
-
- Tr.src = &pano;
- Tr.dest = &view;
-
- PV_ExtractStill( &Tr );
-
- view.format = 0;
- return;
-
-}
-
+/*
+ * vim: set shiftwidth=2 tabstop=8 softtabstop=2 :
+ */