Beispiel #1
0
MdispQtApp::MdispQtApp( int& argc, char** argv )
    : QApplication( argc, argv )
    , m_isCurrentlyHookedOnErrors(false)
    , m_ErrorEventSemaphore(1)
    , m_CreatorThread( QThread::currentThreadId() )
{
    // Set semaphore to initial state (no error event available).
    m_ErrorEventSemaphore.acquire();

    // Allocate an application and system [CALL TO MIL]
    MappAllocDefault(M_DEFAULT, &m_MilApplication, &m_MilSystem, M_NULL, M_NULL, M_NULL);

    // Hook MIL error on function DisplayError() [CALL TO MIL]
    MappHookFunction(M_ERROR_CURRENT,DisplayErrorExt,M_NULL);

    m_isCurrentlyHookedOnErrors = true;

    // Disable MIL error message to be displayed as the usual way [CALL TO MIL]
    MappControl(M_ERROR,M_PRINT_DISABLE);

    // Inquire number of digitizers available on the system [CALL TO MIL]
    MsysInquire(m_MilSystem,M_DIGITIZER_NUM,&m_numberOfDigitizer);

    // Digitizer is available
    if (m_numberOfDigitizer)
    {
        // Allocate a digitizer [CALL TO MIL]
        MdigAlloc(m_MilSystem,M_DEFAULT,M_CAMERA_SETUP,M_DEFAULT,&m_MilDigitizer);

        // Stop live grab when window is disable [CALL TO MIL]
        //TBM MIL 8.0 MsysControl(MilSystem,M_STOP_LIVE_GRAB_WHEN_DISABLED,M_ENABLE);

        // Inquire digitizer informations [CALL TO MIL]
        MdigInquire(m_MilDigitizer,M_SIZE_X,&m_digitizerSizeX);
        MdigInquire(m_MilDigitizer,M_SIZE_Y,&m_digitizerSizeY);
        MdigInquire(m_MilDigitizer,M_SIZE_BAND,&m_digitizerNbBands);

        if (m_digitizerSizeX > M_DEF_IMAGE_SIZE_X_MAX)
            m_digitizerSizeX = M_DEF_IMAGE_SIZE_X_MAX;
        if (m_digitizerSizeY > M_DEF_IMAGE_SIZE_Y_MAX)
            m_digitizerSizeY = M_DEF_IMAGE_SIZE_Y_MAX;
    }
    // Digitizer is not available
    else
    {
        m_MilDigitizer = 0;
        m_digitizerNbBands  =   M_DEF_IMAGE_NUMBANDS_MIN;
    }


    // Initialize the state of the grab
    m_isGrabStarted = FALSE;

    // Initialize GUI
    MainFrame* mf = new MainFrame();
    //setMainWidget(mf);

    mf->show();

}
// Initialize camera input
bool CvCaptureCAM_MIL::open( int wIndex )
{
    close();

    if( g_Mil.MilApplication == M_NULL )
    {
        assert(g_Mil.MilUser == 0);
        MappAlloc(M_DEFAULT, &(g_Mil.MilApplication) );
        g_Mil.MilUser = 1;
    }
    else
    {
        assert(g_Mil.MilUser>0);
        g_Mil.MilUser++;
    }

    int dev_table[16] = { M_DEV0, M_DEV1, M_DEV2, M_DEV3,
        M_DEV4, M_DEV5, M_DEV6, M_DEV7,
        M_DEV8, M_DEV9, M_DEV10, M_DEV11,
        M_DEV12, M_DEV13, M_DEV14, M_DEV15 };

    //set default window size
    int w = 320;
    int h = 240;

    for( ; wIndex < 16; wIndex++ )
    {
        MsysAlloc( M_SYSTEM_SETUP, //we use default system,
                                   //if this does not work
                                   //try to define exact board
                                   //e.g.M_SYSTEM_METEOR,M_SYSTEM_METEOR_II...
                   dev_table[wIndex],
                   M_DEFAULT,
                   &MilSystem );

        if( MilSystem != M_NULL )
            break;
    }
    if( MilSystem != M_NULL )
    {
        MdigAlloc(MilSystem,M_DEFAULT,
                  M_CAMERA_SETUP, //default. May be M_NTSC or other
                  M_DEFAULT,&MilDigitizer);

        rgb_frame = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3 );
        MdigControl(MilDigitizer, M_GRAB_SCALE,  1.0 / 2);

        /*below line enables getting image vertical orientation
         consistent with VFW but it introduces some image corruption
         on MeteorII, so we left the image as is*/
        //MdigControl(MilDigitizer, M_GRAB_DIRECTION_Y, M_REVERSE );

        MilImage = MbufAllocColor(MilSystem, 3, w, h,
            8+M_UNSIGNED, M_IMAGE + M_GRAB, M_NULL);
    }

    return MilSystem != M_NULL;
}
Beispiel #3
0
bool MdispGtkApp::InitInstance()
   {
   // Allocate an application and system [CALL TO MIL]
   MappAllocDefault(M_DEFAULT, &m_MilApplication, &m_MilSystem, M_NULL, M_NULL, M_NULL);

   // Hook MIL error on function DisplayError() [CALL TO MIL]
   MappHookFunction(M_ERROR_CURRENT,DisplayErrorExt,this);

   m_isCurrentlyHookedOnErrors = true;
	
   // Disable MIL error message to be displayed as the usual way [CALL TO MIL]
   MappControl(M_ERROR,M_PRINT_DISABLE);
 
   // Inquire number of digitizers available on the system [CALL TO MIL]
   MsysInquire(m_MilSystem,M_DIGITIZER_NUM,&m_numberOfDigitizer);
	
   // Digitizer is available
   if (m_numberOfDigitizer)	
      {
      // Allocate a digitizer [CALL TO MIL]
      MdigAlloc(m_MilSystem,M_DEFAULT,M_CAMERA_SETUP,M_DEFAULT,&m_MilDigitizer);
		
      // Stop live grab when window is disable [CALL TO MIL]
    	//TBM MIL 8.0 MsysControl(MilSystem,M_STOP_LIVE_GRAB_WHEN_DISABLED,M_ENABLE);

		// Inquire digitizer informations [CALL TO MIL]
      MdigInquire(m_MilDigitizer,M_SIZE_X,&m_digitizerSizeX);
      MdigInquire(m_MilDigitizer,M_SIZE_Y,&m_digitizerSizeY);  	
      MdigInquire(m_MilDigitizer,M_SIZE_BAND,&m_digitizerNbBands);
   
      if (m_digitizerSizeX > M_DEF_IMAGE_SIZE_X_MAX) 
         m_digitizerSizeX = M_DEF_IMAGE_SIZE_X_MAX;
      if (m_digitizerSizeY > M_DEF_IMAGE_SIZE_Y_MAX) 
         m_digitizerSizeY = M_DEF_IMAGE_SIZE_Y_MAX;
      }
   else 
      {
      m_MilDigitizer=0;
      m_digitizerNbBands =	M_DEF_IMAGE_NUMBANDS_MIN;
      }

   // Initialize the state of the grab
   m_isGrabStarted = false;
   return true;
   }
