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.
44 #include <Carbon/Carbon.h>
50 //#define MS_TO_TICKS(a) a*3/50
53 #define INTERWIDGETSPACE 16
54 #define WIDGETHEIGHT 32
59 typedef struct CvTrackbar
72 CvTrackbarCallback notify;
73 CvTrackbarCallback2 notify2;
79 typedef struct CvWindow
98 CvMouseCallback on_mouse;
111 static CvWindow* hg_windows = 0;
113 #define Assert(exp) \
116 printf("Assertion: %s %s: %d\n", #exp, __FILE__, __LINE__);\
120 static int wasInitialized = 0;
121 static char lastKey = NO_KEY;
122 OSStatus keyHandler(EventHandlerCallRef hcr, EventRef theEvent, void* inUserData);
123 static pascal OSStatus windowEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *inUserData);
125 static const EventTypeSpec applicationKeyboardEvents[] =
127 { kEventClassKeyboard, kEventRawKeyDown },
130 CV_IMPL int cvInitSystem( int argc, char** argv )
133 if( !wasInitialized )
137 err = InstallApplicationEventHandler(NewEventHandlerUPP( keyHandler),GetEventTypeCount(applicationKeyboardEvents),applicationKeyboardEvents,NULL,NULL);
140 fprintf(stderr,"InstallApplicationEventHandler was not ok\n");
148 // TODO: implement missing functionality
149 CV_IMPL int cvStartWindowThread()
154 static int icvCountTrackbarInWindow( const CvWindow* window)
156 CvTrackbar* trackbar = window->toolbar.first;
158 while (trackbar != 0) {
160 trackbar = trackbar->next;
165 static CvTrackbar* icvTrackbarByHandle( void * handle )
167 CvWindow* window = hg_windows;
168 CvTrackbar* trackbar = NULL;
169 while( window != 0 && window->window != handle) {
170 trackbar = window->toolbar.first;
171 while (trackbar != 0 && trackbar->trackbar != handle)
172 trackbar = trackbar->next;
173 if (trackbar != 0 && trackbar->trackbar == handle)
175 window = window->next;
180 static CvWindow* icvWindowByHandle( void * handle )
182 CvWindow* window = hg_windows;
184 while( window != 0 && window->window != handle)
185 window = window->next;
190 CV_IMPL CvWindow * icvFindWindowByName( const char* name)
192 CvWindow* window = hg_windows;
193 while( window != 0 && strcmp(name, window->name) != 0 )
194 window = window->next;
199 static CvTrackbar* icvFindTrackbarByName( const CvWindow* window, const char* name )
201 CvTrackbar* trackbar = window->toolbar.first;
203 while (trackbar != 0 && strcmp( trackbar->name, name ) != 0)
204 trackbar = trackbar->next;
210 /* draw image to frame */
211 static void icvDrawImage( CvWindow* window )
213 Assert( window != 0 );
214 if( window->imageRef == 0 ) return;
216 CGContextRef myContext;
219 int width = window->imageWidth;
220 int height = window->imageHeight;
222 GetWindowPortBounds(window->window, &portrect);
224 if( window->flags & CV_WINDOW_AUTOSIZE )
226 CGPoint origin = {0,0};
227 CGSize size = {portrect.right-portrect.left, portrect.bottom-portrect.top-window->trackbarheight};
228 rect.origin = origin; rect.size = size;
232 CGPoint origin = {0, portrect.bottom - height - window->trackbarheight};
233 CGSize size = {width, height};
234 rect.origin = origin; rect.size = size;
237 /* To be sybnchronous we are using this, better would be to susbcribe to the draw event and process whenever requested, we might save SOME CPU cycles*/
238 SetPortWindowPort (window->window);
239 QDBeginCGContext (GetWindowPort (window->window), &myContext);
240 CGContextSetInterpolationQuality (myContext, kCGInterpolationLow);
241 CGContextDrawImage(myContext,rect,window->imageRef);
242 CGContextFlush(myContext);// 4
243 QDEndCGContext (GetWindowPort(window->window), &myContext);// 5
247 /* update imageRef */
248 static void icvPutImage( CvWindow* window )
250 Assert( window != 0 );
251 if( window->image == 0 ) return;
253 CGColorSpaceRef colorspace = NULL;
254 CGDataProviderRef provider = NULL;
255 int width = window->imageWidth = window->image->cols;
256 int height = window->imageHeight = window->image->rows;
258 colorspace = CGColorSpaceCreateDeviceRGB();
263 provider = CGDataProviderCreateWithData(NULL, window->image->data.ptr, width * height , NULL );
265 if (window->imageRef != NULL){
266 CGImageRelease(window->imageRef);
267 window->imageRef = NULL;
270 window->imageRef = CGImageCreate( width, height, size , size*nbChannels , window->image->step, colorspace, kCGImageAlphaNone , provider, NULL, true, kCGRenderingIntentDefault );
271 icvDrawImage( window );
273 /* release the provider's memory */
274 CGDataProviderRelease( provider );
277 static void icvUpdateWindowSize( const CvWindow* window )
279 int width = 0, height = 240; /* init à al taille de base de l'image*/
282 GetWindowBounds(window->window, kWindowContentRgn, &globalBounds);
286 if( window->image ) {
287 width = MAX(MAX(window->image->width, width), minWidth);
288 height = window->image->height;
292 height += window->trackbarheight;
294 //height +=WIDGETHEIGHT; /* 32 pixels are spearating tracbars from the video display */
296 globalBounds.right = globalBounds.left + width;
297 globalBounds.bottom = globalBounds.top + height;
298 SetWindowBounds(window->window, kWindowContentRgn, &globalBounds);
301 static void icvDeleteWindow( CvWindow* window )
303 CvTrackbar* trackbar;
306 window->prev->next = window->next;
308 hg_windows = window->next;
311 window->next->prev = window->prev;
313 window->prev = window->next = 0;
315 cvReleaseMat( &window->image );
316 cvReleaseMat( &window->dst_image );
318 for( trackbar = window->toolbar.first; trackbar != 0; )
320 CvTrackbar* next = trackbar->next;
321 cvFree( (void**)&trackbar );
325 if (window->imageRef != NULL)
326 CGImageRelease(window->imageRef);
328 cvFree( (void**)&window );
332 CV_IMPL void cvDestroyWindow( const char* name)
334 CV_FUNCNAME( "cvDestroyWindow" );
341 CV_ERROR( CV_StsNullPtr, "NULL name string" );
343 window = icvFindWindowByName( name );
347 icvDeleteWindow( window );
353 CV_IMPL void cvDestroyAllWindows( void )
357 CvWindow* window = hg_windows;
358 icvDeleteWindow( window );
363 CV_IMPL void cvShowImage( const char* name, const CvArr* arr)
365 CV_FUNCNAME( "cvShowImage" );
375 CV_ERROR( CV_StsNullPtr, "NULL name" );
377 window = icvFindWindowByName(name);
380 cvNamedWindow(name, 1);
381 window = icvFindWindowByName(name);
384 if( !window || !arr )
385 EXIT; // keep silence here.
387 if( CV_IS_IMAGE_HDR( arr ))
388 origin = ((IplImage*)arr)->origin;
390 CV_CALL( image = cvGetMat( arr, &stub ));
394 cvResizeWindow( name, image->cols, image->rows );
398 !CV_ARE_SIZES_EQ(window->image, image) ) {
399 if ( ! (window->flags & CV_WINDOW_AUTOSIZE) )//FD
401 cvReleaseMat( &window->image );
404 if( !window->image ) {
406 window->image = cvCreateMat( image->rows, image->cols, CV_8UC3 );
409 cvConvertImage( image, window->image, (origin != 0 ? CV_CVTIMG_FLIP : 0) + CV_CVTIMG_SWAP_RB );
410 icvPutImage( window );
412 icvUpdateWindowSize( window );
417 CV_IMPL void cvResizeWindow( const char* name, int width, int height)
419 CV_FUNCNAME( "cvResizeWindow" );
424 //CvTrackbar* trackbar;
427 CV_ERROR( CV_StsNullPtr, "NULL name" );
429 window = icvFindWindowByName(name);
433 SizeWindow(window->window, width, height, true);
438 CV_IMPL void cvMoveWindow( const char* name, int x, int y)
440 CV_FUNCNAME( "cvMoveWindow" );
445 //CvTrackbar* trackbar;
448 CV_ERROR( CV_StsNullPtr, "NULL name" );
450 window = icvFindWindowByName(name);
454 MoveWindow(window->window, x, y, true);
459 void TrackbarActionProcPtr (ControlRef theControl, ControlPartCode partCode)
461 CvTrackbar * trackbar = icvTrackbarByHandle (theControl);
463 if (trackbar == NULL)
465 fprintf(stderr,"Error getting trackbar\n");
470 int pos = GetControl32BitValue (theControl);
471 if ( trackbar->data )
472 *trackbar->data = pos;
473 if ( trackbar->notify )
474 trackbar->notify(pos);
475 else if ( trackbar->notify2 )
476 trackbar->notify2(pos, trackbar->userdata);
481 static int icvCreateTrackbar (const char* trackbar_name,
482 const char* window_name,
484 CvTrackbarCallback on_notify,
485 CvTrackbarCallback2 on_notify2,
490 CV_FUNCNAME( "icvCreateTrackbar" );
493 /*char slider_name[32];*/
494 CvWindow* window = 0;
495 CvTrackbar* trackbar = 0;
497 ControlRef outControl;
498 ControlRef stoutControl;
501 if( !window_name || !trackbar_name )
502 CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );
505 CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
507 window = icvFindWindowByName(window_name);
511 trackbar = icvFindTrackbarByName(window,trackbar_name);
514 int len = strlen(trackbar_name);
515 trackbar = (CvTrackbar*)cvAlloc(sizeof(CvTrackbar) + len + 1);
516 memset( trackbar, 0, sizeof(*trackbar));
517 trackbar->signature = CV_TRACKBAR_MAGIC_VAL;
518 trackbar->name = (char*)(trackbar+1);
519 memcpy( trackbar->name, trackbar_name, len + 1 );
520 trackbar->parent = window;
521 trackbar->next = window->toolbar.first;
522 window->toolbar.first = trackbar;
531 trackbar->pos = value;
532 trackbar->data = val;
535 trackbar->maxval = count;
537 int c = icvCountTrackbarInWindow(window);
539 GetWindowBounds(window->window,kWindowContentRgn,&bounds);
541 stboundsRect.top = (INTERWIDGETSPACE +WIDGETHEIGHT)* (c-1)+INTERWIDGETSPACE;
542 stboundsRect.left = INTERWIDGETSPACE;
543 stboundsRect.bottom = stboundsRect.top + WIDGETHEIGHT;
544 stboundsRect.right = stboundsRect.left+LABELWIDTH;
546 //fprintf(stdout,"create trackabar bounds (%d %d %d %d)\n",stboundsRect.top,stboundsRect.left,stboundsRect.bottom,stboundsRect.right);
547 CreateStaticTextControl (window->window,&stboundsRect,CFStringCreateWithCString(NULL,trackbar_name,kCFStringEncodingASCII),NULL,&stoutControl);
549 stboundsRect.top = (INTERWIDGETSPACE +WIDGETHEIGHT)* (c-1)+INTERWIDGETSPACE;
550 stboundsRect.left = INTERWIDGETSPACE*2+LABELWIDTH;
551 stboundsRect.bottom = stboundsRect.top + WIDGETHEIGHT;
552 stboundsRect.right = bounds.right-INTERWIDGETSPACE;
554 CreateSliderControl (window->window,&stboundsRect, trackbar->pos,0,trackbar->maxval,kControlSliderLiveFeedback,0,true,NewControlActionUPP(TrackbarActionProcPtr),&outControl);
556 bounds.bottom += INTERWIDGETSPACE + WIDGETHEIGHT;
557 SetControlVisibility (outControl,true,true);
558 SetControlVisibility (stoutControl,true,true);
560 trackbar->trackbar = outControl;
561 trackbar->label = stoutControl;
563 window->trackbarheight = INTERWIDGETSPACE*2 + WIDGETHEIGHT;
565 window->trackbarheight += INTERWIDGETSPACE + WIDGETHEIGHT;
566 icvUpdateWindowSize( window );
569 trackbar->notify = on_notify;
570 trackbar->notify2 = on_notify2;
571 trackbar->userdata = userdata;
580 CV_IMPL int cvCreateTrackbar (const char* trackbar_name,
581 const char* window_name,
583 CvTrackbarCallback on_notify)
585 return icvCreateTrackbar(trackbar_name, window_name, val, count, on_notify, 0, 0);
589 CV_IMPL int cvCreateTrackbar2(const char* trackbar_name,
590 const char* window_name,
592 CvTrackbarCallback2 on_notify2,
595 return icvCreateTrackbar(trackbar_name, window_name, val,
596 count, 0, on_notify2, userdata);
601 cvSetMouseCallback( const char* name, CvMouseCallback function, void* info)
603 CvWindow* window = icvFindWindowByName( name );
606 window->on_mouse = function;
607 window->on_mouse_param = info;
611 fprintf(stdout,"Error with cvSetMouseCallback. Window not found : %s\n",name);
615 CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
619 CV_FUNCNAME( "cvGetTrackbarPos" );
624 CvTrackbar* trackbar = 0;
626 if( trackbar_name == 0 || window_name == 0 )
627 CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
629 window = icvFindWindowByName( window_name );
631 trackbar = icvFindTrackbarByName( window, trackbar_name );
641 CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos)
643 CV_FUNCNAME( "cvSetTrackbarPos" );
648 CvTrackbar* trackbar = 0;
650 if( trackbar_name == 0 || window_name == 0 )
651 CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
653 window = icvFindWindowByName( window_name );
655 trackbar = icvFindTrackbarByName( window, trackbar_name );
662 if( pos > trackbar->maxval )
663 pos = trackbar->maxval;
665 // Set new value and redraw the trackbar
666 SetControlValue( trackbar->trackbar, pos );
667 Draw1Control( trackbar->trackbar );
674 CV_IMPL void* cvGetWindowHandle( const char* name )
676 WindowRef result = 0;
681 window = icvFindWindowByName( name );
683 result = window->window;
693 CV_IMPL const char* cvGetWindowName( void* window_handle )
695 const char* window_name = "";
697 CV_FUNCNAME( "cvGetWindowName" );
703 if( window_handle == 0 )
704 CV_ERROR( CV_StsNullPtr, "NULL window" );
705 window = icvWindowByHandle(window_handle );
707 window_name = window->name;
715 CV_IMPL int cvNamedWindow( const char* name, int flags )
718 CV_FUNCNAME( "cvNamedWindow" );
720 cvInitSystem(0, NULL);
722 // to be able to display a window, we need to be a 'faceful' application
723 // http://lists.apple.com/archives/carbon-dev/2005/Jun/msg01414.html
724 static bool switched_to_faceful = false;
725 if (! switched_to_faceful)
727 ProcessSerialNumber psn = { 0, kCurrentProcess };
728 OSStatus ret = TransformProcessType (&psn, kProcessTransformToForegroundApplication );
732 SetFrontProcess( &psn );
733 switched_to_faceful = true;
737 fprintf(stderr, "Failed to tranform process type: %d\n", (int) ret);
744 WindowRef outWindow = NULL;
745 OSStatus err = noErr;
746 Rect contentBounds = {100,100,320,440};
749 UInt wAttributes = 0;
753 const EventTypeSpec genericWindowEventHandler[] = {
754 { kEventClassMouse, kEventMouseMoved},
755 { kEventClassMouse, kEventMouseDragged},
756 { kEventClassMouse, kEventMouseUp},
757 { kEventClassMouse, kEventMouseDown},
758 { kEventClassWindow, kEventWindowClose },
759 { kEventClassWindow, kEventWindowBoundsChanged }//FD
763 CV_ERROR( CV_StsNullPtr, "NULL name string" );
765 if( icvFindWindowByName( name ) != 0 ){
770 CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
771 memset( window, 0, sizeof(*window));
772 window->name = (char*)(window + 1);
773 memcpy( window->name, name, len + 1 );
774 window->flags = flags;
775 window->signature = CV_WINDOW_MAGIC_VAL;
777 window->last_key = 0;
778 window->on_mouse = 0;
779 window->on_mouse_param = 0;
781 window->next = hg_windows;
784 hg_windows->prev = window;
786 wAttributes = kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute;
788 err = CreateNewWindow ( kDocumentWindowClass,wAttributes,&contentBounds,&outWindow);
790 fprintf(stderr,"Error while creating the window\n");
792 SetWindowTitleWithCFString(outWindow,CFStringCreateWithCString(NULL,name,kCFStringEncodingASCII));
794 fprintf(stdout,"Error SetWindowTitleWithCFString\n");
796 window->window = outWindow;
798 err = InstallWindowEventHandler(outWindow, NewEventHandlerUPP(windowEventHandler), GetEventTypeCount(genericWindowEventHandler), genericWindowEventHandler, outWindow, NULL);
800 ShowWindow( outWindow );
807 static pascal OSStatus windowEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *inUserData)
809 CvWindow* window = NULL;
810 UInt32 eventKind, eventClass;
814 HIPoint point = {0,0};
815 EventMouseButton eventMouseButton = 0;//FD
816 UInt32 modifiers;//FD
818 WindowRef theWindow = (WindowRef)inUserData;
819 if (theWindow == NULL)
820 return eventNotHandledErr;
821 window = icvWindowByHandle(theWindow);
823 return eventNotHandledErr;
825 eventKind = GetEventKind(theEvent);
826 eventClass = GetEventClass(theEvent);
828 switch (eventClass) {
829 case kEventClassMouse : {
832 case kEventMouseDown :
833 case kEventMouseMoved :
834 case kEventMouseDragged : {
835 err = CallNextEventHandler(nextHandler, theEvent);
836 if (err != eventNotHandledErr)
838 err = GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(eventMouseButton), NULL, &eventMouseButton);
839 err = GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
840 err = GetEventParameter(theEvent,kEventParamClickCount,typeUInt32,NULL,sizeof(UInt32),NULL,&count);
842 if (count >1) event += 6;
844 event = CV_EVENT_MOUSEMOVE;
847 if (eventKind == kEventMouseUp)
849 if (eventKind == kEventMouseDown)
852 unsigned int flags = 0;
854 err = GetEventParameter(theEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point);
855 if (eventKind != kEventMouseMoved){
856 switch(eventMouseButton){
857 case kEventMouseButtonPrimary:
858 if (modifiers & controlKey){
859 flags += CV_EVENT_FLAG_RBUTTON;
862 flags += CV_EVENT_FLAG_LBUTTON;
865 case kEventMouseButtonSecondary:
866 flags += CV_EVENT_FLAG_RBUTTON;
869 case kEventMouseButtonTertiary:
870 flags += CV_EVENT_FLAG_MBUTTON;
876 if (modifiers&controlKey) flags += CV_EVENT_FLAG_CTRLKEY;
877 if (modifiers&shiftKey) flags += CV_EVENT_FLAG_SHIFTKEY;
878 if (modifiers& cmdKey ) flags += CV_EVENT_FLAG_ALTKEY;
880 if (window->on_mouse != NULL){
882 Rect structure, content;
883 GetWindowBounds(theWindow, kWindowStructureRgn, &structure);
884 GetWindowBounds(theWindow, kWindowContentRgn, &content);
885 lx = (int)point.x - content.left + structure.left;
886 ly = (int)point.y - window->trackbarheight - content.top + structure.top; /* minus la taille des trackbars */
887 if (window->flags & CV_WINDOW_AUTOSIZE) {//FD
888 //printf("was %d,%d\n", lx, ly);
889 /* scale the mouse coordinates */
890 lx = lx * window->imageWidth / (content.right - content.left);
891 ly = ly * window->imageHeight / (content.bottom - content.top - window->trackbarheight);
894 if (lx>0 && ly >0){ /* a remettre dans les coordonnées locale */
895 window->on_mouse (event, lx, ly, flags, window->on_mouse_param);
900 default : return eventNotHandledErr;
903 case kEventClassWindow : {//FD
905 case kEventWindowBoundsChanged :
907 /* resize the trackbars */
910 GetWindowBounds(window->window,kWindowContentRgn,&bounds);
911 for ( t = window->toolbar.first; t != 0; t = t->next )
912 SizeControl(t->trackbar,bounds.right - bounds.left - INTERWIDGETSPACE*3 - LABELWIDTH , WIDGETHEIGHT);
914 /* redraw the image */
915 icvDrawImage(window);
918 return eventNotHandledErr;
922 return eventNotHandledErr;
925 return eventNotHandledErr;
928 OSStatus keyHandler(EventHandlerCallRef hcr, EventRef theEvent, void* inUserData)
934 eventKind = GetEventKind (theEvent);
935 eventClass = GetEventClass (theEvent);
936 err = GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(lastKey), NULL, &lastKey);
943 CV_IMPL int cvWaitKey (int maxWait)
945 EventRecord theEvent;
947 // wait at least for one event (to allow mouse, etc. processing), exit if maxWait milliseconds passed (nullEvent)
948 UInt32 start = TickCount();
952 // remaining time until maxWait is over
953 UInt32 wait = EventTimeToTicks (maxWait / 1000.0) - (TickCount() - start);
956 if( maxWait > 0 && iters > 0 )
961 WaitNextEvent (everyEvent, &theEvent, maxWait > 0 ? wait : kDurationForever, NULL);
963 while (lastKey == NO_KEY && theEvent.what != nullEvent);