1
/*M///////////////////////////////////////////////////////////////////////////////////////
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
10
// Intel License Agreement
11
// For Open Source Computer Vision Library
13
// Copyright (C) 2000, Intel Corporation, all rights reserved.
14
// Third party copyrights are property of their respective owners.
16
// Redistribution and use in source and binary forms, with or without modification,
17
// are permitted provided that the following conditions are met:
19
// * Redistribution's of source code must retain the above copyright notice,
20
// this list of conditions and the following disclaimer.
22
// * Redistribution's in binary form must reproduce the above copyright notice,
23
// this list of conditions and the following disclaimer in the documentation
24
// and/or other materials provided with the distribution.
26
// * The name of Intel Corporation may not be used to endorse or promote products
27
// derived from this software without specific prior written permission.
29
// This software is provided by the copyright holders and contributors "as is" and
30
// any express or implied warranties, including, but not limited to, the implied
31
// warranties of merchantability and fitness for a particular purpose are disclaimed.
32
// In no event shall the Intel Corporation or contributors be liable for any direct,
33
// indirect, incidental, special, exemplary, or consequential damages
34
// (including, but not limited to, procurement of substitute goods or services;
35
// loss of use, data, or profits; or business interruption) however caused
36
// and on any theory of liability, whether in contract, strict liability,
37
// or tort (including negligence or otherwise) arising in any way out of
38
// the use of this software, even if advised of the possibility of such damage.
42
#include "precomp.hpp"
43
#include "opencv2/imgproc.hpp"
47
#if defined (HAVE_GTK)
50
#include <gdk/gdkkeysyms.h>
51
#include <gdk-pixbuf/gdk-pixbuf.h>
54
#if (GTK_MAJOR_VERSION == 3)
56
#endif //GTK_MAJOR_VERSION >= 3
59
#include <gtk/gtkgl.h>
64
// TODO Fix the initial window size when flags=0. Right now the initial window is by default
65
// 320x240 size. A better default would be actual size of the image. Problem
66
// is determining desired window size with trackbars while still allowing resizing.
68
// Gnome Totem source may be of use here, see bacon_video_widget_set_scale_ratio
69
// in totem/src/backend/bacon-video-widget-xine.c
71
////////////////////////////////////////////////////////////
72
// CvImageWidget GTK Widget Public API
73
////////////////////////////////////////////////////////////
74
typedef struct _CvImageWidget CvImageWidget;
75
typedef struct _CvImageWidgetClass CvImageWidgetClass;
77
struct _CvImageWidget {
79
CvMat * original_image;
84
struct _CvImageWidgetClass
86
GtkWidgetClass parent_class;
90
/** Allocate new image viewer widget */
91
GtkWidget* cvImageWidgetNew (int flags);
93
/** Set the image to display in the widget */
94
void cvImageWidgetSetImage(CvImageWidget * widget, const CvArr *arr);
96
// standard GTK object macros
97
#define CV_IMAGE_WIDGET(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, cvImageWidget_get_type (), CvImageWidget)
98
#define CV_IMAGE_WIDGET_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, cvImageWidget_get_type (), CvImageWidgetClass)
99
#define CV_IS_IMAGE_WIDGET(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, cvImageWidget_get_type ())
101
/////////////////////////////////////////////////////////////////////////////
102
// Private API ////////////////////////////////////////////////////////
103
/////////////////////////////////////////////////////////////////////////////
104
GType cvImageWidget_get_type (void);
106
static GtkWidgetClass * parent_class = NULL;
108
// flag to help size initial window
109
#define CV_WINDOW_NO_IMAGE 2
111
void cvImageWidgetSetImage(CvImageWidget * widget, const CvArr *arr){
115
//printf("cvImageWidgetSetImage\n");
117
if( CV_IS_IMAGE_HDR( arr ))
118
origin = ((IplImage*)arr)->origin;
120
mat = cvGetMat(arr, &stub);
122
if(widget->original_image && !CV_ARE_SIZES_EQ(mat, widget->original_image)){
123
cvReleaseMat( &widget->original_image );
125
if(!widget->original_image){
126
widget->original_image = cvCreateMat( mat->rows, mat->cols, CV_8UC3 );
127
gtk_widget_queue_resize( GTK_WIDGET( widget ) );
129
cvConvertImage( mat, widget->original_image,
130
(origin != 0 ? CV_CVTIMG_FLIP : 0) + CV_CVTIMG_SWAP_RB );
131
if(widget->scaled_image){
132
cvResize( widget->original_image, widget->scaled_image, CV_INTER_AREA );
135
// window does not refresh without this
136
gtk_widget_queue_draw( GTK_WIDGET(widget) );
140
cvImageWidgetNew (int flags)
142
CvImageWidget *image_widget;
144
image_widget = CV_IMAGE_WIDGET( gtk_widget_new (cvImageWidget_get_type (), NULL) );
145
image_widget->original_image = 0;
146
image_widget->scaled_image = 0;
147
image_widget->flags = flags | CV_WINDOW_NO_IMAGE;
149
return GTK_WIDGET (image_widget);
153
cvImageWidget_realize (GtkWidget *widget)
155
GdkWindowAttr attributes;
156
gint attributes_mask;
158
#if defined(GTK_VERSION3)
159
GtkAllocation allocation;
160
gtk_widget_get_allocation(widget, &allocation);
161
#endif //GTK_VERSION3
163
//printf("cvImageWidget_realize\n");
164
g_return_if_fail (widget != NULL);
165
g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
167
gtk_widget_set_realized(widget, TRUE);
169
#if defined(GTK_VERSION3)
170
attributes.x = allocation.x;
171
attributes.y = allocation.y;
172
attributes.width = allocation.width;
173
attributes.height = allocation.height;
175
attributes.x = widget->allocation.x;
176
attributes.y = widget->allocation.y;
177
attributes.width = widget->allocation.width;
178
attributes.height = widget->allocation.height;
179
#endif //GTK_VERSION3
181
attributes.wclass = GDK_INPUT_OUTPUT;
182
attributes.window_type = GDK_WINDOW_CHILD;
183
attributes.event_mask = gtk_widget_get_events (widget) |
184
GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
185
GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK;
186
attributes.visual = gtk_widget_get_visual (widget);
188
#if defined(GTK_VERSION3)
189
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
190
gtk_widget_set_window(
193
gtk_widget_get_parent_window(widget),
199
gtk_widget_set_style(
202
gtk_widget_get_style(widget),
203
gtk_widget_get_window(widget)
207
gdk_window_set_user_data (
208
gtk_widget_get_window(widget),
212
gtk_style_set_background (
213
gtk_widget_get_style(widget),
214
gtk_widget_get_window(widget),
218
// The following lines are included to prevent breaking
219
// compatibility with older Gtk2 (<gtk+-2.18) libraries.
220
attributes.colormap = gtk_widget_get_colormap (widget);
221
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
222
widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
224
widget->style = gtk_style_attach (widget->style, widget->window);
225
gdk_window_set_user_data (widget->window, widget);
227
gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
228
#endif // GTK_VERSION3
231
static CvSize cvImageWidget_calc_size( int im_width, int im_height, int max_width, int max_height ){
232
float aspect = (float)im_width/(float)im_height;
233
float max_aspect = (float)max_width/(float)max_height;
234
if(aspect > max_aspect){
235
return cvSize( max_width, cvRound(max_width/aspect) );
237
return cvSize( cvRound(max_height*aspect), max_height );
240
#if defined (GTK_VERSION3)
242
cvImageWidget_get_preferred_width (GtkWidget *widget, gint *minimal_width, gint *natural_width)
244
g_return_if_fail (widget != NULL);
245
g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
246
CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
248
if(image_widget->original_image != NULL) {
249
*minimal_width = (image_widget->flags & CV_WINDOW_AUTOSIZE) != CV_WINDOW_AUTOSIZE ?
250
gdk_window_get_width(gtk_widget_get_window(widget)) : image_widget->original_image->cols;
253
*minimal_width = 320;
256
if(image_widget->scaled_image != NULL) {
257
*natural_width = *minimal_width < image_widget->scaled_image->cols ?
258
image_widget->scaled_image->cols : *minimal_width;
261
*natural_width = *minimal_width;
266
cvImageWidget_get_preferred_height (GtkWidget *widget, gint *minimal_height, gint *natural_height)
268
g_return_if_fail (widget != NULL);
269
g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
270
CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
272
if(image_widget->original_image != NULL) {
273
*minimal_height = (image_widget->flags & CV_WINDOW_AUTOSIZE) != CV_WINDOW_AUTOSIZE ?
274
gdk_window_get_height(gtk_widget_get_window(widget)) : image_widget->original_image->rows;
277
*minimal_height = 240;
280
if(image_widget->scaled_image != NULL) {
281
*natural_height = *minimal_height < image_widget->scaled_image->rows ?
282
image_widget->scaled_image->cols : *minimal_height;
285
*natural_height = *minimal_height;
291
cvImageWidget_size_request (GtkWidget *widget,
292
GtkRequisition *requisition)
294
CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
296
//printf("cvImageWidget_size_request ");
297
// the case the first time cvShowImage called or when AUTOSIZE
298
if( image_widget->original_image &&
299
((image_widget->flags & CV_WINDOW_AUTOSIZE) ||
300
(image_widget->flags & CV_WINDOW_NO_IMAGE)))
302
//printf("original ");
303
requisition->width = image_widget->original_image->cols;
304
requisition->height = image_widget->original_image->rows;
307
else if(image_widget->scaled_image){
309
requisition->width = image_widget->scaled_image->cols;
310
requisition->height = image_widget->scaled_image->rows;
312
// the case before cvShowImage called
314
//printf("default ");
315
requisition->width = 320;
316
requisition->height = 240;
318
//printf("%d %d\n",requisition->width, requisition->height);
320
#endif //GTK_VERSION3
322
static void cvImageWidget_set_size(GtkWidget * widget, int max_width, int max_height){
323
CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
325
//printf("cvImageWidget_set_size %d %d\n", max_width, max_height);
327
// don't allow to set the size
328
if(image_widget->flags & CV_WINDOW_AUTOSIZE) return;
329
if(!image_widget->original_image) return;
331
CvSize scaled_image_size = cvImageWidget_calc_size( image_widget->original_image->cols,
332
image_widget->original_image->rows, max_width, max_height );
334
if( image_widget->scaled_image &&
335
( image_widget->scaled_image->cols != scaled_image_size.width ||
336
image_widget->scaled_image->rows != scaled_image_size.height ))
338
cvReleaseMat( &image_widget->scaled_image );
340
if( !image_widget->scaled_image ){
341
image_widget->scaled_image = cvCreateMat( scaled_image_size.height, scaled_image_size.width, CV_8UC3 );
345
assert( image_widget->scaled_image );
349
cvImageWidget_size_allocate (GtkWidget *widget,
350
GtkAllocation *allocation)
352
CvImageWidget *image_widget;
354
//printf("cvImageWidget_size_allocate\n");
355
g_return_if_fail (widget != NULL);
356
g_return_if_fail (CV_IS_IMAGE_WIDGET (widget));
357
g_return_if_fail (allocation != NULL);
359
#if defined (GTK_VERSION3)
360
gtk_widget_set_allocation(widget, allocation);
362
widget->allocation = *allocation;
363
#endif //GTK_VERSION3
364
image_widget = CV_IMAGE_WIDGET (widget);
367
if( (image_widget->flags & CV_WINDOW_AUTOSIZE)==0 && image_widget->original_image ){
368
// (re) allocated scaled image
369
if( image_widget->flags & CV_WINDOW_NO_IMAGE ){
370
cvImageWidget_set_size( widget, image_widget->original_image->cols,
371
image_widget->original_image->rows);
374
cvImageWidget_set_size( widget, allocation->width, allocation->height );
376
cvResize( image_widget->original_image, image_widget->scaled_image, CV_INTER_AREA );
379
if (gtk_widget_get_realized (widget))
381
image_widget = CV_IMAGE_WIDGET (widget);
383
if( image_widget->original_image &&
384
((image_widget->flags & CV_WINDOW_AUTOSIZE) ||
385
(image_widget->flags & CV_WINDOW_NO_IMAGE)) )
387
#if defined (GTK_VERSION3)
388
allocation->width = image_widget->original_image->cols;
389
allocation->height = image_widget->original_image->rows;
390
gtk_widget_set_allocation(widget, allocation);
392
widget->allocation.width = image_widget->original_image->cols;
393
widget->allocation.height = image_widget->original_image->rows;
394
#endif //GTK_VERSION3
395
gdk_window_move_resize( gtk_widget_get_window(widget),
396
allocation->x, allocation->y,
397
image_widget->original_image->cols, image_widget->original_image->rows );
398
if(image_widget->flags & CV_WINDOW_NO_IMAGE){
399
image_widget->flags &= ~CV_WINDOW_NO_IMAGE;
400
gtk_widget_queue_resize( GTK_WIDGET(widget) );
404
gdk_window_move_resize (gtk_widget_get_window(widget),
405
allocation->x, allocation->y,
406
allocation->width, allocation->height );
411
#if defined (GTK_VERSION3)
413
cvImageWidget_destroy (GtkWidget *object)
416
cvImageWidget_destroy (GtkObject *object)
417
#endif //GTK_VERSION3
419
CvImageWidget *image_widget;
421
g_return_if_fail (object != NULL);
422
g_return_if_fail (CV_IS_IMAGE_WIDGET (object));
424
image_widget = CV_IMAGE_WIDGET (object);
426
cvReleaseMat( &image_widget->scaled_image );
427
cvReleaseMat( &image_widget->original_image );
429
#if defined (GTK_VERSION3)
430
if (GTK_WIDGET_CLASS (parent_class)->destroy)
431
(* GTK_WIDGET_CLASS (parent_class)->destroy) (object);
433
if (GTK_OBJECT_CLASS (parent_class)->destroy)
434
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
435
#endif //GTK_VERSION3
438
static void cvImageWidget_class_init (CvImageWidgetClass * klass)
440
#if defined (GTK_VERSION3)
441
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
443
GtkObjectClass *object_class;
444
GtkWidgetClass *widget_class;
446
object_class = (GtkObjectClass*) klass;
447
widget_class = (GtkWidgetClass*) klass;
448
#endif //GTK_VERSION3
450
parent_class = GTK_WIDGET_CLASS( g_type_class_peek (gtk_widget_get_type ()) );
452
#if defined (GTK_VERSION3)
453
widget_class->destroy = cvImageWidget_destroy;
454
widget_class->get_preferred_width = cvImageWidget_get_preferred_width;
455
widget_class->get_preferred_height = cvImageWidget_get_preferred_height;
457
object_class->destroy = cvImageWidget_destroy;
458
widget_class->size_request = cvImageWidget_size_request;
459
#endif //GTK_VERSION3
461
widget_class->realize = cvImageWidget_realize;
462
widget_class->size_allocate = cvImageWidget_size_allocate;
463
widget_class->button_press_event = NULL;
464
widget_class->button_release_event = NULL;
465
widget_class->motion_notify_event = NULL;
469
cvImageWidget_init (CvImageWidget *image_widget)
471
image_widget->original_image=0;
472
image_widget->scaled_image=0;
473
image_widget->flags=0;
476
GType cvImageWidget_get_type (void){
477
static GType image_type = 0;
481
image_type = g_type_register_static_simple(
483
(gchar*) "CvImageWidget",
484
sizeof(CvImageWidgetClass),
485
(GClassInitFunc) cvImageWidget_class_init,
486
sizeof(CvImageWidget),
487
(GInstanceInitFunc) cvImageWidget_init,
494
/////////////////////////////////////////////////////////////////////////////
496
/////////////////////////////////////////////////////////////////////////////
501
typedef struct CvTrackbar
512
CvTrackbarCallback notify;
513
CvTrackbarCallback2 notify2;
519
typedef struct CvWindow
531
int status;//0 normal, 1 fullscreen (YV)
533
CvMouseCallback on_mouse;
534
void* on_mouse_param;
547
CvOpenGlDrawCallback glDrawCallback;
554
static gboolean icvOnClose( GtkWidget* widget, GdkEvent* event, gpointer user_data );
555
static gboolean icvOnKeyPress( GtkWidget* widget, GdkEventKey* event, gpointer user_data );
556
static void icvOnTrackbar( GtkWidget* widget, gpointer user_data );
557
static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_data );
560
int thread_started=0;
561
static gpointer icvWindowThreadLoop();
562
GMutex* last_key_mutex;
563
GCond* cond_have_key;
564
GMutex* window_mutex;
565
GThread* window_thread;
566
GtkWidget* cvTopLevelWidget = 0;
569
static int last_key = -1;
570
static CvWindow* hg_windows = 0;
572
CV_IMPL int cvInitSystem( int argc, char** argv )
574
static int wasInitialized = 0;
576
// check initialization status
577
if( !wasInitialized )
581
gtk_init( &argc, &argv );
582
setlocale(LC_NUMERIC,"C");
585
gtk_gl_init(&argc, &argv);
594
CV_IMPL int cvStartWindowThread(){
596
cvInitSystem(0,NULL);
597
if (!thread_started) {
598
if (!g_thread_supported ()) {
599
/* the GThread system wasn't inited, so init it */
603
// this mutex protects the window resources
604
window_mutex = g_mutex_new();
606
// protects the 'last key pressed' variable
607
last_key_mutex = g_mutex_new();
609
// conditional that indicates a key has been pressed
610
cond_have_key = g_cond_new();
612
// this is the window update thread
613
window_thread = g_thread_create((GThreadFunc) icvWindowThreadLoop,
616
thread_started = window_thread!=NULL;
617
return thread_started;
624
gpointer icvWindowThreadLoop(){
626
g_mutex_lock(window_mutex);
627
gtk_main_iteration_do(FALSE);
628
g_mutex_unlock(window_mutex);
638
#define CV_LOCK_MUTEX() \
639
if(thread_started && g_thread_self()!=window_thread){ g_mutex_lock( window_mutex ); } else { }
641
#define CV_UNLOCK_MUTEX() \
642
if(thread_started && g_thread_self()!=window_thread){ g_mutex_unlock( window_mutex); } else { }
645
#define CV_LOCK_MUTEX()
646
#define CV_UNLOCK_MUTEX()
649
static CvWindow* icvFindWindowByName( const char* name )
651
CvWindow* window = hg_windows;
652
while( window != 0 && strcmp(name, window->name) != 0 )
653
window = window->next;
658
static CvWindow* icvWindowByWidget( GtkWidget* widget )
660
CvWindow* window = hg_windows;
662
while( window != 0 && window->widget != widget &&
663
window->frame != widget && window->paned != widget )
664
window = window->next;
669
double cvGetModeWindow_GTK(const char* name)//YV
673
CV_FUNCNAME( "cvGetModeWindow_GTK" );
680
CV_ERROR( CV_StsNullPtr, "NULL name string" );
682
window = icvFindWindowByName( name );
684
CV_ERROR( CV_StsNullPtr, "NULL window" );
687
result = window->status;
695
void cvSetModeWindow_GTK( const char* name, double prop_value)//Yannick Verdie
698
CV_FUNCNAME( "cvSetModeWindow_GTK" );
705
CV_ERROR( CV_StsNullPtr, "NULL name string" );
707
window = icvFindWindowByName( name );
709
CV_ERROR( CV_StsNullPtr, "NULL window" );
711
if(window->flags & CV_WINDOW_AUTOSIZE)//if the flag CV_WINDOW_AUTOSIZE is set
714
//so easy to do fullscreen here, Linux rocks !
716
if (window->status==CV_WINDOW_FULLSCREEN && prop_value==CV_WINDOW_NORMAL)
719
gtk_window_unfullscreen(GTK_WINDOW(window->frame));
720
window->status=CV_WINDOW_NORMAL;
725
if (window->status==CV_WINDOW_NORMAL && prop_value==CV_WINDOW_FULLSCREEN)
728
gtk_window_fullscreen(GTK_WINDOW(window->frame));
729
window->status=CV_WINDOW_FULLSCREEN;
737
void cv::setWindowTitle(const String& winname, const String& title)
739
CvWindow* window = icvFindWindowByName(winname.c_str());
743
namedWindow(winname);
744
window = icvFindWindowByName(winname.c_str());
748
CV_Error(Error::StsNullPtr, "NULL window");
751
gtk_window_set_title(GTK_WINDOW(window->frame), title.c_str());
755
double cvGetPropWindowAutoSize_GTK(const char* name)
759
CV_FUNCNAME( "cvGetPropWindowAutoSize_GTK" );
766
CV_ERROR( CV_StsNullPtr, "NULL name string" );
768
window = icvFindWindowByName( name );
770
EXIT; // keep silence here
772
result = window->flags & CV_WINDOW_AUTOSIZE;
779
double cvGetRatioWindow_GTK(const char* name)
783
CV_FUNCNAME( "cvGetRatioWindow_GTK" );
790
CV_ERROR( CV_StsNullPtr, "NULL name string" );
792
window = icvFindWindowByName( name );
794
EXIT; // keep silence here
796
#if defined (GTK_VERSION3)
797
result = static_cast<double>(
798
gtk_widget_get_allocated_width(window->widget)) / gtk_widget_get_allocated_height(window->widget);
800
result = static_cast<double>(window->widget->allocation.width) / window->widget->allocation.height;
801
#endif // GTK_VERSION3
807
double cvGetOpenGlProp_GTK(const char* name)
812
CV_FUNCNAME( "cvGetOpenGlProp_GTK" );
819
CV_ERROR( CV_StsNullPtr, "NULL name string" );
821
window = icvFindWindowByName( name );
823
EXIT; // keep silence here
825
result = window->useGl;
842
void createGlContext(CvWindow* window)
844
GdkGLConfig* glconfig;
846
CV_FUNCNAME( "createGlContext" );
850
// Try double-buffered visual
851
glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE));
853
CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
855
// Set OpenGL-capability to the widget
856
if (!gtk_widget_set_gl_capability(window->widget, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE))
857
CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
859
window->useGl = true;
864
void drawGl(CvWindow* window)
866
CV_FUNCNAME( "drawGl" );
870
GdkGLContext* glcontext = gtk_widget_get_gl_context(window->widget);
871
GdkGLDrawable* gldrawable = gtk_widget_get_gl_drawable(window->widget);
873
if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
874
CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
876
glViewport(0, 0, window->widget->allocation.width, window->widget->allocation.height);
878
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
880
if (window->glDrawCallback)
881
window->glDrawCallback(window->glDrawData);
883
if (gdk_gl_drawable_is_double_buffered (gldrawable))
884
gdk_gl_drawable_swap_buffers(gldrawable);
888
gdk_gl_drawable_gl_end(gldrawable);
894
#endif // HAVE_OPENGL
896
#if defined (GTK_VERSION3)
897
static gboolean cvImageWidget_draw(GtkWidget* widget, cairo_t *cr, gpointer data)
900
CvWindow* window = (CvWindow*)data;
911
CvImageWidget *image_widget = NULL;
912
GdkPixbuf *pixbuf = NULL;
914
g_return_val_if_fail (widget != NULL, FALSE);
915
g_return_val_if_fail (CV_IS_IMAGE_WIDGET (widget), FALSE);
917
image_widget = CV_IMAGE_WIDGET (widget);
919
if( image_widget->scaled_image ){
920
// center image in available region
921
int x0 = (gtk_widget_get_allocated_width(widget) - image_widget->scaled_image->cols)/2;
922
int y0 = (gtk_widget_get_allocated_height(widget) - image_widget->scaled_image->rows)/2;
924
pixbuf = gdk_pixbuf_new_from_data(image_widget->scaled_image->data.ptr, GDK_COLORSPACE_RGB, false,
925
8, MIN(image_widget->scaled_image->cols, gtk_widget_get_allocated_width(widget)),
926
MIN(image_widget->scaled_image->rows, gtk_widget_get_allocated_height(widget)),
927
image_widget->scaled_image->step, NULL, NULL);
929
gdk_cairo_set_source_pixbuf(cr, pixbuf, x0, y0);
931
else if( image_widget->original_image ){
932
pixbuf = gdk_pixbuf_new_from_data(image_widget->original_image->data.ptr, GDK_COLORSPACE_RGB, false,
933
8, MIN(image_widget->original_image->cols, gtk_widget_get_allocated_width(widget)),
934
MIN(image_widget->original_image->rows, gtk_widget_get_allocated_height(widget)),
935
image_widget->original_image->step, NULL, NULL);
936
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
940
g_object_unref(pixbuf);
945
static gboolean cvImageWidget_expose(GtkWidget* widget, GdkEventExpose* event, gpointer data)
948
CvWindow* window = (CvWindow*)data;
959
CvImageWidget *image_widget = NULL;
961
GdkPixbuf *pixbuf = NULL;
963
g_return_val_if_fail (widget != NULL, FALSE);
964
g_return_val_if_fail (CV_IS_IMAGE_WIDGET (widget), FALSE);
965
g_return_val_if_fail (event != NULL, FALSE);
967
if (event->count > 0)
970
cr = gdk_cairo_create(widget->window);
971
image_widget = CV_IMAGE_WIDGET (widget);
973
if( image_widget->scaled_image ){
974
// center image in available region
975
int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2;
976
int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2;
978
pixbuf = gdk_pixbuf_new_from_data(image_widget->scaled_image->data.ptr, GDK_COLORSPACE_RGB, false,
979
8, MIN(image_widget->scaled_image->cols, widget->allocation.width),
980
MIN(image_widget->scaled_image->rows, widget->allocation.height),
981
image_widget->scaled_image->step, NULL, NULL);
983
gdk_cairo_set_source_pixbuf(cr, pixbuf, x0, y0);
985
else if( image_widget->original_image ){
986
pixbuf = gdk_pixbuf_new_from_data(image_widget->original_image->data.ptr, GDK_COLORSPACE_RGB, false,
987
8, MIN(image_widget->original_image->cols, widget->allocation.width),
988
MIN(image_widget->original_image->rows, widget->allocation.height),
989
image_widget->original_image->step, NULL, NULL);
990
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
994
g_object_unref(pixbuf);
998
#endif //GTK_VERSION3
1000
CV_IMPL int cvNamedWindow( const char* name, int flags )
1003
CV_FUNCNAME( "cvNamedWindow" );
1010
cvInitSystem(1,(char**)&name);
1012
CV_ERROR( CV_StsNullPtr, "NULL name string" );
1014
// Check the name in the storage
1015
if( icvFindWindowByName( name ) != 0 )
1022
CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
1023
memset( window, 0, sizeof(*window));
1024
window->name = (char*)(window + 1);
1025
memcpy( window->name, name, len + 1 );
1026
window->flags = flags;
1027
window->signature = CV_WINDOW_MAGIC_VAL;
1028
window->last_key = 0;
1029
window->on_mouse = 0;
1030
window->on_mouse_param = 0;
1031
memset( &window->toolbar, 0, sizeof(window->toolbar));
1032
window->next = hg_windows;
1034
window->status = CV_WINDOW_NORMAL;//YV
1038
window->frame = gtk_window_new( GTK_WINDOW_TOPLEVEL );
1040
window->paned = gtk_vbox_new( FALSE, 0 );
1041
window->widget = cvImageWidgetNew( flags );
1042
gtk_box_pack_end( GTK_BOX(window->paned), window->widget, TRUE, TRUE, 0 );
1043
gtk_widget_show( window->widget );
1044
gtk_container_add( GTK_CONTAINER(window->frame), window->paned );
1045
gtk_widget_show( window->paned );
1048
if (flags & CV_WINDOW_OPENGL)
1049
CV_ERROR( CV_OpenGlNotSupported, "Library was built without OpenGL support" );
1051
if (flags & CV_WINDOW_OPENGL)
1052
createGlContext(window);
1054
window->glDrawCallback = 0;
1055
window->glDrawData = 0;
1059
// configure event handlers
1060
// TODO -- move this to CvImageWidget ?
1061
g_signal_connect( window->frame, "key-press-event",
1062
G_CALLBACK(icvOnKeyPress), window );
1063
g_signal_connect( window->widget, "button-press-event",
1064
G_CALLBACK(icvOnMouse), window );
1065
g_signal_connect( window->widget, "button-release-event",
1066
G_CALLBACK(icvOnMouse), window );
1067
g_signal_connect( window->widget, "motion-notify-event",
1068
G_CALLBACK(icvOnMouse), window );
1069
g_signal_connect( window->frame, "delete-event",
1070
G_CALLBACK(icvOnClose), window );
1071
#if defined(GTK_VERSION3)
1072
g_signal_connect( window->widget, "draw",
1073
G_CALLBACK(cvImageWidget_draw), window );
1075
g_signal_connect( window->widget, "expose-event",
1076
G_CALLBACK(cvImageWidget_expose), window );
1077
#endif //GTK_VERSION3
1079
gtk_widget_add_events (window->widget, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK) ;
1081
gtk_widget_show( window->frame );
1082
gtk_window_set_title( GTK_WINDOW(window->frame), name );
1085
hg_windows->prev = window;
1086
hg_windows = window;
1088
gtk_window_set_resizable( GTK_WINDOW(window->frame), (flags & CV_WINDOW_AUTOSIZE) == 0 );
1091
// allow window to be resized
1092
if( (flags & CV_WINDOW_AUTOSIZE)==0 ){
1093
GdkGeometry geometry;
1094
geometry.min_width = 50;
1095
geometry.min_height = 50;
1096
gtk_window_set_geometry_hints( GTK_WINDOW( window->frame ), GTK_WIDGET( window->widget ),
1097
&geometry, (GdkWindowHints) (GDK_HINT_MIN_SIZE));
1104
cvSetOpenGlContext(name);
1116
CV_IMPL void cvSetOpenGlContext(const char* name)
1119
GdkGLContext* glcontext;
1120
GdkGLDrawable* gldrawable;
1122
CV_FUNCNAME( "cvSetOpenGlContext" );
1127
CV_ERROR( CV_StsNullPtr, "NULL name string" );
1129
window = icvFindWindowByName( name );
1131
CV_ERROR( CV_StsNullPtr, "NULL window" );
1134
CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" );
1136
glcontext = gtk_widget_get_gl_context(window->widget);
1137
gldrawable = gtk_widget_get_gl_drawable(window->widget);
1139
if (!gdk_gl_drawable_make_current(gldrawable, glcontext))
1140
CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
1145
CV_IMPL void cvUpdateWindow(const char* name)
1147
CV_FUNCNAME( "cvUpdateWindow" );
1154
CV_ERROR( CV_StsNullPtr, "NULL name string" );
1156
window = icvFindWindowByName( name );
1160
// window does not refresh without this
1161
gtk_widget_queue_draw( GTK_WIDGET(window->widget) );
1166
CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata)
1170
CV_FUNCNAME( "cvCreateOpenGLCallback" );
1175
CV_ERROR( CV_StsNullPtr, "NULL name string" );
1177
window = icvFindWindowByName( name );
1182
CV_ERROR( CV_OpenGlNotSupported, "Window was created without OpenGL context" );
1184
window->glDrawCallback = callback;
1185
window->glDrawData = userdata;
1190
#endif // HAVE_OPENGL
1195
static void icvDeleteWindow( CvWindow* window )
1197
CvTrackbar* trackbar;
1200
window->prev->next = window->next;
1202
hg_windows = window->next;
1205
window->next->prev = window->prev;
1207
window->prev = window->next = 0;
1209
gtk_widget_destroy( window->frame );
1211
for( trackbar = window->toolbar.first; trackbar != 0; )
1213
CvTrackbar* next = trackbar->next;
1214
cvFree( &trackbar );
1220
// if last window, send key press signal
1221
// to jump out of any waiting cvWaitKey's
1222
if(hg_windows==0 && thread_started){
1223
g_cond_broadcast(cond_have_key);
1229
CV_IMPL void cvDestroyWindow( const char* name )
1231
CV_FUNCNAME( "cvDestroyWindow" );
1238
CV_ERROR( CV_StsNullPtr, "NULL name string" );
1240
window = icvFindWindowByName( name );
1244
// note that it is possible for the update thread to run this function
1245
// if there is a call to cvShowImage in a mouse callback
1246
// (this would produce a deadlock on window_mutex)
1249
icvDeleteWindow( window );
1258
cvDestroyAllWindows( void )
1264
CvWindow* window = hg_windows;
1265
icvDeleteWindow( window );
1270
// CvSize icvCalcOptimalWindowSize( CvWindow * window, CvSize new_image_size){
1271
// CvSize window_size;
1272
// GtkWidget * toplevel = gtk_widget_get_toplevel( window->frame );
1273
// gdk_drawable_get_size( GDK_DRAWABLE(toplevel->window),
1274
// &window_size.width, &window_size.height );
1276
// window_size.width = window_size.width + new_image_size.width - window->widget->allocation.width;
1277
// window_size.height = window_size.height + new_image_size.height - window->widget->allocation.height;
1279
// return window_size;
1283
cvShowImage( const char* name, const CvArr* arr )
1285
CV_FUNCNAME( "cvShowImage" );
1292
CV_ERROR( CV_StsNullPtr, "NULL name" );
1296
window = icvFindWindowByName(name);
1299
cvNamedWindow(name, 1);
1300
window = icvFindWindowByName(name);
1308
cv::imshow(name, cv::cvarrToMat(arr));
1313
CvImageWidget * image_widget = CV_IMAGE_WIDGET( window->widget );
1314
cvImageWidgetSetImage( image_widget, arr );
1322
CV_IMPL void cvResizeWindow(const char* name, int width, int height )
1324
CV_FUNCNAME( "cvResizeWindow" );
1329
CvImageWidget * image_widget;
1332
CV_ERROR( CV_StsNullPtr, "NULL name" );
1334
window = icvFindWindowByName(name);
1338
image_widget = CV_IMAGE_WIDGET( window->widget );
1339
//if(image_widget->flags & CV_WINDOW_AUTOSIZE)
1344
gtk_window_set_resizable( GTK_WINDOW(window->frame), 1 );
1345
gtk_window_resize( GTK_WINDOW(window->frame), width, height );
1347
// disable initial resize since presumably user wants to keep
1349
image_widget->flags &= ~CV_WINDOW_NO_IMAGE;
1357
CV_IMPL void cvMoveWindow( const char* name, int x, int y )
1359
CV_FUNCNAME( "cvMoveWindow" );
1366
CV_ERROR( CV_StsNullPtr, "NULL name" );
1368
window = icvFindWindowByName(name);
1374
gtk_window_move( GTK_WINDOW(window->frame), x, y );
1383
icvFindTrackbarByName( const CvWindow* window, const char* name )
1385
CvTrackbar* trackbar = window->toolbar.first;
1387
for( ; trackbar != 0 && strcmp( trackbar->name, name ) != 0; trackbar = trackbar->next )
1394
icvCreateTrackbar( const char* trackbar_name, const char* window_name,
1395
int* val, int count, CvTrackbarCallback on_notify,
1396
CvTrackbarCallback2 on_notify2, void* userdata )
1400
CV_FUNCNAME( "icvCreateTrackbar" );
1404
/*char slider_name[32];*/
1405
CvWindow* window = 0;
1406
CvTrackbar* trackbar = 0;
1408
if( !window_name || !trackbar_name )
1409
CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );
1412
CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
1414
window = icvFindWindowByName(window_name);
1418
trackbar = icvFindTrackbarByName(window,trackbar_name);
1424
int len = strlen(trackbar_name);
1425
trackbar = (CvTrackbar*)cvAlloc(sizeof(CvTrackbar) + len + 1);
1426
memset( trackbar, 0, sizeof(*trackbar));
1427
trackbar->signature = CV_TRACKBAR_MAGIC_VAL;
1428
trackbar->name = (char*)(trackbar+1);
1429
memcpy( trackbar->name, trackbar_name, len + 1 );
1430
trackbar->parent = window;
1431
trackbar->next = window->toolbar.first;
1432
window->toolbar.first = trackbar;
1434
GtkWidget* hscale_box = gtk_hbox_new( FALSE, 10 );
1435
GtkWidget* hscale_label = gtk_label_new( trackbar_name );
1436
GtkWidget* hscale = gtk_hscale_new_with_range( 0, count, 1 );
1437
gtk_scale_set_digits( GTK_SCALE(hscale), 0 );
1438
//gtk_scale_set_value_pos( hscale, GTK_POS_TOP );
1439
gtk_scale_set_draw_value( GTK_SCALE(hscale), TRUE );
1441
trackbar->widget = hscale;
1442
gtk_box_pack_start( GTK_BOX(hscale_box), hscale_label, FALSE, FALSE, 5 );
1443
gtk_widget_show( hscale_label );
1444
gtk_box_pack_start( GTK_BOX(hscale_box), hscale, TRUE, TRUE, 5 );
1445
gtk_widget_show( hscale );
1446
gtk_box_pack_start( GTK_BOX(window->paned), hscale_box, FALSE, FALSE, 5 );
1447
gtk_widget_show( hscale_box );
1458
gtk_range_set_value( GTK_RANGE(trackbar->widget), value );
1459
trackbar->pos = value;
1460
trackbar->data = val;
1463
trackbar->maxval = count;
1464
trackbar->notify = on_notify;
1465
trackbar->notify2 = on_notify2;
1466
trackbar->userdata = userdata;
1467
g_signal_connect( trackbar->widget, "value-changed",
1468
G_CALLBACK(icvOnTrackbar), trackbar );
1470
// queue a widget resize to trigger a window resize to
1471
// compensate for the addition of trackbars
1472
gtk_widget_queue_resize( GTK_WIDGET(window->widget) );
1486
cvCreateTrackbar( const char* trackbar_name, const char* window_name,
1487
int* val, int count, CvTrackbarCallback on_notify )
1489
return icvCreateTrackbar(trackbar_name, window_name, val, count,
1495
cvCreateTrackbar2( const char* trackbar_name, const char* window_name,
1496
int* val, int count, CvTrackbarCallback2 on_notify2,
1499
return icvCreateTrackbar(trackbar_name, window_name, val, count,
1500
0, on_notify2, userdata);
1505
cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param )
1507
CV_FUNCNAME( "cvSetMouseCallback" );
1511
CvWindow* window = 0;
1514
CV_ERROR( CV_StsNullPtr, "NULL window name" );
1516
window = icvFindWindowByName(window_name);
1520
window->on_mouse = on_mouse;
1521
window->on_mouse_param = param;
1527
CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
1531
CV_FUNCNAME( "cvGetTrackbarPos" );
1536
CvTrackbar* trackbar = 0;
1538
if( trackbar_name == 0 || window_name == 0 )
1539
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
1541
window = icvFindWindowByName( window_name );
1543
trackbar = icvFindTrackbarByName( window, trackbar_name );
1546
pos = trackbar->pos;
1554
CV_IMPL void cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos )
1556
CV_FUNCNAME( "cvSetTrackbarPos" );
1561
CvTrackbar* trackbar = 0;
1563
if( trackbar_name == 0 || window_name == 0 )
1564
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
1566
window = icvFindWindowByName( window_name );
1568
trackbar = icvFindTrackbarByName( window, trackbar_name );
1575
if( pos > trackbar->maxval )
1576
pos = trackbar->maxval;
1581
gtk_range_set_value( GTK_RANGE(trackbar->widget), pos );
1589
CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval)
1591
CV_FUNCNAME("cvSetTrackbarMax");
1597
CvWindow* window = 0;
1598
CvTrackbar* trackbar = 0;
1600
if (trackbar_name == 0 || window_name == 0)
1602
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name");
1605
window = icvFindWindowByName( window_name );
1608
trackbar = icvFindTrackbarByName(window, trackbar_name);
1611
trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval;
1615
gtk_range_set_range(GTK_RANGE(trackbar->widget), 0, trackbar->maxval);
1626
CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval)
1628
CV_FUNCNAME("cvSetTrackbarMin");
1634
CvWindow* window = 0;
1635
CvTrackbar* trackbar = 0;
1637
if (trackbar_name == 0 || window_name == 0)
1639
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name");
1642
window = icvFindWindowByName( window_name );
1645
trackbar = icvFindTrackbarByName(window, trackbar_name);
1648
trackbar->minval = (minval<trackbar->maxval)?minval:trackbar->maxval;
1652
gtk_range_set_range(GTK_RANGE(trackbar->widget), minval, trackbar->maxval);
1663
CV_IMPL void* cvGetWindowHandle( const char* window_name )
1667
CV_FUNCNAME( "cvGetWindowHandle" );
1673
if( window_name == 0 )
1674
CV_ERROR( CV_StsNullPtr, "NULL window name" );
1676
window = icvFindWindowByName( window_name );
1678
widget = (void*)window->widget;
1686
CV_IMPL const char* cvGetWindowName( void* window_handle )
1688
const char* window_name = "";
1690
CV_FUNCNAME( "cvGetWindowName" );
1696
if( window_handle == 0 )
1697
CV_ERROR( CV_StsNullPtr, "NULL window" );
1699
window = icvWindowByWidget( (GtkWidget*)window_handle );
1701
window_name = window->name;
1708
static GtkFileFilter* icvMakeGtkFilter(const char* name, const char* patterns, GtkFileFilter* images)
1710
GtkFileFilter* filter = gtk_file_filter_new();
1711
gtk_file_filter_set_name(filter, name);
1715
gtk_file_filter_add_pattern(filter, patterns);
1716
gtk_file_filter_add_pattern(images, patterns);
1717
patterns += strlen(patterns) + 1;
1723
static void icvShowSaveAsDialog(GtkWidget* widget, CvWindow* window)
1725
if (!window || !widget)
1728
CvImageWidget* image_widget = CV_IMAGE_WIDGET(window->widget);
1729
if (!image_widget || !image_widget->original_image)
1732
GtkWidget* dialog = gtk_file_chooser_dialog_new("Save As...",
1734
GTK_FILE_CHOOSER_ACTION_SAVE,
1735
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1736
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
1738
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
1740
cv::String sname = gtk_window_get_title(GTK_WINDOW(window->frame));
1741
sname = sname.substr(sname.find_last_of("\\/") + 1) + ".png";
1742
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), sname.c_str());
1744
GtkFileFilter* filter_all = gtk_file_filter_new();
1745
gtk_file_filter_set_name(filter_all, "All Files");
1746
gtk_file_filter_add_pattern(filter_all, "*");
1748
GtkFileFilter* filter_images = gtk_file_filter_new();
1749
gtk_file_filter_set_name(filter_images, "All Images");
1751
GtkFileFilter* file_filters[] = {
1752
icvMakeGtkFilter("Portable Network Graphics files (*.png)", "*.png\0", filter_images),
1753
icvMakeGtkFilter("JPEG files (*.jpeg;*.jpg;*.jpe)", "*.jpeg\0*.jpg\0*.jpe\0", filter_images),
1754
icvMakeGtkFilter("Windows bitmap (*.bmp;*.dib)", "*.bmp\0*.dib\0", filter_images),
1755
icvMakeGtkFilter("TIFF Files (*.tiff;*.tif)", "*.tiff\0*.tif\0", filter_images),
1756
icvMakeGtkFilter("JPEG-2000 files (*.jp2)", "*.jp2\0", filter_images),
1757
icvMakeGtkFilter("WebP files (*.webp)", "*.webp\0", filter_images),
1758
icvMakeGtkFilter("Portable image format (*.pbm;*.pgm;*.ppm;*.pxm;*.pnm)", "*.pbm\0*.pgm\0*.ppm\0*.pxm\0*.pnm\0", filter_images),
1759
icvMakeGtkFilter("OpenEXR Image files (*.exr)", "*.exr\0", filter_images),
1760
icvMakeGtkFilter("Radiance HDR (*.hdr;*.pic)", "*.hdr\0*.pic\0", filter_images),
1761
icvMakeGtkFilter("Sun raster files (*.sr;*.ras)", "*.sr\0*.ras\0", filter_images),
1766
for (size_t idx = 0; idx < sizeof(file_filters)/sizeof(file_filters[0]); ++idx)
1767
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), file_filters[idx]);
1768
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter_images);
1770
cv::String filename;
1771
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1773
char* fname = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
1777
gtk_widget_destroy(dialog);
1779
if (!filename.empty())
1782
cv::cvtColor(cv::cvarrToMat(image_widget->original_image), bgr, cv::COLOR_RGB2BGR);
1783
cv::imwrite(filename, bgr);
1787
#if defined (GTK_VERSION3)
1788
#define GDK_Escape GDK_KEY_Escape
1789
#define GDK_Return GDK_KEY_Return
1790
#define GDK_Linefeed GDK_KEY_Linefeed
1791
#define GDK_Tab GDK_KEY_Tab
1792
#define GDK_s GDK_KEY_s
1793
#define GDK_S GDK_KEY_S
1794
#endif //GTK_VERSION3
1796
static gboolean icvOnKeyPress(GtkWidget* widget, GdkEventKey* event, gpointer user_data)
1800
if ( (event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK && (event->keyval == GDK_s || event->keyval == GDK_S))
1804
icvShowSaveAsDialog(widget, (CvWindow*)user_data);
1808
// suppress all exceptions here
1812
switch( event->keyval )
1825
code = event->keyval;
1828
code |= event->state << 16;
1831
if(thread_started) g_mutex_lock(last_key_mutex);
1838
// signal any waiting threads
1839
g_cond_broadcast(cond_have_key);
1840
g_mutex_unlock(last_key_mutex);
1848
static void icvOnTrackbar( GtkWidget* widget, gpointer user_data )
1850
int pos = cvRound( gtk_range_get_value(GTK_RANGE(widget)));
1851
CvTrackbar* trackbar = (CvTrackbar*)user_data;
1853
if( trackbar && trackbar->signature == CV_TRACKBAR_MAGIC_VAL &&
1854
trackbar->widget == widget )
1856
trackbar->pos = pos;
1857
if( trackbar->data )
1858
*trackbar->data = pos;
1859
if( trackbar->notify2 )
1860
trackbar->notify2(pos, trackbar->userdata);
1861
else if( trackbar->notify )
1862
trackbar->notify(pos);
1866
static gboolean icvOnClose( GtkWidget* widget, GdkEvent* /*event*/, gpointer user_data )
1868
CvWindow* window = (CvWindow*)user_data;
1869
if( window->signature == CV_WINDOW_MAGIC_VAL &&
1870
window->frame == widget )
1872
icvDeleteWindow(window);
1878
static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_data )
1880
// TODO move this logic to CvImageWidget
1881
CvWindow* window = (CvWindow*)user_data;
1882
CvPoint2D32f pt32f(-1., -1.);
1884
int cv_event = -1, state = 0;
1885
CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget );
1887
if( window->signature != CV_WINDOW_MAGIC_VAL ||
1888
window->widget != widget || !window->widget ||
1889
!window->on_mouse /*|| !image_widget->original_image*/)
1892
if( event->type == GDK_MOTION_NOTIFY )
1894
GdkEventMotion* event_motion = (GdkEventMotion*)event;
1896
cv_event = CV_EVENT_MOUSEMOVE;
1897
pt32f.x = cvRound(event_motion->x);
1898
pt32f.y = cvRound(event_motion->y);
1899
state = event_motion->state;
1901
else if( event->type == GDK_BUTTON_PRESS ||
1902
event->type == GDK_BUTTON_RELEASE ||
1903
event->type == GDK_2BUTTON_PRESS )
1905
GdkEventButton* event_button = (GdkEventButton*)event;
1906
pt32f.x = cvRound(event_button->x);
1907
pt32f.y = cvRound(event_button->y);
1910
if( event_button->type == GDK_BUTTON_PRESS )
1912
cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDOWN :
1913
event_button->button == 2 ? CV_EVENT_MBUTTONDOWN :
1914
event_button->button == 3 ? CV_EVENT_RBUTTONDOWN : 0;
1916
else if( event_button->type == GDK_BUTTON_RELEASE )
1918
cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONUP :
1919
event_button->button == 2 ? CV_EVENT_MBUTTONUP :
1920
event_button->button == 3 ? CV_EVENT_RBUTTONUP : 0;
1922
else if( event_button->type == GDK_2BUTTON_PRESS )
1924
cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDBLCLK :
1925
event_button->button == 2 ? CV_EVENT_MBUTTONDBLCLK :
1926
event_button->button == 3 ? CV_EVENT_RBUTTONDBLCLK : 0;
1928
state = event_button->state;
1931
if( cv_event >= 0 ){
1932
// scale point if image is scaled
1933
if( (image_widget->flags & CV_WINDOW_AUTOSIZE)==0 &&
1934
image_widget->original_image &&
1935
image_widget->scaled_image ){
1936
// image origin is not necessarily at (0,0)
1937
#if defined (GTK_VERSION3)
1938
int x0 = (gtk_widget_get_allocated_width(widget) - image_widget->scaled_image->cols)/2;
1939
int y0 = (gtk_widget_get_allocated_height(widget) - image_widget->scaled_image->rows)/2;
1941
int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2;
1942
int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2;
1943
#endif //GTK_VERSION3
1944
pt.x = cvFloor( ((pt32f.x-x0)*image_widget->original_image->cols)/
1945
image_widget->scaled_image->cols );
1946
pt.y = cvFloor( ((pt32f.y-y0)*image_widget->original_image->rows)/
1947
image_widget->scaled_image->rows );
1950
pt = cvPointFrom32f( pt32f );
1953
// if((unsigned)pt.x < (unsigned)(image_widget->original_image->width) &&
1954
// (unsigned)pt.y < (unsigned)(image_widget->original_image->height) )
1956
int flags = (state & GDK_SHIFT_MASK ? CV_EVENT_FLAG_SHIFTKEY : 0) |
1957
(state & GDK_CONTROL_MASK ? CV_EVENT_FLAG_CTRLKEY : 0) |
1958
(state & (GDK_MOD1_MASK|GDK_MOD2_MASK) ? CV_EVENT_FLAG_ALTKEY : 0) |
1959
(state & GDK_BUTTON1_MASK ? CV_EVENT_FLAG_LBUTTON : 0) |
1960
(state & GDK_BUTTON2_MASK ? CV_EVENT_FLAG_MBUTTON : 0) |
1961
(state & GDK_BUTTON3_MASK ? CV_EVENT_FLAG_RBUTTON : 0);
1962
window->on_mouse( cv_event, pt.x, pt.y, flags, window->on_mouse_param );
1970
static gboolean icvAlarm( gpointer user_data )
1972
*(int*)user_data = 1;
1977
CV_IMPL int cvWaitKey( int delay )
1980
if(thread_started && g_thread_self()!=window_thread){
1984
// wait for signal or timeout if delay > 0
1987
g_get_current_time(&timer);
1988
g_time_val_add(&timer, delay*1000);
1989
expired = !g_cond_timed_wait(cond_have_key, last_key_mutex, &timer);
1992
g_cond_wait(cond_have_key, last_key_mutex);
1995
my_last_key = last_key;
1996
g_mutex_unlock(last_key_mutex);
1997
if(expired || hg_windows==0){
2007
timer = g_timeout_add( delay, icvAlarm, &expired );
2009
while( gtk_main_iteration_do(TRUE) && last_key < 0 && !expired && hg_windows != 0 )
2012
if( delay > 0 && !expired )
2013
g_source_remove(timer);