/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, // copy or use the software. // // // Intel License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000, Intel Corporation, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistribution's of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistribution's in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * The name of Intel Corporation may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and // any express or implied warranties, including, but not limited to, the implied // warranties of merchantability and fitness for a particular purpose are disclaimed. // In no event shall the Intel Corporation or contributors be liable for any direct, // indirect, incidental, special, exemplary, or consequential damages // (including, but not limited to, procurement of substitute goods or services; // loss of use, data, or profits; or business interruption) however caused // and on any theory of liability, whether in contract, strict liability, // or tort (including negligence or otherwise) arising in any way out of // the use of this software, even if advised of the possibility of such damage. // //M*/ #include "_highgui.h" #include #include #include #include //#define MS_TO_TICKS(a) a*3/50 #define LABELWIDTH 64 #define INTERWIDGETSPACE 16 #define WIDGETHEIGHT 32 #define NO_KEY -1 struct CvWindow; typedef struct CvTrackbar { int signature; ControlRef trackbar; ControlRef label; char* name; CvTrackbar* next; CvWindow* parent; int* data; int pos; int maxval; CvTrackbarCallback notify; } CvTrackbar; typedef struct CvWindow { int signature; char* name; CvWindow* prev; CvWindow* next; WindowRef window; CGImageRef imageRef; int imageWidth;//FD int imageHeight;//FD CvMat* image; CvMat* dst_image; int converted; int last_key; int flags; CvMouseCallback on_mouse; void* on_mouse_param; struct { int pos; int rows; CvTrackbar* first; } toolbar; int trackbarheight; } CvWindow; static CvWindow* hg_windows = 0; #define Assert(exp) \ if( !(exp) ) \ { \ printf("Assertion: %s %s: %d\n", #exp, __FILE__, __LINE__);\ assert(exp); \ } static int wasInitialized = 0; static char lastKey = NO_KEY; OSStatus keyHandler(EventHandlerCallRef hcr, EventRef theEvent, void* inUserData); static pascal OSStatus windowEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *inUserData); static const EventTypeSpec applicationKeyboardEvents[] = { { kEventClassKeyboard, kEventRawKeyDown }, }; CV_IMPL int cvInitSystem( int argc, char** argv ) { OSErr err = noErr; if( !wasInitialized ) { hg_windows = 0; err = InstallApplicationEventHandler(NewEventHandlerUPP( keyHandler),GetEventTypeCount(applicationKeyboardEvents),applicationKeyboardEvents,NULL,NULL); if (err != noErr) { fprintf(stderr,"InstallApplicationEventHandler was not ok\n"); } wasInitialized = 1; } return 0; } // TODO: implement missing functionality CV_IMPL int cvStartWindowThread() { return 0; } static int icvCountTrackbarInWindow( const CvWindow* window) { CvTrackbar* trackbar = window->toolbar.first; int count = 0; while (trackbar != 0) { count++; trackbar = trackbar->next; } return count; } static CvTrackbar* icvTrackbarByHandle( void * handle ) { CvWindow* window = hg_windows; CvTrackbar* trackbar = NULL; while( window != 0 && window->window != handle) { trackbar = window->toolbar.first; while (trackbar != 0 && trackbar->trackbar != handle) trackbar = trackbar->next; if (trackbar != 0 && trackbar->trackbar == handle) break; window = window->next; } return trackbar; } static CvWindow* icvWindowByHandle( void * handle ) { CvWindow* window = hg_windows; while( window != 0 && window->window != handle) window = window->next; return window; } CV_IMPL CvWindow * icvFindWindowByName( const char* name) { CvWindow* window = hg_windows; while( window != 0 && strcmp(name, window->name) != 0 ) window = window->next; return window; } static CvTrackbar* icvFindTrackbarByName( const CvWindow* window, const char* name ) { CvTrackbar* trackbar = window->toolbar.first; while (trackbar != 0 && strcmp( trackbar->name, name ) != 0) trackbar = trackbar->next; return trackbar; } //FD /* draw image to frame */ static void icvDrawImage( CvWindow* window ) { Assert( window != 0 ); if( window->imageRef == 0 ) return; CGContextRef myContext; CvTrackbar* t; CGRect rect; Rect portrect; int width = window->imageWidth; int height = window->imageHeight; GetWindowPortBounds(window->window, &portrect); if( window->flags & CV_WINDOW_AUTOSIZE ) { CGPoint origin = {0,0}; CGSize size = {portrect.right-portrect.left, portrect.bottom-portrect.top-window->trackbarheight}; rect.origin = origin; rect.size = size; } else { CGPoint origin = {0, portrect.bottom - height - window->trackbarheight}; CGSize size = {width, height}; rect.origin = origin; rect.size = size; } /* 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*/ SetPortWindowPort (window->window); QDBeginCGContext (GetWindowPort (window->window), &myContext); CGContextSetInterpolationQuality (myContext, kCGInterpolationLow); CGContextDrawImage(myContext,rect,window->imageRef); CGContextFlush(myContext);// 4 QDEndCGContext (GetWindowPort(window->window), &myContext);// 5 } //FD /* update imageRef */ static void icvPutImage( CvWindow* window ) { Assert( window != 0 ); if( window->image == 0 ) return; CGColorSpaceRef colorspace = NULL; CGDataProviderRef provider = NULL; int width = window->imageWidth = window->image->cols; int height = window->imageHeight = window->image->rows; colorspace = CGColorSpaceCreateDeviceRGB(); int size = 8; int nbChannels = 3; provider = CGDataProviderCreateWithData(NULL, window->image->data.ptr, width * height , NULL ); if (window->imageRef != NULL){ CGImageRelease(window->imageRef); window->image == NULL; } window->imageRef = CGImageCreate( width, height, size , size*nbChannels , window->image->step, colorspace, kCGImageAlphaNone , provider, NULL, true, kCGRenderingIntentDefault ); icvDrawImage( window ); } static void icvUpdateWindowSize( const CvWindow* window ) { int width = 0, height = 240; /* init ˆ al taille de base de l'image*/ CvTrackbar* t; Rect globalBounds; GetWindowBounds(window->window, kWindowContentRgn, &globalBounds); int minWidth = 320; if( window->image ) { width = MAX(MAX(window->image->width, width), minWidth); height = window->image->height; } else width = minWidth; height += window->trackbarheight; //height +=WIDGETHEIGHT; /* 32 pixels are spearating tracbars from the video display */ globalBounds.right = globalBounds.left + width; globalBounds.bottom = globalBounds.top + height; SetWindowBounds(window->window, kWindowContentRgn, &globalBounds); } static void icvDeleteWindow( CvWindow* window ) { CvTrackbar* trackbar; if( window->prev ) window->prev->next = window->next; else hg_windows = window->next; if( window->next ) window->next->prev = window->prev; window->prev = window->next = 0; cvReleaseMat( &window->image ); cvReleaseMat( &window->dst_image ); for( trackbar = window->toolbar.first; trackbar != 0; ) { CvTrackbar* next = trackbar->next; cvFree( (void**)&trackbar ); trackbar = next; } if (window->imageRef != NULL) CGImageRelease(window->imageRef); cvFree( (void**)&window ); } CV_IMPL void cvDestroyWindow( const char* name) { CV_FUNCNAME( "cvDestroyWindow" ); __BEGIN__; CvWindow* window; if(!name) CV_ERROR( CV_StsNullPtr, "NULL name string" ); window = icvFindWindowByName( name ); if( !window ) EXIT; icvDeleteWindow( window ); __END__; } CV_IMPL void cvDestroyAllWindows( void ) { while( hg_windows ) { CvWindow* window = hg_windows; icvDeleteWindow( window ); } } CV_IMPL void cvShowImage( const char* name, const CvArr* arr) { CV_FUNCNAME( "cvShowImage" ); __BEGIN__; CvWindow* window; int origin = 0; int resize = 0; CvMat stub, *image; if( !name ) CV_ERROR( CV_StsNullPtr, "NULL name" ); window = icvFindWindowByName(name); if( !window || !arr ) EXIT; // keep silence here. if( CV_IS_IMAGE_HDR( arr )) origin = ((IplImage*)arr)->origin; CV_CALL( image = cvGetMat( arr, &stub )); /* if( !window->image ) cvResizeWindow( name, image->cols, image->rows ); */ if( window->image && !CV_ARE_SIZES_EQ(window->image, image) ) { if ( ! (window->flags & CV_WINDOW_AUTOSIZE) )//FD resize = 1; cvReleaseMat( &window->image ); } if( !window->image ) { resize = 1;//FD window->image = cvCreateMat( image->rows, image->cols, CV_8UC3 ); } cvConvertImage( image, window->image, (origin != 0 ? CV_CVTIMG_FLIP : 0) + CV_CVTIMG_SWAP_RB ); icvPutImage( window ); if ( resize )//FD icvUpdateWindowSize( window ); __END__; } CV_IMPL void cvResizeWindow( const char* name, int width, int height) { CV_FUNCNAME( "cvResizeWindow" ); __BEGIN__; CvWindow* window; //CvTrackbar* trackbar; if( !name ) CV_ERROR( CV_StsNullPtr, "NULL name" ); window = icvFindWindowByName(name); if(!window) EXIT; SizeWindow(window->window, width, height, true); __END__; } CV_IMPL void cvMoveWindow( const char* name, int x, int y) { CV_FUNCNAME( "cvMoveWindow" ); __BEGIN__; CvWindow* window; //CvTrackbar* trackbar; if( !name ) CV_ERROR( CV_StsNullPtr, "NULL name" ); window = icvFindWindowByName(name); if(!window) EXIT; MoveWindow(window->window, x, y, true); __END__; } void TrackbarActionProcPtr (ControlRef theControl, ControlPartCode partCode) { CvTrackbar * trackbar = icvTrackbarByHandle (theControl); if (trackbar == NULL) { fprintf(stderr,"Erreur recuperation trackbar\n"); return; } else { if ( trackbar->data ) *trackbar->data = GetControl32BitValue (theControl); if ( trackbar->notify ) trackbar->notify(GetControl32BitValue (theControl)); } } CV_IMPL int cvCreateTrackbar (const char* trackbar_name, const char* window_name,int* val, int count, CvTrackbarCallback on_notify) { int result = 0; CV_FUNCNAME( "cvCreateTrackbar" ); __BEGIN__; /*char slider_name[32];*/ CvWindow* window = 0; CvTrackbar* trackbar = 0; Rect stboundsRect; ControlRef outControl; ControlRef stoutControl; Rect bounds; if( !window_name || !trackbar_name ) CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" ); if( count <= 0 ) CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" ); window = icvFindWindowByName(window_name); if( !window ) EXIT; trackbar = icvFindTrackbarByName(window,trackbar_name); if( !trackbar ) { int len = strlen(trackbar_name); trackbar = (CvTrackbar*)cvAlloc(sizeof(CvTrackbar) + len + 1); memset( trackbar, 0, sizeof(*trackbar)); trackbar->signature = CV_TRACKBAR_MAGIC_VAL; trackbar->name = (char*)(trackbar+1); memcpy( trackbar->name, trackbar_name, len + 1 ); trackbar->parent = window; trackbar->next = window->toolbar.first; window->toolbar.first = trackbar; if( val ) { int value = *val; if( value < 0 ) value = 0; if( value > count ) value = count; trackbar->pos = value; trackbar->data = val; } trackbar->maxval = count; trackbar->notify = on_notify; int c = icvCountTrackbarInWindow(window); GetWindowBounds(window->window,kWindowContentRgn,&bounds); stboundsRect.top = (INTERWIDGETSPACE +WIDGETHEIGHT)* (c-1)+INTERWIDGETSPACE; stboundsRect.left = INTERWIDGETSPACE; stboundsRect.bottom = stboundsRect.top + WIDGETHEIGHT; stboundsRect.right = stboundsRect.left+LABELWIDTH; fprintf(stdout,"create trackabar bounds (%d %d %d %d)\n",stboundsRect.top,stboundsRect.left,stboundsRect.bottom,stboundsRect.right); CreateStaticTextControl (window->window,&stboundsRect,CFStringCreateWithCString(NULL,trackbar_name,kCFStringEncodingASCII),NULL,&stoutControl); stboundsRect.top = (INTERWIDGETSPACE +WIDGETHEIGHT)* (c-1)+INTERWIDGETSPACE; stboundsRect.left = INTERWIDGETSPACE*2+LABELWIDTH; stboundsRect.bottom = stboundsRect.top + WIDGETHEIGHT; stboundsRect.right = bounds.right-INTERWIDGETSPACE; CreateSliderControl (window->window,&stboundsRect, trackbar->pos,0,trackbar->maxval,kControlSliderLiveFeedback,0,true,NewControlActionUPP(TrackbarActionProcPtr),&outControl); bounds.bottom += INTERWIDGETSPACE + WIDGETHEIGHT; SetControlVisibility (outControl,true,true); SetControlVisibility (stoutControl,true,true); trackbar->trackbar = outControl; trackbar->label = stoutControl; if (c == 1) window->trackbarheight = INTERWIDGETSPACE*2 + WIDGETHEIGHT; else window->trackbarheight += INTERWIDGETSPACE + WIDGETHEIGHT; icvUpdateWindowSize( window ); } __END__; return result; } CV_IMPL void cvSetMouseCallback( const char* name, CvMouseCallback function, void* info) { CvWindow* window = icvFindWindowByName( name ); if (window != NULL) { window->on_mouse = function; window->on_mouse_param = info; } else { fprintf(stdout,"Une erreur lors de cvSetMouseCallback, window nom trouvee : %s",name); } } CV_IMPL int cvGetTrackbarPos( const char*, const char* ) { //CV_NO_GTK_ERROR( "cvGetTrackbarPos" ); return -1; } CV_IMPL void cvSetTrackbarPos( const char*, const char*, int ) { // CV_NO_GTK_ERROR( "cvSetTrackbarPos" ); return ; } CV_IMPL void* cvGetWindowHandle( const char* name ) { WindowRef result = 0; CV_FUNCNAME( "cvGetWindowHandle" ); __BEGIN__; CvWindow* window; window = icvFindWindowByName( name ); if (window != NULL) result = window->window; else result = NULL; __END__; return NULL; } CV_IMPL const char* cvGetWindowName( void* window_handle ) { const char* window_name = ""; CV_FUNCNAME( "cvGetWindowName" ); __BEGIN__; CvWindow* window; if( window_handle == 0 ) CV_ERROR( CV_StsNullPtr, "NULL window" ); window = icvWindowByHandle(window_handle ); if( window ) window_name = window->name; __END__; return window_name; } CV_IMPL int cvNamedWindow( const char* name, int flags ) { int result = 0; CV_FUNCNAME( "cvNamedWindow" ); if (!wasInitialized) cvInitSystem(0, NULL); // to be able to display a window, we need to be a 'faceful' application // http://lists.apple.com/archives/carbon-dev/2005/Jun/msg01414.html static bool switched_to_faceful = false; if (! switched_to_faceful) { ProcessSerialNumber psn = { 0, kCurrentProcess }; OSStatus ret = TransformProcessType (&psn, kProcessTransformToForegroundApplication ); if (ret == noErr) { SetFrontProcess( &psn ); switched_to_faceful = true; } else { fprintf(stderr, "Failed to tranform process type: %d\n", (int) ret); fflush (stderr); } } __BEGIN__; WindowRef outWindow = NULL; OSStatus err = noErr; Rect contentBounds = {100,100,320,440}; CvWindow* window; UInt wAttributes = 0; int len; const EventTypeSpec genericWindowEventHandler[] = { { kEventClassMouse, kEventMouseMoved}, { kEventClassMouse, kEventMouseUp}, { kEventClassMouse, kEventMouseDown}, { kEventClassWindow, kEventWindowClose }, { kEventClassWindow, kEventWindowBoundsChanged }//FD }; if( !name ) CV_ERROR( CV_StsNullPtr, "NULL name string" ); if( icvFindWindowByName( name ) != 0 ){ result = 1; EXIT; } len = strlen(name); CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1)); memset( window, 0, sizeof(*window)); window->name = (char*)(window + 1); memcpy( window->name, name, len + 1 ); window->flags = flags; window->signature = CV_WINDOW_MAGIC_VAL; window->image = 0; window->last_key = 0; window->on_mouse = 0; window->on_mouse_param = 0; window->next = hg_windows; window->prev = 0; if( hg_windows ) hg_windows->prev = window; hg_windows = window; wAttributes = kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute; err = CreateNewWindow ( kDocumentWindowClass,wAttributes,&contentBounds,&outWindow); if (err != noErr) fprintf(stderr,"Erreur while creating the window\n"); SetWindowTitleWithCFString(outWindow,CFStringCreateWithCString(NULL,name,kCFStringEncodingASCII)); if (err != noErr) fprintf(stdout,"Erreur SetWindowTitleWithCFString\n"); window->window = outWindow; err = InstallWindowEventHandler(outWindow, NewEventHandlerUPP(windowEventHandler), GetEventTypeCount(genericWindowEventHandler), genericWindowEventHandler, outWindow, NULL); ShowWindow( outWindow ); result = 1; __END__; return result; } static pascal OSStatus windowEventHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *inUserData) { CvWindow* window = NULL; UInt32 eventKind, eventClass; OSErr err = noErr; int event = 0; UInt32 count = 0; HIPoint point = {0,0}; EventMouseButton eventMouseButton = 0;//FD UInt32 modifiers;//FD WindowRef theWindow = (WindowRef)inUserData; if (theWindow == NULL) return eventNotHandledErr; window = icvWindowByHandle(theWindow); if ( window == NULL) return eventNotHandledErr; eventKind = GetEventKind(theEvent); eventClass = GetEventClass(theEvent); switch (eventClass) { case kEventClassMouse : { switch (eventKind){ case kEventMouseUp : case kEventMouseDown : case kEventMouseMoved : { err = CallNextEventHandler(nextHandler, theEvent); if (err != eventNotHandledErr) return err; err = GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(eventMouseButton), NULL, &eventMouseButton); err = GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); err = GetEventParameter(theEvent,kEventParamClickCount,typeUInt32,NULL,sizeof(UInt32),NULL,&count); if (err == noErr){ if (count >1) event += 6; } else { event = CV_EVENT_MOUSEMOVE; } if (eventKind == kEventMouseUp) event +=4; if (eventKind == kEventMouseDown) event +=1; err = GetEventParameter(theEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point); if (eventKind != kEventMouseMoved){ switch(eventMouseButton){ case kEventMouseButtonPrimary: if (modifiers & controlKey) /* ctrl-click for right button */ event += 1; break; case kEventMouseButtonSecondary: event += 1; break; case kEventMouseButtonTertiary: event += 2; break; } } int c = icvCountTrackbarInWindow(window); if (window->on_mouse != NULL){ int lx,ly; Rect structure, content; GetWindowBounds(theWindow, kWindowStructureRgn, &structure); GetWindowBounds(theWindow, kWindowContentRgn, &content); lx = point.x - content.left + structure.left; ly = point.y - window->trackbarheight - content.top + structure.top; /* minus la taille des trackbars */ if (window->flags & CV_WINDOW_AUTOSIZE) {//FD //printf("was %d,%d\n", lx, ly); /* scale the mouse coordinates */ lx = lx * window->imageWidth / (content.right - content.left); ly = ly * window->imageHeight / (content.bottom - content.top - window->trackbarheight); //printf("now %d,%d\n", lx, ly); } //fprintf(stdout,"final OpenCV event is %d\n",event); //fprintf(stdout,"event @ %d %d which is localy %d %d offset of %d\n",point.h, point.v ,lx,ly,yOffset); if (lx>0 && ly >0){ /* a remettre dans les coordonnŽes locale */ window->on_mouse(event,lx,ly,0,NULL); } } } default : return eventNotHandledErr; } } case kEventClassWindow : {//FD switch (eventKind){ case kEventWindowBoundsChanged : { /* resize the trackbars */ CvTrackbar *t; Rect bounds; GetWindowBounds(window->window,kWindowContentRgn,&bounds); for ( t = window->toolbar.first; t != 0; t = t->next ) SizeControl(t->trackbar,bounds.right - bounds.left - INTERWIDGETSPACE*3 - LABELWIDTH , WIDGETHEIGHT); } /* redraw the image */ icvDrawImage(window); break; default : return eventNotHandledErr; } } default: return eventNotHandledErr; } return eventNotHandledErr; } OSStatus keyHandler(EventHandlerCallRef hcr, EventRef theEvent, void* inUserData) { UInt32 eventKind; UInt32 eventClass; OSErr err = noErr; eventKind = GetEventKind (theEvent); eventClass = GetEventClass (theEvent); err = GetEventParameter(theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(lastKey), NULL, &lastKey); if (err != noErr) lastKey = NO_KEY; return noErr; } CV_IMPL int cvWaitKey (int maxWait) { EventRecord theEvent; // wait at least for one event (to allow mouse, etc. processing), exit if maxWait milliseconds passed (nullEvent) UInt32 start = TickCount(); do { // remaining time until maxWait is over UInt32 wait = EventTimeToTicks (maxWait / 1000.0) - (TickCount() - start); if (wait < 0) wait = 0; WaitNextEvent (everyEvent, &theEvent, maxWait > 0 ? wait : kDurationForever, NULL); } while (lastKey == NO_KEY && theEvent.what != nullEvent); int key = lastKey; lastKey = NO_KEY; return key; } /* End of file. */