/*************************** ini_control_digitalizador  *********************
	Función para reservar memoria para los diferentes formatos de
	digitalizadores que se utilizarán en la toma de imágenes.
	Previamente, se comprueba que los parámetros iniciales son válidos para
	el formato y tipo de digitalizador reservado.
	Seguidamente se reserva el display y los buffers que se utilizan en el
	proceso de adquisición de imágenes.
*****************************************************************************/
int ini_control_digitalizador(parametros *param)
{
	char	*fn = "ini_control_digitalizador - ";
	int		i;

	paramAux = param; //para usar en otras funciones

	//	SI DEFINO UN TAMAÑO DE DIGITALIZADOR DE ENFOQUE...	(DIGITALIZADOR)
	//	Reservo memoria para un nuevo display en el que se mostrarán los campos
	//	recorridos y los que se han podido enfocar. 
	if (param->Cam.formatoDig_e[0] != '\0' &&
		strcmp(param->Cam.formatoDig, param->Cam.formatoDig_e) )  
    {

		//	Configuro el digitalizador en formato enfoque
		if (M_digitalizador != M_NULL)
			libera_digitalizador();
		if ( MdigAlloc (M_sistema, M_DEV0, param->Cam.formatoDig_e, M_DEFAULT, &M_digitalizador)
			== M_NULL )  
        {
			error_fatal("ini_control_digitalizador", "Formato incorrecto", 0);
#if !defined (__BORLANDC__)
			putch('\a');
#endif
			return 1;
		}
		MdigInquire(M_digitalizador, M_SIZE_X, &limCam.anchoDig_e);
		if ( limCam.anchoDig_e > MAX_ANCHO_IMAGEN ||
				limCam.anchoDig_e < param->Cam.anchoImagen_e )  
        {
			error_fatal(fn, "Error en los parámetros iniciales", 0);
#if !defined (__BORLANDC__)
			putch('\a');
#endif
			return 1;
		}

		MdigInquire(M_digitalizador, M_SIZE_Y, &limCam.altoDig_e);
		if ( limCam.altoDig_e > MAX_ALTO_IMAGEN || 
                limCam.altoDig_e < param->Cam.altoImagen_e )  
        {
			error_fatal(fn, "Error en los parámetros iniciales", 0);
#if !defined (__BORLANDC__)
			putch('\a');
#endif
			return 1;
		}
	}


	//	Configuro el digitalizador en formato normal. 
	if (M_digitalizador != M_NULL)
		libera_digitalizador();

	if ( MdigAlloc (M_sistema, M_DEV0, param->Cam.formatoDig, M_DEFAULT, &M_digitalizador)
		== M_NULL )  {
		error_fatal("ini_control_proceso_imagenes", "Formato incorrecto", 0);
		return 1;
	}
	MdigInquire(M_digitalizador, M_SIZE_X, &limCam.anchoDig);
	if ( limCam.anchoDig > MAX_ANCHO_IMAGEN ||
			limCam.anchoDig < param->Cam.anchoImagen )  {
		error_fatal(fn, "Error en los parámetros iniciales", 0);
#if !defined (__BORLANDC__)
		putch('\a');
#endif
		return 1;
	}

	MdigInquire(M_digitalizador, M_SIZE_Y, &limCam.altoDig);
	if ( limCam.altoDig > MAX_ALTO_IMAGEN || 
            limCam.altoDig < param->Cam.altoImagen )  {
		error_fatal(fn, "Error en los parámetros iniciales", 0);
#if !defined (__BORLANDC__)
		putch('\a');
#endif
		return 1;
	}

	//	Si el formato del digitalizador de enfoque es el mismo que el de
	//	captura normal, copiamos las dimensiones porque no se leyeron. 
	if ( strcmp(param->Cam.formatoDig, param->Cam.formatoDig_e) == 0 )  {
		limCam.anchoDig_e = limCam.anchoDig;
		limCam.altoDig_e = limCam.altoDig;
	}

	//	Compruebo los valores iniciales de brillo, ganancia y exposición. 
	if ( info_digitalizador(M_digitalizador) )  {
		error_fatal(fn, "Error en los parámetros iniciales", 0);
		return 1;
	}

    // Se centra la camara en el caso de que se haya configurado un tamaño de toma diferente al maximo de la camara
	if ( configura_digitalizador(FORMATO_NORMAL) )  
        return 1;

	//	Buffer auxiliar de PROFUNDIDAD_ACUMULACION bits para acumular valores.
	MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, PROFUNDIDAD_ACUMULACION+M_UNSIGNED,
		M_IMAGE+M_DISP+M_PROC+M_GRAB, &M_imagen_acum);
	if ( M_imagen_acum == M_NULL )  {
		error_fatal(fn, "M_imagen_acum", 0);
		return 1;
	}

    // Obtenemos la profundidad de la camara
	MdigInquire(M_digitalizador, M_SIZE_BIT , &param->Cam.profundidad);

    if ( (BITS_CAMARA > 8 && param->Cam.profundidad <= 8) ||
         (BITS_CAMARA <= 8 && param->Cam.profundidad > 8) )
    {
		error_fatal(fn, "BITS_CAMARA (DEFINE en codigo) y profundidad camara no coherentes", 0);
		return 1;
	}

    //Si la profundidad no es de 8bit, hay que configurar el display.
    //El display siempre es de 8 bit
    if (param->Cam.profundidad == 16)
    {
        MdispControl(M_display_normal,M_VIEW_MODE,M_BIT_SHIFT);
        MdispControl(M_display_normal,M_VIEW_BIT_SHIFT,4); //despreciamos los 4 bits menos significativos
		MdispLut(M_display_normal, M_PSEUDO); //esto es necesario para que la intensidad no sea anormalmente elevada
    }

	//	Reservamos los buffers donde se almacenarán y procesarán las imágenes. 
	//	M_imagen1 será el buffer que normalmente estará asociado al display_normal.

	// En modo VGA no permite grabar datos en el buffer.
    long nSD_size;
    MsysInquire(M_sistema,M_SYSTEM_DESCRIPTOR_SIZE,&nSD_size);
    char* systemDescriptor = new char[nSD_size];
    MsysInquire(M_sistema,M_SYSTEM_DESCRIPTOR,systemDescriptor);
	if (systemDescriptor == M_SYSTEM_VGA)
		MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, param->Cam.profundidad+M_UNSIGNED,
			M_IMAGE+M_DISP+M_PROC, &M_imagen1 );
	else
		MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, param->Cam.profundidad+M_UNSIGNED,
			M_IMAGE+M_DISP+M_GRAB+M_PROC, &M_imagen1 );
    delete [ ] systemDescriptor;
	if ( M_imagen1 == M_NULL)  {
		error_fatal(fn, "M_imagen1", 0);
		return -1;
	}
	if ( M_imagen1 != M_NULL )  
    {
	//	Seleccionamos el display para imagen normal, asociando el overlay. 
#if !defined (__BORLANDC__)
	    configura_overlay(M_display_normal, M_imagen1, &M_overlay_normal, 1);
#else
	    configura_overlay(M_display_normal, M_imagen1, HWindow, &M_overlay_normal, 1);
        borra_buffer(M_imagen1, NEGRO, 0, 0, NULL, NULL);
#endif
/*
*/
	    if (param->Cam.anchoImagen != param->Cam.anchoImagen_e    || 
            param->Cam.altoImagen != param->Cam.altoImagen_e)  
        {
            // Reservo un child buffer de M_imagen1 con el tamaño de enfoque.
            MbufChild2d(M_imagen1, (param->Cam.anchoImagen - param->Cam.anchoImagen_e) /2,
                (param->Cam.altoImagen- param->Cam.altoImagen_e) /2,
                param->Cam.anchoImagen_e, param->Cam.altoImagen_e, &M_centro_imagen);
            if (M_centro_imagen == M_NULL)  
            {
                error_fatal(fn, "M_centro_imagen", 0);
                return -1;
		    }
        }
        else
            M_centro_imagen = M_imagen1;
	}

	MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, param->Cam.profundidad+M_UNSIGNED,
		M_IMAGE+M_DISP+M_PROC, &M_imagen2 );
	if ( M_imagen2 == M_NULL )  {
		error_fatal(fn, "M_imagen2", 0);
		return -1;
	}

	MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, param->Cam.profundidad+M_UNSIGNED,
		M_IMAGE+M_DISP+M_PROC, &M_imagen3);
	if ( M_imagen3 == M_NULL )  {
		error_fatal(fn, "M_imagen3", 0);
		return -1;
	}

	MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, param->Cam.profundidad+M_UNSIGNED,
		M_IMAGE+M_DISP+M_PROC, &M_imagen4);
	if ( M_imagen4 == M_NULL )  {
		error_fatal(fn, "M_imagen4", 0);
		return -1;
	}

	MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, param->Cam.profundidad+M_UNSIGNED,
		M_IMAGE+M_DISP+M_PROC, &M_imagen5);
	if ( M_imagen5 == M_NULL )  {
		error_fatal(fn, "M_imagen5", 0);
		return -1;
	}

	MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, param->Cam.profundidad+M_UNSIGNED,
		M_IMAGE+M_DISP+M_PROC, &M_imagen6);
	if ( M_imagen6 == M_NULL )  {
		error_fatal(fn, "M_imagen6", 0);
		return -1;
	}

	//	Reservo memoria para los buffers utilizados en la adquisición
	//	de las bandas y en la correccion de la iluminación.
	for (i=0; i < param->nBandas; i++) {
		MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, param->Cam.profundidad+M_UNSIGNED,
			M_IMAGE+M_DISP+M_PROC, &M_banda[i]);
		MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, 32+M_FLOAT,
			M_IMAGE+M_PROC, &M_correc_denom[i]);
		MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, 32+M_FLOAT,
			M_IMAGE+M_PROC, &M_correc_numer[i]);

		if ( M_banda[i] == M_NULL ||
				M_correc_numer[i] == M_NULL || M_correc_denom[i] == M_NULL )  {
			error_fatal(fn, "M_banda", 0);
			return 1;
		}
	}
    //El resto de filtros no usados a NULL
	for (; i < MAX_FILTROS_DTA; i++)
		M_banda[i] = M_correc_numer[i] = M_correc_denom[i] = M_NULL;

	MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, 32+M_FLOAT,
		M_IMAGE+M_PROC, &M_correc_aux);
	if ( M_correc_aux == M_NULL )  {
		error_fatal(fn, "M_correc_aux", 0);
		return 1;
	}

	//	SI DEFINO UN TAMAÑO DE DIGITALIZADOR DE ENFOQUE...	(BUFFERS)
    //	Reservo memoria para los buffers empleados durante el enfoque mediante la funcion determina_contraste2
	if ( param->Cam.formatoDig_e[0] != '\0' )  {
		MbufAlloc2d(M_sistema, param->Cam.anchoImagen_e, param->Cam.altoImagen_e, param->Cam.profundidad+M_UNSIGNED,
			M_IMAGE+M_DISP+M_GRAB+M_PROC, &M_enfoque);
		if ( M_enfoque == M_NULL )  {
			error_fatal(fn, "M_enfoque", 0);
			return 1;
		}
	}

	return 0;
}
/*************************** configura_digitalizador *************************
	Función para configurar el digitalizador para el formato de imagen que
	se desea emplear en la adquisición.
*****************************************************************************/
int configura_digitalizador(int formato)
{
    static bool bConfigurado = false;

	//	Compruebo si los digitalizadores son iguales. Si no son iguales
	//	libero el digitalizador antiguo, para reservarlo según las nuevas
	//	especificaciones. 
	if ( strcmp(paramAux->Cam.formatoDig, paramAux->Cam.formatoDig_e) || !bConfigurado)  
    {

	//	Si el digitalizador esta reservado, libero la memoria reservada, para
	//		poder configurarlo. 
		if ( M_digitalizador != M_NULL )	libera_digitalizador();

		switch (formato) {
			case FORMATO_NORMAL:
				MdigAlloc (M_sistema, M_DEV0, paramAux->Cam.formatoDig, M_DEFAULT, &M_digitalizador);
				break;
			case FORMATO_ENFOQUE:
				MdigAlloc (M_sistema, M_DEV0, paramAux->Cam.formatoDig_e, M_DEFAULT, &M_digitalizador);
				break;
			default:
				error_fatal("configura_digitalizador", "Formato de digitalización inaceptable", 0);
				return 1;
		}

		// Fijamos los parámetros de adquisición, según los datos leidos del fichero ini. 
		MdigControl(M_digitalizador, M_BRIGHTNESS, paramAux->Cam.brillo);
		MdigControl(M_digitalizador, M_GAIN, paramAux->Cam.ganancia);
        ModificaExposicion(paramAux->Rueda.exposicion[paramAux->Rueda.posFiltro]);
        ModificaBaseExposicion(paramAux->Rueda.base_exp[paramAux->Rueda.posFiltro]);
	}

	if (paramAux->Cam.anchoImagen != paramAux->Cam.anchoImagen_e    || 
        paramAux->Cam.altoImagen != paramAux->Cam.altoImagen_e      || 
        !bConfigurado)
    {

	    //	Selecciono la configuración del digitalizador. 
	    MdigControl(M_digitalizador, M_SOURCE_OFFSET_X, 0); // Necesario para evitar salirnos del cuadro
	    MdigControl(M_digitalizador, M_SOURCE_OFFSET_Y, 0); // al modificar el tamaño de la captura
	    switch (formato) {
		    case FORMATO_NORMAL:
			    MdigControl(M_digitalizador, M_SOURCE_SIZE_X, paramAux->Cam.anchoImagen);
			    MdigControl(M_digitalizador, M_SOURCE_OFFSET_X, (limCam.anchoDig - paramAux->Cam.anchoImagen) / 2);

                MdigControl(M_digitalizador, M_SOURCE_SIZE_Y, paramAux->Cam.altoImagen);
			    MdigControl(M_digitalizador, M_SOURCE_OFFSET_Y, (limCam.altoDig - paramAux->Cam.altoImagen) / 2);

    //			ModificaExposicion(paramAux->Cam.exposicion[paramAux->Mtb.posFiltro]);
			    break;
		    case FORMATO_ENFOQUE:
			    MdigControl(M_digitalizador, M_SOURCE_SIZE_X, paramAux->Cam.anchoImagen_e);
			    MdigControl(M_digitalizador, M_SOURCE_OFFSET_X, (limCam.anchoDig_e - paramAux->Cam.anchoImagen_e) / 2);

			    MdigControl(M_digitalizador, M_SOURCE_SIZE_Y, paramAux->Cam.altoImagen_e);
			    MdigControl(M_digitalizador, M_SOURCE_OFFSET_Y, (limCam.altoDig_e - paramAux->Cam.altoImagen_e) / 2);

    //			ModificaExposicion(paramAux->Cam.exposicion[paramAux->Mtb.posFiltro]);
			    break;
	    }
    }

    // Nos aseguramos de que lo anterior sólo se ejecuta una vez si el formato y las dimensiones 
    // del digitalizador son iguales para adquisición normal y autoenfoque
    bConfigurado = true;

	return 0;
}
Beispiel #6
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.");
	}

}  
/* Main function. */
int MosMain(void)
   {
   MIL_ID   MilApplication;
   MIL_ID   MilSystem;
   MIL_ID   MilDigitizer[2];
   MIL_ID   MilDisplay[2];
   MIL_ID   MilImageDisp[2];

   /* Allocations. */
   MappAlloc(M_DEFAULT, &MilApplication);
   MsysAlloc(MIL_TEXT("M_DEFAULT"), M_DEFAULT, M_DEFAULT, &MilSystem);
   MdigAlloc(MilSystem,  M_DEV0,    MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDigitizer[0]);
   MdigAlloc(MilSystem,  M_DEV1,    MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDigitizer[1]);
   MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay[0]);
   MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay[1]);

   /* Allocate 2 display buffers and clear them. */
   MbufAlloc2d(MilSystem,
               (MIL_INT)(MdigInquire(MilDigitizer[0], M_SIZE_X, M_NULL)*GRAB_SCALE),
               (MIL_INT)(MdigInquire(MilDigitizer[0], M_SIZE_Y, M_NULL)*GRAB_SCALE),
               8L+M_UNSIGNED,
               M_IMAGE+M_GRAB+M_PROC+M_DISP, &MilImageDisp[0]);
   MbufClear(MilImageDisp[0], 0x0);
   MbufAlloc2d(MilSystem,
               (MIL_INT)(MdigInquire(MilDigitizer[1], M_SIZE_X, M_NULL)*GRAB_SCALE),
               (MIL_INT)(MdigInquire(MilDigitizer[1], M_SIZE_Y, M_NULL)*GRAB_SCALE),
               8L+M_UNSIGNED,
               M_IMAGE+M_GRAB+M_PROC+M_DISP, &MilImageDisp[1]);
   MbufClear(MilImageDisp[1], 0x80);

   /* Display the buffers. */
   MdispSelect(MilDisplay[0], MilImageDisp[0]);
   MdispSelect(MilDisplay[1], MilImageDisp[1]);

   /* Grab continuously on displays at the specified scale. */
   MdigControl(MilDigitizer[0], M_GRAB_SCALE, GRAB_SCALE);
   MdigGrabContinuous(MilDigitizer[0],MilImageDisp[0]);
   MdigControl(MilDigitizer[1], M_GRAB_SCALE, GRAB_SCALE);
   MdigGrabContinuous(MilDigitizer[1],MilImageDisp[1]);

   /* Print a message. */
   MosPrintf(MIL_TEXT("Press <Enter> to stop continuous grab.\n"));
   MosGetch();

   /* Halt continuous grab. */
   MdigHalt(MilDigitizer[0]);
   MdigHalt(MilDigitizer[1]);

   /* Print a message. */
   MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
   MosGetch();

   /* Free allocations. */
   MbufFree(MilImageDisp[0]);
   MbufFree(MilImageDisp[1]);
   MdispFree(MilDisplay[0]);
   MdispFree(MilDisplay[1]);
   MdigFree(MilDigitizer[0]);
   MdigFree(MilDigitizer[1]);
   MsysFree(MilSystem);
   MappFree(MilApplication);

   return 0;
   }
