/* IUP/OpenGL Capture using IM Uses IUP for user interface IM for image I/O and capture OpenGL for drawing Needs IUP: comctl32.lib iup.lib iupcontrols.lib iupgl.lib cd.lib cdiup.lib IM: im.lib im_capture.lib im_process.lib im_avi.lib strmiids.lib vfw32.lib OpenGL: opengl32.lib glu32.lib Libraries Available at: http://www.tecgraf.puc-rio.br/iup/ http://www.tecgraf.puc-rio.br/im/ http://www.tecgraf.puc-rio.br/cd/ The "strmiids.lib" may have to be updated to the version in: http://www.tecgraf.puc-rio.br/im/download/strmiids.zip Look for EDIT_HERE in the code to find where you should add your own code. You must first connect to a capture device, if the conection is successfull images will be captured from the device and shown on the left canvas. You may change capture device settings and control if the capture is live or not. Images can also be played from a video file. Frames will also be reproduced in idle function not considering the original frame rate. When you process the capture data, the result is always displayed in the right canvas. The objective is to preserve the original image to display 3D data on top of it. Version: 1.3 - Can save frame sequence in TIFF, GIF and AVI. GIF can only be used for the right image. arProcess API changed to include gldata. Dial replaced by another Valuator. 1.2 - New video file input. Changed some button image sizes to 23x23 in "iconlib.c". Fixed image type initialization of the save right video file. New save left video file. 1.1 - Full iconlib.c Authors: Antonio Scuri Marcelo Gattass Tecgraf/PUC-Rio - 2004 */ #ifdef WIN32 #include /* necessary because of the Microsoft OpenGL headers dependency */ #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NEW_ARPROCESS #ifdef NEW_ARPROCESS #include "ARProcess.h" #endif /* implemented in "iconlib.c" to load standard icon images into IUP */ void IconLibOpen(void); /* Process the image to detect known points: * image - input and output image ( in gray scale - IM_GRAY); * aux_image - an auxiliar image of the same type and size; * flags[3] - three interface flags; * angle - an angle controled by the user dial (the angle is zero when the user click&hold the control); * value - a real value controled by the user valuator [0,1]. * * Implemented in "arprocess.c". */ #ifndef NEW_ARPROCESS void arProcess(unsigned char* gl_data, imImage *image,imImage *aux_image, int *flags, double value1, double value2); #endif typedef struct _appData { imFile* file_cap; /* file input */ imVideoCapture* video_cap; /* live capture input */ int file_image_count, file_image_index; /* [0, image_count] or -1 = paused */ imImage* image; /* process buffer (right) */ imImage* aux_image; /* auxiliar process buffer, this is necessary for spatial filters. */ unsigned char* gl_data; /* opengl display buffer (left) */ imFile *videoright_file, /* video file to save frames of the image buffer */ *videoleft_file; int videoright_started, /* flag to indicate that at least one frame has been saved. */ videoleft_started; /* Global to help enable/disable items in the interface */ Ihandle *left_canvas, *right_canvas, *status_label, *config_but, *config_menu, *capture_but, *capture_menu; int user_flags[3]; double user_value1, user_value2; } appData; int user1_cb(Ihandle *self) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); if (app_data->user_flags[0] == 0) { IupMessage("Large Black Areas", "This will activate the detection\n" "of large black areas. The sequence is:\n" " Gaussian (sigma=1) - eliminate noise\n" " Threshold by Slice (0 - v1) - select black pixels\n" " Binary Opening (iter=v2) - eliminate small areas\n" " Binary Outline - detect borders"); app_data->user_flags[0] = 1; } else app_data->user_flags[0] = 0; return IUP_DEFAULT; } int user2_cb(Ihandle *self) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); if (app_data->user_flags[1] == 0) { app_data->user_flags[1] = 1; } else app_data->user_flags[1] = 0; return IUP_DEFAULT; } int user3_cb(Ihandle *self) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); if (app_data->user_flags[2] == 0) { app_data->user_flags[2] = 1; } else app_data->user_flags[2] = 0; return IUP_DEFAULT; } int user_val2_cb(Ihandle *self, double value) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); app_data->user_value2 = value; return IUP_DEFAULT; } int user_val1_cb(Ihandle *self, double value) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); app_data->user_value1 = value; return IUP_DEFAULT; } int appRepaint(Ihandle* self, int left) { #ifdef NEW_ARPROCESS unsigned char* data; #endif appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); IupGLMakeCurrent(self); /* activates this GL Canvas as the current drawing area. */ glClear(GL_COLOR_BUFFER_BIT); /* clears the back buffer */ if (app_data->image) { /* Draws the captured image at (0,0) */ glRasterPos2f(0.f, 0.f); #ifndef NEW_ARPROCESS if (left) glDrawPixels(app_data->image->width, app_data->image->height, GL_RGB, GL_UNSIGNED_BYTE, app_data->gl_data); else glDrawPixels(app_data->image->width, app_data->image->height, GL_LUMINANCE, GL_UNSIGNED_BYTE, app_data->image->data[0]); #else if (left) arRepaintLeftCanvas(); else arRepaintRightCanvas(); #endif } IupGLSwapBuffers(self); /* swap data from back buffer to front buffer */ return IUP_DEFAULT; } int app_left_repaint_cb(Ihandle* self) { return appRepaint(self, 1); } int app_right_repaint_cb(Ihandle* self) { return appRepaint(self, 0); } void appGLInit(int width, int height) { glClearColor(0., 0., 0., 1.0); /* window background */ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* data alignment is 1 */ glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D (0.0, (GLdouble)width, 0.0, (GLdouble)height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int app_resize_cb(Ihandle* self, int w, int h) { IupGLMakeCurrent(self); appGLInit(w, h); return IUP_DEFAULT; } void appSaveImage(imImage* image, unsigned char* gl_data) { int ret, error, format_count; char filename[1024] = ".\\*.*"; imFile* ifile; char* format_list[50]; if (!image) { IupMessage("Error", "Image not initialized."); return; } ret = IupGetFile(filename); /* get a file name */ if (ret == -1) return; /* get a file format */ imFormatList(format_list, &format_count); ret = IupListDialog(1,"Format Selection",format_count,format_list,1,20,10,NULL); if (ret == -1) return; ifile = imFileNew(filename, format_list[ret], &error); if (!ifile) { IupMessage("Error", "Error creating image file."); return; } if (gl_data) { /* save the raw image data */ imFileWriteImageInfo(ifile, image->width, image->height, IM_RGB|IM_PACKED, IM_BYTE); error = imFileWriteImageData(ifile, gl_data); } else error = imFileSaveImage(ifile, image); /* save the processed image */ if (error) IupMessage("Error", "Error writing image file."); imFileClose(ifile); } int app_leftimage_cb(Ihandle* self) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); appSaveImage(app_data->image, app_data->gl_data); return IUP_DEFAULT; } int app_rightimage_cb(Ihandle* self) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); appSaveImage(app_data->image, NULL); return IUP_DEFAULT; } void ConvertGLData2Luminance(unsigned char* gl_data, imImage* image) { int i; unsigned char* im_data = (unsigned char*)image->data[0]; for (i = 0; i < image->count; i++) { *im_data++ = (unsigned char)( 0.2999*(*gl_data) + 0.587*(*(gl_data+1)) + 0.114*(*(gl_data+2)) ); gl_data += 3; } } /* OpenGL does not supports palette based images, so convert to RGB */ /* this function can also be use for RGBA images */ void ConvertMapToGLData(unsigned char* data, int count, int depth, long* palette, int palette_count) { int c, i; unsigned char r[256], g[256], b[256]; unsigned char* src_data = data + count-1; unsigned char* dst_data = data + depth*(count-1); for (c = 0; c < palette_count; c++) imColorDecode(&r[c], &g[c], &b[c], palette[c]); for (i = 0; i < count; i++) { int index = *src_data; *dst_data = r[index]; *(dst_data+1) = g[index]; *(dst_data+2) = b[index]; dst_data -= depth; src_data--; } } void appVideoClose(imFile* *video_file, int *video_started) { imFileClose(*video_file); IupMessage("Message", "Video file closed."); *video_file = NULL; *video_started = 0; } void appVideoFrameSave(imFile* *video_file, int *video_started, int width, int height, int color_mode, unsigned char* data) { /* save the captured video in a file */ int error = imFileWriteImageInfo(*video_file, width, height, color_mode, IM_BYTE); if (error == IM_ERR_NONE) { imFileWriteImageData(*video_file, data); *video_started = 1; /* at least one frame has been written */ } else { IupMessage("Error", "Error writing video frame."); appVideoClose(video_file, video_started); } } int idle_cb(void) { int process = 0; appData* app_data = (appData*)IupGetGlobal("APP_DATA"); if (app_data->file_cap) { int width = 0, height = 0, file_color_mode; imFileReadImageInfo(app_data->file_cap, app_data->file_image_index, &width, &height, &file_color_mode, NULL); if (width != app_data->image->width || height != app_data->image->height) return IUP_DEFAULT; imFileReadImageData(app_data->file_cap, app_data->gl_data, 1, IM_PACKED); app_data->file_image_index++; if (file_color_mode & IM_MAP || file_color_mode & IM_GRAY || file_color_mode & IM_BINARY) { long palette[256]; int palette_count; imFileGetPalette(app_data->file_cap, palette, &palette_count); ConvertMapToGLData(app_data->gl_data, width*height, 3, palette, palette_count); } if (app_data->file_image_index == app_data->file_image_count) app_data->file_image_index = 0; process = 1; } else if (app_data->video_cap && imVideoCaptureLive(app_data->video_cap, -1)) { /* retrieve a frame available at the capture buffer. normally this will be a new frame, except when a timeout occours. */ imVideoCaptureFrame(app_data->video_cap, app_data->gl_data, IM_RGB|IM_PACKED, 1000); process = 1; } if (app_data->videoleft_file) { /* save the captured video in a file */ appVideoFrameSave(&app_data->videoleft_file, &app_data->videoleft_started, app_data->image->width, app_data->image->height, IM_RGB|IM_PACKED, app_data->gl_data); } if (process) { ConvertGLData2Luminance(app_data->gl_data, app_data->image); #ifdef NEW_ARPROCESS arFrameProcess(app_data->gl_data, 0, 0.0, 0.0); #else arProcess(app_data->gl_data, app_data->image, app_data->aux_image, app_data->user_flags, app_data->user_value1, app_data->user_value2); #endif if (app_data->videoright_file) { /* save the processed video in a file */ appVideoFrameSave(&app_data->videoright_file, &app_data->videoright_started, app_data->image->width, app_data->image->height, IM_GRAY, app_data->image->data[0]); } /* force a repaint */ app_left_repaint_cb(app_data->left_canvas); app_right_repaint_cb(app_data->right_canvas); if (1) { /* estimate the number of frames per second */ static int frame_count = 1; static int start_time = 0; int current_time = clock(); if (current_time - start_time > CLOCKS_PER_SEC) { IupSetfAttribute(app_data->status_label, "TITLE", "fps: %3.2f flags:%1d%1d%1d value1: %.2lf value2: %.2lf", (double)(frame_count*CLOCKS_PER_SEC)/(double)(current_time-start_time), app_data->user_flags[0], app_data->user_flags[1], app_data->user_flags[2], app_data->user_value1, app_data->user_value2); frame_count = 1; start_time = current_time; } frame_count++; } } return IUP_DEFAULT; } void appUpdateInterface(appData* app_data) { if ((!app_data->video_cap || imVideoCaptureConnect(app_data->video_cap, -1) == -1) && !app_data->file_cap) { /* if no input, disable everything */ IupSetAttribute(app_data->config_but,"ACTIVE","NO"); IupSetAttribute(app_data->capture_but,"ACTIVE","NO"); IupSetAttribute(app_data->config_menu,"ACTIVE","NO"); IupSetAttribute(app_data->capture_menu,"ACTIVE","NO"); return; } /* if any input, enable almost everything */ IupSetAttribute(app_data->capture_but,"ACTIVE","YES"); IupSetAttribute(app_data->capture_menu,"ACTIVE","YES"); /* enable config only when capture device connected */ if (app_data->video_cap && imVideoCaptureConnect(app_data->video_cap, -1) != -1) { IupSetAttribute(app_data->config_but,"ACTIVE","YES"); IupSetAttribute(app_data->config_menu,"ACTIVE","YES"); } else { IupSetAttribute(app_data->config_but,"ACTIVE","NO"); IupSetAttribute(app_data->config_menu,"ACTIVE","NO"); } /* if live set the idle and update the start/stop toggle */ if ((app_data->video_cap && imVideoCaptureLive(app_data->video_cap, -1)) || (app_data->file_cap && app_data->file_image_index != -1)) { IupSetFunction(IUP_IDLE_ACTION, (Icallback)idle_cb); IupSetAttribute(app_data->capture_but,"VALUE","ON"); } else { IupSetFunction(IUP_IDLE_ACTION, (Icallback)NULL); IupSetAttribute(app_data->capture_but,"VALUE","OFF"); } } void appResetImageData(appData* app_data) { int width = 0, height = 0; /* retrieve the image size */ if (app_data->file_cap) imFileReadImageInfo(app_data->file_cap, 0, &width, &height, NULL, NULL); else if (app_data->video_cap) imVideoCaptureGetImageSize(app_data->video_cap, &width, &height); if (width == 0 || height == 0) { IupMessage("Error!", "Invalid image size."); return; } #ifdef NEW_ARPROCESS arInit(width, height); #endif /* alocates the buffers */ if (app_data->gl_data) free(app_data->gl_data); app_data->gl_data = malloc(width*height*3); if (app_data->image) imImageDestroy(app_data->image); if (app_data->aux_image) imImageDestroy(app_data->aux_image); app_data->image = imImageCreate(width, height, IM_GRAY, IM_BYTE); app_data->aux_image = imImageClone(app_data->image); if (app_data->videoright_file && app_data->videoright_started) { /* if the video file is already started it should be stopped */ appVideoClose(&app_data->videoright_file, &app_data->videoright_started); } if (app_data->videoleft_file && app_data->videoleft_started) { /* if the video file is already started it should be stopped */ appVideoClose(&app_data->videoleft_file, &app_data->videoleft_started); } } int app_capture_cb(Ihandle *self) { int paused = 0; appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); if (app_data->file_cap) { if (app_data->file_image_index == -1) app_data->file_image_index = 0; else { app_data->file_image_index = -1; paused = 1; } } else if (app_data->video_cap && imVideoCaptureConnect(app_data->video_cap, -1) != -1) { int live = !imVideoCaptureLive(app_data->video_cap, -1); /* invert live state */ if (!imVideoCaptureLive(app_data->video_cap, live)) IupMessage("Error!", "Could not change live state!"); if (!live) paused = 1; } if (paused) { if (app_data->videoright_file && app_data->videoright_started) { /* if the video file is already started it should be stopped */ appVideoClose(&app_data->videoright_file, &app_data->videoright_started); } if (app_data->videoleft_file && app_data->videoleft_started) { /* if the video file is already started it should be stopped */ appVideoClose(&app_data->videoleft_file, &app_data->videoleft_started); } } appUpdateInterface(app_data); return IUP_DEFAULT; } int app_connect_cb(Ihandle *self) { int device = 0; appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); /* get a capture device */ int cap_count = imVideoCaptureDeviceCount(); if (cap_count > 1) { int i, ret; char* cap_list[50]; for (i = 0; i < cap_count; i++) cap_list[i] = (char*)imVideoCaptureDeviceDesc(i); ret = IupListDialog(1,"Capture Device Selection",cap_count,cap_list,1,40,10,NULL); if (ret == -1) return IUP_DEFAULT; device = ret; } if (!imVideoCaptureConnect(app_data->video_cap, device)) { IupMessage("Error!", "Could not connect to the capture device."); appUpdateInterface(app_data); return IUP_DEFAULT; } /* if input file oppened, close it */ if (app_data->file_cap) { imFileClose(app_data->file_cap); app_data->file_cap = NULL; } appResetImageData(app_data); return app_capture_cb(self); } int app_configure_cb(Ihandle *self) { int dlg = 0, live; appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); /* get a configuration dialog */ int dlg_count = imVideoCaptureDialogCount(app_data->video_cap); if (dlg_count > 1) { int i, ret; char* dlg_list[50]; for (i = 0; i < dlg_count; i++) dlg_list[i] = (char*)imVideoCaptureDialogDesc(app_data->video_cap, i); ret = IupListDialog(1,"Configuration Dialog Selection",dlg_count,dlg_list,1,20,10,NULL); if (ret == -1) return IUP_DEFAULT; dlg = ret; } live = imVideoCaptureLive(app_data->video_cap, -1); if (live) imVideoCaptureLive(app_data->video_cap, 0); /* deactivate the capture before calling the dialog */ if (!imVideoCaptureShowDialog(app_data->video_cap, dlg, IupGetAttribute((Ihandle*)IupGetGlobal("app_dialog"), "WID"))) { IupMessage("Error!", "Could not set configuration."); appUpdateInterface(app_data); return IUP_DEFAULT; } /* reset data because the dialogs can change the image size */ appResetImageData(app_data); if (live) imVideoCaptureLive(app_data->video_cap, 1); /* restore the live state */ appUpdateInterface(app_data); return IUP_DEFAULT; } int app_open_cb(Ihandle* self) { int ret, error; appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); char videoin_filename[1024] = ".\\*.*"; /* if input file oppened, close it */ if (app_data->file_cap) { imFileClose(app_data->file_cap); app_data->file_cap = NULL; } /* get a file name */ ret = IupGetFile(videoin_filename); if (ret == -1) return IUP_DEFAULT; app_data->file_cap = imFileOpen(videoin_filename, &error); if (!app_data->file_cap) { IupMessage("Error", "Error reading video file."); appUpdateInterface(app_data); return IUP_DEFAULT; } imFileGetInfo(app_data->file_cap, NULL, NULL, &app_data->file_image_count); app_data->file_image_index = -1; /* start as paused, to toggle in app_capture_cb */ /* if connected, disconnect */ if (app_data->video_cap) imVideoCaptureDisconnect(app_data->video_cap); appResetImageData(app_data); return app_capture_cb(self); } int appSaveVideo(imFile* *video_file, int *video_started) { int ret; char filename[1024] = ".\\*.*"; /* if output file oppened, close it */ if (*video_file) { appVideoClose(video_file, video_started); return IUP_DEFAULT; } /* get a file name */ ret = IupGetFile(filename); if (ret != -1) { int error, ret; char* format_list[3] = { "TIFF", "GIF", /* this can only be used for the right image */ "AVI", }; ret = IupListDialog(1,"Format Selection",3,format_list,1,20,10,NULL); if (ret == -1) return IUP_DEFAULT; *video_file = imFileNew(filename, format_list[ret], &error); if (!(*video_file)) IupMessage("Error", "Error creating video file."); } return IUP_DEFAULT; } int app_leftvideo_cb(Ihandle* self) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); return appSaveVideo(&app_data->videoleft_file, &app_data->videoleft_started); } int app_rightvideo_cb(Ihandle* self) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); return appSaveVideo(&app_data->videoright_file, &app_data->videoright_started); } int app_exit_cb(Ihandle *self) { appData* app_data = (appData*)IupGetAttribute(self, "APP_DATA"); /* destroy buffers, disconnect devices, close files */ if (app_data->videoright_file) imFileClose(app_data->videoright_file); if (app_data->videoleft_file) imFileClose(app_data->videoleft_file); if (app_data->file_cap) imFileClose(app_data->file_cap); if (app_data->video_cap) imVideoCaptureDestroy(app_data->video_cap); if (app_data->image) imImageDestroy(app_data->image); if (app_data->aux_image) imImageDestroy(app_data->aux_image); if (app_data->gl_data) free(app_data->gl_data); free(app_data); #ifdef NEW_ARPROCESS arEnd(); #endif return IUP_CLOSE; } int app_about_cb(Ihandle *self) { IupMessagef("About", "IUPGLCapture 1.3\n" "Tecgraf/PUC-Rio\n" " ---------------- \n" "IUP Version %s\n" "IM Version %s\n" " ---------------- \n" "OpenGL:\n" " Vendor: %s\n" " Renderer: %s\n" " Version: %s\n" , IUP_RELEASE_VERSION, IM_VERSION, glGetString(GL_VENDOR),glGetString(GL_RENDERER),glGetString(GL_VERSION)); return IUP_DEFAULT; } void mainMenuCreate(appData* app_data) { Ihandle* file_menu = IupMenu( IupItem( "Save Left Video...", "app_leftvideo_cb"), IupItem( "Save Right Video...", "app_rightvideo_cb"), IupSeparator(), IupItem( "Save Left Image...", "app_leftimage_cb"), IupItem( "Save Right Image...", "app_rightimage_cb"), IupSeparator(), IupItem( "Exit", "app_exit_cb"), NULL ); Ihandle* capture_menu = IupMenu( IupItem( "Open Input Video File...", "app_open_cb"), IupSeparator(), IupItem( "Connect Input Device...", "app_connect_cb"), app_data->config_menu = IupItem( "Configure Device...", "app_configure_cb"), IupSeparator(), app_data->capture_menu = IupItem( "Start/Stop", "app_capture_cb"), NULL ); Ihandle* process_menu = IupMenu( IupItem( "user1", "user1_cb"), /* EDIT_HERE */ IupItem( "user2", "user2_cb"), IupItem( "user3", "user3_cb"), NULL ); Ihandle* help_menu = IupMenu( IupItem( "About...", "app_about_cb"), NULL ); Ihandle* menu = IupMenu( IupSubmenu("File", file_menu), IupSubmenu("Capture", capture_menu), IupSubmenu("Process", process_menu), IupSubmenu("Help", help_menu), NULL ); IupSetAttribute(app_data->config_menu,"ACTIVE","NO"); IupSetAttribute(app_data->capture_menu,"ACTIVE","NO"); /* this will be used by the dialog */ IupSetHandle("app_menu", menu); /* associate callbacks with names */ IupSetFunction("app_exit_cb", app_exit_cb); IupSetFunction("app_about_cb", app_about_cb); IupSetFunction("app_leftvideo_cb", app_leftvideo_cb); IupSetFunction("app_rightvideo_cb", app_rightvideo_cb); IupSetFunction("app_leftimage_cb", app_leftimage_cb); IupSetFunction("app_rightimage_cb", app_rightimage_cb); } Ihandle* mainToolbarCreate(appData* app_data) { Ihandle *toolbar, *val1, *val2, *connect, *open, *configure, *capture; /* creates the toolbar and its buttons */ open = IupButton("", "app_open_cb"); IupSetAttribute(open,"TIP","Opens an input video file."); IupSetAttribute(open,"IMAGE","icon_lib_open"); IupSetFunction("app_open_cb", (Icallback)app_open_cb); connect = IupButton("", "app_connect_cb"); IupSetAttribute(connect,"TIP","Connects to a capture device."); IupSetAttribute(connect,"IMAGE","icon_lib_connect"); IupSetFunction("app_connect_cb", (Icallback)app_connect_cb); configure = IupButton("", "app_configure_cb"); IupSetAttribute(configure,"TIP","Connects to a capture device."); IupSetAttribute(configure,"IMAGE","icon_lib_configure"); IupSetAttribute(configure,"IMINACTIVE","icon_lib_configure_inactive"); IupSetAttribute(configure,"ACTIVE","NO"); IupSetFunction("app_configure_cb", (Icallback)app_configure_cb); app_data->config_but = configure; capture = IupToggle("", "app_capture_cb"); IupSetAttribute(capture,"TIP","Connects to a capture device."); IupSetAttribute(capture,"IMAGE","icon_lib_capture"); IupSetAttribute(capture,"IMINACTIVE","icon_lib_capture_inactive"); IupSetAttribute(capture,"ACTIVE","NO"); IupSetFunction("app_capture_cb", (Icallback)app_capture_cb); app_data->capture_but = capture; /* these are user controls */ val2 = IupVal("HORIZONTAL"); IupSetAttribute(val2, "MOUSEMOVE_CB", "user_val2_cb"); IupSetFunction("user_val2_cb", (Icallback)user_val2_cb); val1 = IupVal("HORIZONTAL"); IupSetAttribute(val1, "MOUSEMOVE_CB", "user_val1_cb"); IupSetFunction("user_val1_cb", (Icallback)user_val1_cb); toolbar = IupHbox( open, connect, configure, capture, IupFill(), IupButton("user1", "user1_cb"), /* EDIT_HERE */ IupButton("user2", "user2_cb"), IupButton("user3", "user3_cb"), val1, val2, NULL); IupSetAttribute(toolbar, "ALIGNMENT", "ACENTER"); IupSetAttribute(toolbar, "MARGIN", "2x2"); IupSetFunction("user1_cb", (Icallback)user1_cb); /* EDIT_HERE */ IupSetFunction("user2_cb", (Icallback)user2_cb); IupSetFunction("user3_cb", (Icallback)user3_cb); return toolbar; } void mainDialogCreate(void) { appData* app_data; Ihandle *dialog, *statusbar, *toolbar, *box, *label, *left_canvas, *right_canvas; /* initialize application context */ app_data = malloc(sizeof(appData)); memset(app_data, 0, sizeof(appData)); app_data->video_cap = imVideoCaptureCreate(); if (!app_data->video_cap) IupMessage("Error!", "No Capture Device available!"); /* initialize interface */ toolbar = mainToolbarCreate(app_data); /* left canvas for the captured image and the final results (3D data) */ /* right canvas for intermediate results */ left_canvas = IupGLCanvas("app_left_repaint_cb"); IupSetAttribute(left_canvas, "BORDER", "NO"); IupSetAttribute(left_canvas, "BUFFER", "DOUBLE"); /* use double buffer */ IupSetAttribute(left_canvas, "RESIZE_CB", "app_resize_cb"); /* configure the resize callback */ app_data->left_canvas = left_canvas; right_canvas = IupGLCanvas("app_right_repaint_cb"); IupSetAttribute(right_canvas, "BORDER", "NO"); IupSetAttribute(right_canvas, "BUFFER", "DOUBLE"); /* use double buffer */ IupSetAttribute(right_canvas, "RESIZE_CB", "app_resize_cb"); /* configure the resize callback */ app_data->right_canvas = right_canvas; IupSetFunction("app_resize_cb", (Icallback)app_resize_cb); IupSetFunction("app_left_repaint_cb", (Icallback)app_left_repaint_cb); IupSetFunction("app_right_repaint_cb", (Icallback)app_right_repaint_cb); /* the status bar is just a label to put some usefull information in run time */ label = IupLabel("status"); IupSetAttribute(label, "EXPAND", "HORIZONTAL"); IupSetAttribute(label, "FONT", "COURIER_NORMAL_10"); statusbar = IupSetAttributes(IupHbox( IupFrame(IupHbox(label, NULL)), NULL), "MARGIN=5x5"); app_data->status_label = label; /* this is the most external box that puts together the toolbar, the two canvas and the status bar */ box = IupVbox( toolbar, IupSetAttributes(IupHbox( left_canvas, right_canvas, NULL), "GAP=5"), statusbar, NULL); /* create the dialog and set its attributes */ mainMenuCreate(app_data); dialog = IupDialog(box); IupSetAttribute(dialog, "MENU", "app_menu"); /* configure the menu */ IupSetAttribute(dialog, "CLOSE_CB", "app_exit_cb"); IupSetAttribute(dialog, "TITLE", "IUPGLCapture"); IupSetAttribute(dialog, "RASTERSIZE", "680x380"); /* initial size */ IupSetAttribute(dialog, "SHRINK", "YES"); IupSetHandle("app_dialog", dialog); IupSetGlobal(IUP_PARENTDIALOG, "app_dialog"); /* to be used by the idle callback */ IupSetAttribute(dialog, "APP_DATA", (char*)app_data); IupSetGlobal("APP_DATA", (char*)app_data); IupShowXY(dialog, IUP_CENTER, IUP_CENTER); } int main(int argc, char* argv[]) { /* IUP initialization */ IupOpen(); IupControlsOpen(); IupGLCanvasOpen(); IconLibOpen(); /* Initialize the AVI format */ imFormatRegisterAVI(); /* Create and show the main dialog */ mainDialogCreate(); /* IUP event loop */ IupMainLoop(); /* IUP closing */ IupControlsClose(); IupClose(); return 0; }