int MosMain(void)
{
   MIL_ID       MilApplication,       /* Application Identifier.  */
                MilSystem,            /* System Identifier.       */
                MilDisplay,           /* Display Identifier.      */
                MilImage;             /* Image buffer Identifier. */
   long         ReturnValue;          /* Return Value holder.     */
   MIL_DOUBLE   SynchronousCallTime,  /* Timer variable.          */
                AsynchronousCallTime; /* Timer variable.          */
   int          n;                    /* Counter.                 */
   
   /* Allocate application, system and display. */
   MappAlloc(M_DEFAULT, &MilApplication);
   MsysAlloc(SLAVE_SYSTEM_DESCRIPTOR, M_DEF_SYSTEM_NUM, M_SETUP, &MilSystem);
   MdispAlloc(MilSystem, M_DEV0, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay);

   /* Restore source image into an automatically allocated image buffer. */
   MbufRestore(IMAGE_FILE, MilSystem, &MilImage);
  
   /* Uncomment to display the image.    */
   /* MdispSelect(MilDisplay, MilImage); */
   
   /* Pause */
   MosPrintf(MIL_TEXT("\nMIL DTK:\n"));
   MosPrintf(MIL_TEXT("--------\n\n"));
   MosPrintf(MIL_TEXT("Custom synchronous and asynchronous MIL functions:\n\n"));
   MosPrintf(MIL_TEXT("This example times a synchronous and asynchronous custom function call.\n"));
   MosPrintf(MIL_TEXT("Press a key to continue.\n\n"));
   MosGetch();

   /* Synchronous function call. */
   /* -------------------------- */

   /* Call the function a first time for more accurate timings later (dll load, ...). */
   ReturnValue = SynchronousFunction(MilImage, MilImage, M_DEFAULT);

   /* Start the timer */
   MappTimer(M_TIMER_RESET+M_SYNCHRONOUS, M_NULL);

   /* Loop many times for more precise timing. */
   for (n= 0; n < NB_LOOP; n++)
      {
      /* Call the custom MIL synchronous function. */
      ReturnValue = SynchronousFunction(MilImage, MilImage, M_DEFAULT);
      }

   /* Read the timer. */
   MappTimer(M_TIMER_READ+M_SYNCHRONOUS, &SynchronousCallTime);

   /* Print the synchronous call time. */
   MosPrintf(MIL_TEXT("Synchronous  function call time: %.1f us.\n"), SynchronousCallTime*1000000/NB_LOOP);

   /* Asynchronous function call. */
   /* --------------------------- */

   /* Call the function a first time for more accurate timings later (dll load, ...). */
  AsynchronousFunction(MilImage, MilImage, M_DEFAULT);
  MthrWait(M_DEFAULT, M_THREAD_WAIT, M_NULL);

   /* Start the timer */
   MappTimer(M_TIMER_RESET+M_SYNCHRONOUS, M_NULL);

   /* Loop many times for more precise timing. */
   for (n= 0; n < NB_LOOP; n++)
      {
      /* Call the custom MIL asynchronous function. */
      AsynchronousFunction(MilImage, MilImage, M_DEFAULT);
      }

   /* Read and print the time. */
   MappTimer(M_TIMER_READ+M_SYNCHRONOUS, &AsynchronousCallTime);
      
   /* Print the asynchronous call time. */
   MosPrintf(MIL_TEXT("Asynchronous function call time: %.1f us.\n"), AsynchronousCallTime*1000000/NB_LOOP);
   MosPrintf(MIL_TEXT("Press a key to terminate.\n\n"));
   MosGetch();

   /* Free all allocations. */
   MbufFree(MilImage);
   MdispFree(MilDisplay);
   MsysFree(MilSystem);
   MappFree(MilApplication);

   return 0;
}
Ejemplo n.º 2
0
void mexFunction(int nlhs, mxArray *plhs[],
				 int nrhs, const mxArray *prhs[] )
{
	// validate the command string
	if(nrhs < 1 || mxIsChar(prhs[0]) != 1 || mxGetM(prhs[0]) != 1) {
		mexErrMsgTxt("Missing command string.");
	}

	// get the command
	int cmdlen = mxGetN(prhs[0]) + 1;
	char* command = (char*)mxCalloc(cmdlen, sizeof(char));
	if(mxGetString(prhs[0], command, cmdlen) != 0) {
		mexErrMsgTxt("Get command string failed.");
	}

	// startup 
	if(strcmp(command, "init") == 0) {

		// set things up so a clear will also clean up
		mexAtExit(cleanup);

		if(nrhs > 1) {
			if(!mxIsChar(prhs[1]) || mxGetM(prhs[1]) != 1) {
				mexErrMsgTxt("init argument should be the name of a dcf file.");
			}
			int nmlen = mxGetN(prhs[1]) + 1;
			char* dcfname = (char*)mxCalloc(nmlen, sizeof(char));
			mxGetString(prhs[1], dcfname, nmlen);

			MappAllocDefault(M_SETUP, &MilApplication, &MilSystem,
				M_NULL, M_NULL, M_NULL);
			if(MdigAlloc(MilSystem, M_DEV0, dcfname, M_DEFAULT, &MilDigitizer) == M_NULL) {
				mexErrMsgTxt("init failed.");
			}
		} else {
			/* Allocate defaults. */
			MappAllocDefault(M_SETUP, &MilApplication, &MilSystem,
				M_NULL, &MilDigitizer, M_NULL);
		}
		MBands = (int)MdigInquire(MilDigitizer, M_SIZE_BAND, M_NULL);
		for(int i=0; i<MBands; i++)
			band_is_selected[i] = true;
		bands_selected = MBands;

		MappTimer(M_TIMER_RESET, M_NULL);

		grab_scale_x = grab_scale_y = 1;

		MdigControl(MilDigitizer, M_GRAB_MODE, M_ASYNCHRONOUS);
		MdigControl(MilDigitizer, M_GRAB_SCALE_X, grab_scale_x);
		MdigControl(MilDigitizer, M_GRAB_SCALE_Y, grab_scale_y);
		
	// wrapup
	} else if(strcmp(command, "quit") == 0) {
		cleanup();

	// set the x and y scaling factor
	} else if(strcmp(command, "setscale") == 0) {
		// check the parameters
		if(nrhs != 3 || !mxIsDouble(prhs[1]) || !mxIsDouble(prhs[2])) {
			mexErrMsgTxt("setscale expects 2 arguments.");
		}
		grab_scale_x = mxGetScalar(prhs[1]);
		grab_scale_y = mxGetScalar(prhs[2]);

		MdigControl(MilDigitizer, M_GRAB_SCALE_X, grab_scale_x);
		MdigControl(MilDigitizer, M_GRAB_SCALE_Y, grab_scale_y);

	// select which bands to return for multiband sources
	} else if(strcmp(command, "selectbands") == 0) {
		// check to see if it's legal
		if(MBands == 1) {
			mexErrMsgTxt("selectbands only works for multiband sources.");
		}
		// check the argument
		if(nrhs != 2 || !mxIsDouble(prhs[1]) || mxGetM(prhs[1]) != 1) {
			mexErrMsgTxt("selectbands expects a row vector of band numbers.");
		}
		int nbands = mxGetN(prhs[1]);
		if(nbands == 0 || nbands > MBands) {
			mexErrMsgTxt("selectbands allows only 1 to 3 bands.");
		}
		double* bp = mxGetPr(prhs[1]);
		for(int i=0; i<3; i++) {
			band_is_selected[i] = false;
		}
		bands_selected = 0;
		for(i=0; i<nbands; i++) {
			int bnd = int(bp[i]);
			if(bnd < 0 || bnd > 2) {
				mexErrMsgTxt("selectbands allows bands numbered 0 to 2.");
			}
			if(!band_is_selected[bnd]) {
				band_is_selected[bnd] = true;
				bands_selected++;
			}
		}
		
	// grab a sequence in one call
	} else if(strcmp(command, "grabframes") == 0) {
		// check the parameters
		if(nrhs < 4 || !mxIsDouble(prhs[1]) || !mxIsDouble(prhs[2]) || !mxIsDouble(prhs[3])) {
			mexErrMsgTxt("grabframes expects 3 or 4 arguments.");
		}
		int width = int(mxGetScalar(prhs[1]));
		int height = int(mxGetScalar(prhs[2]));
		int frames = int(mxGetScalar(prhs[3]));

		// indicates whether this is a continuation of a previous grab
		bool grab_continue = false;
		if(nrhs == 5 && mxIsDouble(prhs[4]) && mxGetScalar(prhs[4]) > 0) {
			grab_continue = true;
		}

		// space to record per frame times if requested
		mxArray *time_array = 0;
		double* time_data = 0;
		if(nlhs > 1) {
			time_array = mxCreateDoubleMatrix(frames, 1, mxREAL);
			time_data = mxGetPr(time_array);
		}

		// allocate a matlab multidimensional array to return the image
		int dims[4];
		int ndims = 3;
		dims[0] = height;
		dims[1] = width;
		if(bands_selected > 1) {
			dims[2] = bands_selected;
			dims[3] = frames;
			ndims = 4;
		} else {
			dims[2] = frames;
		}
		mxArray *res = mxCreateNumericArray(ndims, dims, mxUINT8_CLASS, mxREAL);
		int frameelements = width*height*MBands;
		unsigned char* pmat = (unsigned char*)mxGetPr(res);

		// free buffers if they are the wrong size
		if(MilImageX != 0 && (width != MilImageX || height != MilImageY)) {
			MdigGrabWait(MilDigitizer, M_GRAB_END);
			for(int n=0; n<nmilbuff; n++) {
				MbufFree(MilImage[n]);
			}
			MilImageX = MilImageY = 0;
		}
		// allocate a few MIL buffers if we don't already have them
		if(MilImageX == 0) {
			for (int n=0; n<nmilbuff; n++)
			{
				MbufAllocColor(MilSystem,  
					MBands,
					width,
					height,
					8L+M_UNSIGNED, 
					M_IMAGE+M_GRAB, &MilImage[n]);
				if (MilImage[n] == 0)                     
				{
					mexErrMsgTxt("MbufAllocColor failed.");
				}
			}
			MilImageX = width;
			MilImageY = height;
		}

		// grab the frames
		if(!grab_continue) {
			// if you're not continuing a previous grab, then you want a fresh first frame
			MdigGrab(MilDigitizer, MilImage[MilImageNdx]);
		}
		for(int i = 0; i < frames; i++)
		{
			int ndx0 = MilImageNdx;
			MilImageNdx = (MilImageNdx + 1) % nmilbuff;
			MdigGrab(MilDigitizer, MilImage[MilImageNdx]);
			if(time_array)
				MappTimer(M_TIMER_READ, &time_data[i]);
			
			// copy the completed buff to the matlab array
			if(MBands == 1) { // easy
				// get a pointer to the buffer
				unsigned char* pmil;
				MbufInquire(MilImage[ndx0], M_HOST_ADDRESS, &pmil);
				if(pmil == M_NULL) {
					mexErrMsgTxt("no access to mil buffer.");
				}

				// copy the pixels exchanging x and y coordinates to suit matlab
				for(int y=0; y<height; y++) {
					for(int x=0; x<width; x++) {
						pmat[y+x*height] = pmil[x+y*width];
					}
				}
				pmat += width*height;

			} else { // harder
				// I bet there is some smarter way to do this...
				// for each band
				for(int b=0; b<MBands; b++) {
					if(band_is_selected[b]) {
						// allocate a child buffer on the band.
						MIL_ID child = MbufChildColor(MilImage[ndx0], b, M_NULL);
						if(child == M_NULL) {
							mexErrMsgTxt("no child");
						}
						// get a pointer to the child
						unsigned char* pmil;
						MbufInquire(child, M_HOST_ADDRESS, &pmil);
						if(pmil == M_NULL) {
							MbufFree(child);
							mexErrMsgTxt("no access to mil buffer.");
						}
						// do the copy, twizzling the indicies around...
						for(int y=0; y<height; y++) {
							for(int x=0; x<width; x++) {
								pmat[(y + x*height)] = pmil[x+y*width];
							}
						}
						pmat += width*height;

						// release the child
						MbufFree(child);
					}
				}
			}
		}

		plhs[0] = res;
		if(time_array)
			plhs[1] = time_array;

	} else {
		mexErrMsgTxt("Unknown command string.");
	}

}  
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID EventId, void MPTYPE *CallBackDataPtr)
   {
   /* Get the grabbed buffer. */
   ProcessingDataStruct *ProcessingDataPtr = (ProcessingDataStruct *)CallBackDataPtr;
   MIL_ID CurrentProcSrcBufId, CurrentProcDstBufId; 
   MIL_ID GrabbedBufferId;
   MIL_INT GrabbedBufferIndex;
   MIL_TEXT_CHAR Text[BUFFER_MAX_STRING_LENGTH];
   MIL_DOUBLE RectHalfSizeStep = 0.0;
   long RectStep = 0;
   long NbSystem = ProcessingDataPtr->NbSystem;
   long NbProcInitial = ProcessingDataPtr->NbProc;
   long NbBufferToProcess, n;

   /* Retrieve the buffer to process and it's index */
   MdigGetHookInfo(EventId, M_MODIFIED_BUFFER+M_BUFFER_ID,    &GrabbedBufferId);
   MdigGetHookInfo(EventId, M_MODIFIED_BUFFER+M_BUFFER_INDEX, &GrabbedBufferIndex);

   /* Reset the timer. */
   if (ProcessingDataPtr->NbProc == 0)
      MappTimer(M_TIMER_RESET+M_SYNCHRONOUS,&ProcessingDataPtr->Time);

   /* If PROCESS_EACH_IMAGE_ON_ALL_SYSTEMS is set, each grabbed image is processed on all the systems. 
      To have each frame processed only once by one system in round robin fashion, set the define to M_NO.  
   */
   if (ProcessingDataPtr->ProcessEachImageOnAllSystems)
      NbBufferToProcess = NbSystem;
   else
      NbBufferToProcess = 1;

   /* Dispatch the job to the target processing system(s) */ 
   for(n=0; n<NbBufferToProcess; n++)
      {
      /* Calculate target processing buffer. */
      CurrentProcSrcBufId = ProcessingDataPtr->SrcProcBufferListPtr[(ProcessingDataPtr->NbProc)%(NbSystem*BUFFER_PER_PROCESSOR)];
      CurrentProcDstBufId = ProcessingDataPtr->DstProcBufferListPtr[(ProcessingDataPtr->NbProc)%(NbSystem*BUFFER_PER_PROCESSOR)];

      /* Copy the grabbed buffer to a processing platform. */
      MbufCopy(GrabbedBufferId, CurrentProcSrcBufId);

      /* Draw the buffer index in the source. */
      MosSprintf(Text, BUFFER_MAX_STRING_LENGTH, MIL_TEXT("#%ld."), ProcessingDataPtr->NbProc);
      MgraText(M_DEFAULT, CurrentProcSrcBufId, 50, 50, Text);

      /* Process the buffer. */
      #if (!M_MIL_LITE)
          {
          MimArith(CurrentProcSrcBufId, 0x10, CurrentProcDstBufId, M_SUB_CONST+M_SATURATION);
          MimArith(CurrentProcDstBufId, M_NULL, CurrentProcSrcBufId, M_NOT);
          MimRotate(CurrentProcSrcBufId, CurrentProcDstBufId,
                    (ProcessingDataPtr->NbProc*10)%360, 
                    (MIL_DOUBLE) ProcessingDataPtr->SizeX/2,
                    (MIL_DOUBLE) ProcessingDataPtr->SizeY/2,
                    (MIL_DOUBLE) ProcessingDataPtr->SizeX/2,
                    (MIL_DOUBLE) ProcessingDataPtr->SizeY/2,
                    M_NEAREST_NEIGHBOR);
          }
      #else
         {
         RectStep = (ProcessingDataPtr->NbProc % BUFFER_DRAW_RECT_NUMBER);
          if(RectStep < BUFFER_DRAW_INWARD_STEP_NUMBER)
             RectHalfSizeStep = RectStep * BUFFER_DRAW_RECT_STEP;
          else
             RectHalfSizeStep = (BUFFER_DRAW_RECT_NUMBER - RectStep) * BUFFER_DRAW_RECT_STEP;

          MgraColor(M_DEFAULT, 0xff);
          MgraRectFill(M_DEFAULT,
                       CurrentProcDstBufId,
                       ProcessingDataPtr->SizeX/2 - RectHalfSizeStep,
                       ProcessingDataPtr->SizeY/2 - RectHalfSizeStep,
                       ProcessingDataPtr->SizeX/2 + RectHalfSizeStep,
                       ProcessingDataPtr->SizeY/2 + RectHalfSizeStep);
         }
      #endif

      /* Count processed buffers. */
      ProcessingDataPtr->NbProc++;
      MosPrintf(MIL_TEXT("Processing #%ld.\r"), ProcessingDataPtr->NbProc);
      }
      
      /* If required, copy back the result buffers from the processing system(s) for display. */
      #if (DISPLAY_EACH_IMAGE_PROCESSED)
         {
         for(n=0; n<NbBufferToProcess; n++)
           {
           /* Calculate target buffer for display. */
           CurrentProcDstBufId = ProcessingDataPtr->DstProcBufferListPtr[(NbProcInitial+n)%(NbSystem*BUFFER_PER_PROCESSOR)];

           /* Copy result to display. */
           MbufCopy(CurrentProcDstBufId, ProcessingDataPtr->DispBuffer);
           } 
         }
      #endif

   /* Read the timer. */
   MappTimer(M_TIMER_READ+M_SYNCHRONOUS, &ProcessingDataPtr->Time);

   #if M_MIL_USE_CE
   /* Give execution time to user interface when the digitizer processing queue is full.
      If necessary, the Sleep value can be increased to give more execution time to user interface.
   */
   if(MdigInquire(ProcessingDataPtr->MilDigitizer, M_PROCESS_PENDING_GRAB_NUM, M_NULL) <= 1)
      {
      if ((ProcessingDataPtr->NbProc%10) == 0)
         Sleep(2);
      }
   #endif

   return(0);
   }