/* -------------- */
int MosMain(void)
   { 
   MIL_ID MilApplication;
   MIL_ID MilSystem     ;
   MIL_ID MilDigitizer  ;
   MIL_ID MilDisplay    ;
   MIL_ID MilImageDisp  ;
   MIL_ID GrabBufferList[GRAB_BUFFER_NUMBER];
   MIL_ID ProcSystemList[PROCESSING_SYSTEM_NUMBER];  
   MIL_ID SrcProcBufferList[BUFFER_NUMBER];
   MIL_ID DstProcBufferList[BUFFER_NUMBER];
   MIL_INT SizeX, SizeY, SizeBand;
   MIL_TEXT_CHAR SystemDescriptor[SYSTEM_DESCRIPTOR_SIZE];
   long    NbSystem = 0, NbSystemToAllocate = PROCESSING_SYSTEM_NUMBER;
   MIL_INT    GrabFrameCount, n; 
   double SingleSystemProcessingRate, MultipleSystemProcessingRate;
   ProcessingDataStruct ProcessingData;

   /* Allocations and setup. */
   /* ---------------------- */

   /* MIL application allocation. */
   MappAlloc(M_DEFAULT, &MilApplication);

   /* Allocations on the default grab system. */
   MsysAlloc(M_SYSTEM_DEFAULT, M_DEFAULT, M_DEFAULT, &MilSystem);
   MdispAlloc(MilSystem, M_DEV0, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay);
   MdigAlloc(MilSystem, M_DEV0, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDigitizer);
   
   /* Inquire the digitizer's size. */
   SizeX    = ProcessingData.SizeX = (MIL_INT)(MdigInquire(MilDigitizer, M_SIZE_X, M_NULL)*BUFFER_SCALE);
   SizeY    = ProcessingData.SizeY = (MIL_INT)(MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL)*BUFFER_SCALE);
   SizeBand = ProcessingData.SizeBand = (MIL_INT)(MdigInquire(MilDigitizer, M_SIZE_BAND, M_NULL));
   
   /* Allocate a display buffer and clear it. */
   MbufAllocColor(MilSystem, SizeBand, SizeX, SizeY, 8L+M_UNSIGNED, M_IMAGE+M_GRAB+M_DISP, &MilImageDisp);
   MbufClear(MilImageDisp, 0x0);            

   /* Display the processing result if activated (might be the limiting factor for speed). */
   if (DISPLAY_EACH_IMAGE_PROCESSED)
      MdispSelect(MilDisplay, MilImageDisp); 
      
   /* Allocate the grab buffers. */
   for (n=0; n< GRAB_BUFFER_NUMBER; n++)
      MbufAllocColor(MilSystem, SizeBand, SizeX, SizeY, 8L+M_UNSIGNED, M_IMAGE+M_GRAB, &GrabBufferList[n]);
      
   /* Allocate and order the required processing systems. */
   if (USE_GRAB_SYSTEM_AS_ONE_PROCESSOR)
      NbSystemToAllocate--;
   for (n=0; n<NbSystemToAllocate; n++)
      {
      /* Create a system descriptor: (Protocol://Address/System (Ex: dmiltcp://127.0.0.1/M_SYSTEM_HOST)) */
      MosSprintf(SystemDescriptor, SYSTEM_DESCRIPTOR_SIZE, MT("%s://%s/%s"), 
                 DISTRIBUTED_MIL_PROTOCOL, SYSTEM_ADDRESSES[n], PROCESSING_SYSTEM_TYPE);

      /* Allocate the system. */
      MsysAlloc(SystemDescriptor, M_DEFAULT, M_DEFAULT, &ProcSystemList[n]);

      /* Count the sucessfully allocated processing systems. */
      if (ProcSystemList[n])
         NbSystem++;
      }

   /* If the grab system is used to process, we add it at the end of the processing system list .
      This permits to dispatch the job to the other remote systems before to use the grab system 
      itself to process synchronously.
    */
   if (USE_GRAB_SYSTEM_AS_ONE_PROCESSOR)
      {
      ProcSystemList[NbSystem] = MilSystem;
      NbSystem++;
      }

   /* Allocate and order the source and destination processing buffers alternating the target system. */
   for (n=0; n<(NbSystem*BUFFER_PER_PROCESSOR); n++)
      {
      MbufAllocColor(ProcSystemList[n%NbSystem], SizeBand, SizeX, SizeY, 8L+M_UNSIGNED, 
                                                 M_IMAGE+M_PROC, &SrcProcBufferList[n]);
      MbufAllocColor(ProcSystemList[n%NbSystem], SizeBand, SizeX, SizeY, 8L+M_UNSIGNED, 
                                                 M_IMAGE+M_PROC, &DstProcBufferList[n]);
      }

   /* Set the specified grab scale. */
   MdigControl(MilDigitizer, M_GRAB_SCALE, BUFFER_SCALE);
      
   /* Single system processing. */
   /* ------------------------- */

   /* Print a message. */
   /* Print a message. */
   MosPrintf(MIL_TEXT("\nDISTRIBUTED MIL PROCESSING:\n"));
   MosPrintf(MIL_TEXT("---------------------------\n\n"));
   MosPrintf(MIL_TEXT("1 System processing:\n"));
   
   /* Initialize processing variables. */
   ProcessingData.NbSystem = 1;
   ProcessingData.ProcessEachImageOnAllSystems = M_NO;
   ProcessingData.NbProc = 0;
   ProcessingData.MilDigitizer = MilDigitizer;
   ProcessingData.DispBuffer = MilImageDisp; 
   ProcessingData.SrcProcBufferListPtr = SrcProcBufferList;
   ProcessingData.DstProcBufferListPtr = DstProcBufferList;
      
   /* Start processing the buffers. */
   MdigProcess(MilDigitizer, GrabBufferList, GRAB_BUFFER_NUMBER, M_START, M_DEFAULT, 
                                                 ProcessingFunction, &ProcessingData);
      
   /* Wait for a key and stop the processing. */
   MosPrintf(MIL_TEXT("Press <Enter> to stop.\n\n"));  
   MosGetch();   
   MdigProcess(MilDigitizer, GrabBufferList, GRAB_BUFFER_NUMBER, M_STOP+M_WAIT, M_DEFAULT, 
                                                       ProcessingFunction, &ProcessingData);
 
   /* Print statistics. */
   if (ProcessingData.NbProc != 0)
      {
      SingleSystemProcessingRate = ProcessingData.NbProc/ProcessingData.Time;
      MdigInquire(MilDigitizer, M_PROCESS_FRAME_COUNT, &GrabFrameCount);
      MosPrintf(MIL_TEXT("%ld Frames grabbed, %ld Frames processed at %.1f frames/sec (%.1f ms/frame).\n"),
                GrabFrameCount, ProcessingData.NbProc, SingleSystemProcessingRate, 1000.0/SingleSystemProcessingRate); 
      }
   else
      MosPrintf(MIL_TEXT("No frame has been grabbed.\n"));
   MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n"));
   MosGetch();

   /* Multiple systems processing. */
   /* ---------------------------- */

   /* Print a message. */
   MosPrintf(MIL_TEXT("%ld Systems processing:\n"), NbSystem);
   
   /* Halt continuous grab. */
   MdigHalt(MilDigitizer);

   /* Initialize processing variables. */
   ProcessingData.NbSystem = NbSystem;
   ProcessingData.ProcessEachImageOnAllSystems = PROCESS_EACH_IMAGE_ON_ALL_SYSTEMS;
   ProcessingData.NbProc = 0;
   ProcessingData.DispBuffer = MilImageDisp; 
   ProcessingData.SrcProcBufferListPtr = SrcProcBufferList;
   ProcessingData.DstProcBufferListPtr = DstProcBufferList;
   
   
   /* Start processing the buffers. */
   MdigProcess(MilDigitizer, GrabBufferList, GRAB_BUFFER_NUMBER, M_START, M_DEFAULT, 
                                                 ProcessingFunction, &ProcessingData);
      
   /* Wait for a key and stop the processing. */
   MosPrintf(MIL_TEXT("Press <Enter> to stop.\n\n"));  
   MosGetch();   
   MdigProcess(MilDigitizer, GrabBufferList, GRAB_BUFFER_NUMBER, M_STOP+M_WAIT, M_DEFAULT, 
                                                       ProcessingFunction, &ProcessingData);
 
   /* Print statistics. */
   if (ProcessingData.NbProc != 0)
      {
      MultipleSystemProcessingRate = ProcessingData.NbProc/ProcessingData.Time;
      MdigInquire(MilDigitizer, M_PROCESS_FRAME_COUNT, &GrabFrameCount);
      MosPrintf(MIL_TEXT("%ld Frames grabbed, %ld Frames processed at %.1f frames/sec (%.1f ms/frame).\n\n"),
                GrabFrameCount, ProcessingData.NbProc, MultipleSystemProcessingRate, 1000.0/MultipleSystemProcessingRate); 
      MosPrintf(MIL_TEXT("Speedup factor: %.1f.\n\n"),MultipleSystemProcessingRate/SingleSystemProcessingRate);
      if (DISPLAY_EACH_IMAGE_PROCESSED && ((long)((MultipleSystemProcessingRate/SingleSystemProcessingRate)+0.1) < NbSystem))
          MosPrintf(MIL_TEXT("Warning: Display might limit the processing speed. Disable it and retry.\n\n"));
      }
   else
      MosPrintf(MIL_TEXT("No frame has been grabbed.\n"));
   MosPrintf(MIL_TEXT("Press <Enter> to end.\n\n"));
   MosGetch();
   
   /* Free allocations. */
   /* ----------------- */

   for (n=0; n<GRAB_BUFFER_NUMBER; n++)
      MbufFree(GrabBufferList[n]);
   for (n=0; n<BUFFER_NUMBER; n++)
      {
      MbufFree(SrcProcBufferList[n]);
      MbufFree(DstProcBufferList[n]);
      }
   if (USE_GRAB_SYSTEM_AS_ONE_PROCESSOR)
      NbSystem--;
   for (n=0; n<NbSystem; n++)
      MsysFree(ProcSystemList[n]);
   MbufFree(MilImageDisp);
   MdispFree(MilDisplay);
   MdigFree(MilDigitizer);
   MsysFree(MilSystem);
   MappFree(MilApplication);

   return 0;
}