/**************************  ini_TomaPatrones  ******************************
	Reserva de memoria para tomar una serie de imagenes promediadas.
*****************************************************************************/
int ini_TomaPatrones(parametros *param)
{
	int i;

    //Acumuladores
	for (i=0; i < param->nBandas; i++)  {
	    MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, PROFUNDIDAD_ACUMULACION+M_UNSIGNED,
		    M_IMAGE+M_DISP+M_PROC, &M_banda_acum[i]);
	    MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, PROFUNDIDAD_ACUMULACION+M_UNSIGNED,
		    M_IMAGE+M_DISP+M_PROC, &M_banda_enmascarada_acum[i]);
	    MbufClear(M_banda_acum[i], 0);
	    MbufClear(M_banda_enmascarada_acum[i], 0);

        //Contador
	    MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, 8+M_UNSIGNED, //necesario 32+M_FLOAT para realizar operaciones en coma flotante
		    M_IMAGE+M_PROC, &M_cont_campos[i]);
	    MbufClear(M_cont_campos[i], 0);

	}

    //Buffers auxiliares
	MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, 8+M_UNSIGNED,
		M_IMAGE+M_PROC, &M_mascara_aux);
	MbufClear(M_mascara_aux, 0);

	MbufAlloc2d(M_sistema, param->Cam.anchoImagen, param->Cam.altoImagen, PROFUNDIDAD_ACUMULACION+M_UNSIGNED,
		M_IMAGE+M_PROC+M_GRAB, &M_acum_aux);
	MbufClear(M_acum_aux, 0);

	return 0;
}
/*************************** toma2_acumulada *********************************
	Función para la adquisición de una imagen con menor ruido, mediante la
	acumulacion de un cierto número de tomas 

    buf - buffer donde se devolvera la imagen acumulada
    nAcum - numero de veces a acumular

	La imagen acumulada es devuelta en M_imagen1
*****************************************************************************/
void  toma2_acumulada(MIL_ID buf, int nAcum)
{
/*
    fin_toma(); //	tomaContinua = false;

    if (nAcum == 1) //optimizado
    {
	    MdigGrab (M_digitalizador, buf);
    }
    else
    {
	    MbufClear(buf, nAcum / 2); //	para conseguir que en la división final se produzca un redondeo.
	    int n;
	    for (n = 0; n < nAcum; ++n) 
        {
		        MdigGrab (M_digitalizador, M_imagen1);
		        MimArith (M_imagen1, buf, buf, M_ADD);
	    }
    }
*/
	//	para conseguir que en la división final se produzca un redondeo. 
    if (nAcum != 1)
	    MbufClear(buf, nAcum / 2);
    else
	    MbufClear(buf, 0);

    fin_toma(); //	tomaContinua = false;

	int n;
	for (n = 0; n < nAcum; ++n) {
		MdigGrab (M_digitalizador, M_imagen1);
		MimArith (M_imagen1, buf, buf, M_ADD);
	}
}
bool MdispGtkView::newDoc()
   {
    // Set buffer attributes
   if(((MdispGtkApp*)dispGtkApp())->m_numberOfDigitizer)
      {
      m_bufferAttributes=M_IMAGE+M_DISP+M_GRAB+M_PROC;
      m_imageSizeX = ((MdispGtkApp*)dispGtkApp())->m_digitizerSizeX;
      m_imageSizeY = ((MdispGtkApp*)dispGtkApp())->m_digitizerSizeY;
      m_NbBands    = ((MdispGtkApp*)dispGtkApp())->m_digitizerNbBands;

      // Allocate a buffer [CALL TO MIL]
      MbufAllocColor(((MdispGtkApp*)dispGtkApp())->m_MilSystem,
                     m_NbBands,
                     m_imageSizeX,
                     m_imageSizeY,
                     M_DEF_IMAGE_TYPE,
                     m_bufferAttributes,
                     &m_MilImage);

      // Clear the buffer [CALL TO MIL] 
      MbufClear(m_MilImage,M_COLOR_BLACK);
      }
   else
      {
      //Import image in buffer [CALL TO MIL]
      MbufImport(IMAGE_FILE,M_DEFAULT,M_RESTORE,((MdispGtkApp*)dispGtkApp())->m_MilSystem,&m_MilImage);

      // Set SizeX and SizeY variable to the size of the buffer [CALL TO MIL]
      if (m_MilImage) 
         {
         m_imageSizeX   = MbufInquire(m_MilImage, M_SIZE_X, M_NULL);
         m_imageSizeY   = MbufInquire(m_MilImage, M_SIZE_Y, M_NULL);
         m_NbBands      = MbufInquire(m_MilImage, M_SIZE_BAND, M_NULL);
         }
      }

   UpdateContentSize();

   // If not able to allocate a buffer, do not create a new document
   if(!m_MilImage)
      return false;

   Initialize();

   return true;
   }
void ControlImagenes::EliminarTodas()
{
    if (M_overlay_normal != M_NULL)
    {
        MbufClear(M_overlay_normal, TRANSPARENTE );// Relleno el buffer overlay con el color TRANSPARENTE
        M_overlay_normal = M_NULL;
    }


    MIL_ID selected;
    MdispInquire(m_Mildisplay,M_SELECTED,&selected);
    if (selected!=M_NULL)
        MdispDeselect(m_Mildisplay,selected);

    for (int i=0;i<MAX_NUM_IMAGENES;i++)
    {
        if (m_Milimagen[i] != M_NULL)
        {
            MbufFree(m_Milimagen[i]);
            m_Milimagen[i] = M_NULL;
        }
    }
    m_numImagenes = 0;

    //Liberamos RGB
    if (m_MilRGB != M_NULL)
    {
        MbufFree(m_MilRGB);
        m_MilRGB = M_NULL;
    }

    //Liberamos imagen identificacion
    if (M_Clasificacion != M_NULL)
    {
        MbufFree(M_Clasificacion);
        M_Clasificacion = M_NULL;
    }
    if (m_bufClasificacionSelectiva != NULL)
    {
        delete [] m_bufClasificacionSelectiva;
        m_bufClasificacionSelectiva = NULL;
    }
    theApp.clasificacion.Liberar();
}
// A partir de las imagenes guardadas en disco, genera la imagen mosaico
void GenerarMosaicos()
{
	char nombre_fich[512];
    MIL_ID M_aux;
    MIL_ID M_mosaico;
    long lSizeX, lSizeY; //dimensiones imagen


    // Leer tamaño de primera imagen
    sprintf(nombre_fich, "%s%s_%03d_%03d_%02d%s", g_csDirectorioBarrido, g_csMuestra, g_nFilaInicio, g_nColumnaInicio, g_arrFiltros[0]+1, ".tif");
    MbufDiskInquire(nombre_fich,M_SIZE_X, &lSizeX);
    MbufDiskInquire(nombre_fich,M_SIZE_Y, &lSizeY);

	MbufAlloc2d(M_DEFAULT_HOST, lSizeX, lSizeY, 8/*theApp.m_ParamIni.Cam.profundidad*/+M_UNSIGNED,
		M_IMAGE+M_PROC, &M_aux);
	MbufAlloc2d(M_DEFAULT_HOST, lSizeX * (g_nColumnaFin - g_nColumnaInicio + 1), lSizeY * (g_nFilaFin - g_nFilaInicio + 1), 8/*theApp.m_ParamIni.Cam.profundidad*/+M_UNSIGNED,
		M_IMAGE+M_PROC, &M_mosaico);
	for (int f=0; f < g_nBandas; f++)  
    {
        MbufClear(M_mosaico,0);
        for (int i=g_nFilaInicio;i<=g_nFilaFin;i++)
        {
            printf("\rComponiendo mosaico filtro %d  Fila %d ...    ", g_arrFiltros[f], i);
            for (int j=g_nColumnaInicio;j<=g_nColumnaFin;j++)
            {
		        sprintf(nombre_fich, "%s%s_%03d_%03d_%02d%s", g_csDirectorioBarrido, g_csMuestra, i, j, g_arrFiltros[f], ".tif");
		        //carga_imagen_campo8bit(nombre_fich, M_aux, theApp.m_ParamIni.Cam.profundidad); 
		        carga_imagen_campo_bits(nombre_fich, M_aux,8); 
                MbufCopyClip(M_aux,M_mosaico,(j-g_nColumnaInicio)*lSizeX,(i-g_nFilaInicio)*lSizeY);
            }
        }
        printf("\rSalvando mosaico filtro %d ...                      ", g_arrFiltros[f]);
        sprintf(nombre_fich, "%s%s_%02d%s", g_csDirectorioBarrido, g_csMuestra, g_arrFiltros[f], ".tif");
		graba_imagen_campo(nombre_fich, M_mosaico); 

    }
    printf("\r                                                         \n");

	MbufFree(M_aux);
	MbufFree(M_mosaico);
}
/**************************  perfiles  *********************************
   Función para iniciar el proceso de análisis, obteniendo las imágenes
   de disco.
*****************************************************************************/
int perfiles(MIL_ID M_fb, parametros *param)
{
	char mensaje[128];
	int  tecla, posX, posY;
	MIL_ID M_ancho, M_alto;

	posX = param->Cam.anchoImagen / 2;	// Inicio en la posición central de la imagen
	posY = param->Cam.altoImagen / 2;
	
	M_ancho = MbufInquire(M_fb, M_SIZE_X, M_NULL);	// Pregunto sobre el ancho y alto
	M_alto = MbufInquire(M_fb, M_SIZE_Y, M_NULL);	// del buffer seleccionado.

	do {
		sprintf(mensaje, "   - X: %ld.   - Y: %ld.		", posX, posY);
		sendcont(mensaje);
		do {
			dibuja_linea_activa(M_overlay_normal, posX, posY, 0);
			Sleep(200);		// Espera mientras no se pulse una tecla
		} while (!kbhit());
		tecla = getKey();
		switch (tecla) {
			case K_ESC:
				break;
			case K_LEFT:
				/* borro la anterior linea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 1);

				posX = posX - MOV_LENTO;
				posX = (posX < 0)? 0 : posX;
				posY = posY;
				/* Dibujo la nueva línea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 0);
				break;
			case K_RIGHT:
				/* borro la anterior linea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 1);
				
				posX = posX + MOV_LENTO;
				posX = (posX > M_ancho)? M_ancho : posX;
				posY = posY;
				/* Dibujo la nueva línea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 0);
				break;
			case K_UP:
				/* borro la anterior linea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 1);

				posX = posX;
				posY = posY - MOV_LENTO;
				posY = (posY < 0)? 0 : posY;
				/* Dibujo la nueva línea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 0);
				break;
			case K_DOWN:
				/* borro la anterior linea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 1);

				posX = posX;
				posY = posY + MOV_LENTO;
				posY = (posY > M_alto)? M_alto : posY;
				/* Dibujo la nueva línea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 0);
				break;

			case K_CR_LEFT:
				/* borro la anterior linea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 1);

				posX = posX - MOVIMIENTO;
				posX = (posX < 0)? 0 : posX;	// Compruebo que no sobrepaso el límite.
				posY = posY;
				/* Dibujo la nueva línea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 0);
				break;
			case K_CR_RIGHT:
				/* borro la anterior linea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 1);
				
				posX = posX + MOVIMIENTO;
				posX = (posX > M_ancho)? M_ancho : posX;
				posY = posY;
				/* Dibujo la nueva línea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 0);
				break;
			case K_CR_UP:
				/* borro la anterior linea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 1);

				posX = posX;
				posY = posY - MOVIMIENTO;
				posY = (posY < 0)? 0 : posY;
				/* Dibujo la nueva línea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 0);
				break;
			case K_CR_DOWN:
				/* borro la anterior linea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 1);

				posX = posX;
				posY = posY + MOVIMIENTO;
				posY = (posY > M_alto)? M_alto : posY;
				/* Dibujo la nueva línea. */
				dibuja_linea_activa(M_overlay_normal, posX, posY, 0);
				break;
			case 'H':
			case 'h':
				if ( calcula_valores_linea(M_imagen1, posX, posY, L_HORIZ) )
					error_leve("perfiles", "No se puede mostrar el análisis solicitado");
				break;
			case 'V':
			case 'v':
				calcula_valores_linea(M_imagen1, posX, posY, L_VERT);
				break;
			default :
				putch('\a');
		}
	} while (tecla != K_ESC);
	MbufClear(M_overlay_normal, TRANSPARENTE);

	return 0;
}
/* 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;
}  
// Calcula las imagenes monocromas para R, G y B segun los porcentajes dados, 
// reservando memoria y presentando la imagen RGB
// Devuelve true si se ha realizado el calculo, false si no (porque ya se realizó antes)
bool ControlImagenes::MostrarImagenRGB(int arrFiltroPorcentajesR[MAX_NUM_IMAGENES], 
                                       int arrFiltroPorcentajesG[MAX_NUM_IMAGENES], 
                                       int arrFiltroPorcentajesB[MAX_NUM_IMAGENES],
                                       CStatic&	m_control,
                                       int nTotalR,int nTotalG,int nTotalB,
                                       bool bModificado)
{

    MIL_ID selected;
    MdispInquire(m_Mildisplay,M_SELECTED,&selected);
    if (selected!=M_NULL)
        MdispDeselect(m_Mildisplay,selected);

    DisplayBits(8); //para que el display muestre las imagenes en profundidad 8 bit

    // Si es la primera vez, reservar la memoria de la imagen RGB
    if (m_MilRGB == M_NULL)
        MbufAllocColor(M_DEFAULT_HOST, 3, m_nAnchoImagen, m_nAltoImagen, 8+M_UNSIGNED, M_IMAGE+M_DISP, &m_MilRGB); //16 por si las imagenes estan en 16bit
    else if (!bModificado)
    {
        MdispSelectWindow(m_Mildisplay,m_MilRGB,m_control);
        return false;
    }


    unsigned short* pBuffImagen;    //auxiliar para volcar cada imagen de cada filtro, 16 bit
    unsigned char* pRed;           // auxiliar para calcular la banda de color (8 bit)
    unsigned char* pGreen;         // auxiliar para calcular la banda de color (8 bit)
    unsigned char* pBlue;          // auxiliar para calcular la banda de color (8 bit)

    pBuffImagen = (unsigned short*)calloc(m_nAnchoImagen*m_nAltoImagen, sizeof(unsigned short));
    pRed = (unsigned char*)calloc(m_nAnchoImagen*m_nAltoImagen, sizeof(unsigned char));
    pGreen = (unsigned char*)calloc(m_nAnchoImagen*m_nAltoImagen, sizeof(unsigned char));
    pBlue = (unsigned char*)calloc(m_nAnchoImagen*m_nAltoImagen, sizeof(unsigned char));

    for (int i= 0; i<MAX_NUM_IMAGENES;i++)
    {
        // Cargar buffers de filtros solo si se necesita en alguna de las bandas
        if (arrFiltroPorcentajesR[i] != 0 || arrFiltroPorcentajesG[i] != 0 || arrFiltroPorcentajesB[i] != 0)
        {
            MbufGet(m_Milimagen[i],pBuffImagen);

            //Acumular el pocentaje adecuado de este filtro en cada color
            if(arrFiltroPorcentajesR[i] != 0)
            {
                Acumular(pRed, pBuffImagen, ((double)arrFiltroPorcentajesR[i])/nTotalR, m_nAnchoImagen*m_nAltoImagen);
            }
            if(arrFiltroPorcentajesG[i] != 0)
            {
                Acumular(pGreen, pBuffImagen, ((double)arrFiltroPorcentajesG[i])/nTotalG, m_nAnchoImagen*m_nAltoImagen);
            }
            if(arrFiltroPorcentajesB[i] != 0)
            {
                Acumular(pBlue, pBuffImagen, ((double)arrFiltroPorcentajesB[i])/nTotalB, m_nAnchoImagen*m_nAltoImagen);
            }

        }
    }


    // Volcar el array auxiliar calculado al color correspondiente
    MbufPutColor(m_MilRGB,M_SINGLE_BAND,M_BLUE/*2*/,pBlue);
    MbufPutColor(m_MilRGB,M_SINGLE_BAND,M_GREEN/*1*/,pGreen);
    MbufPutColor(m_MilRGB,M_SINGLE_BAND,M_RED/*0*/,pRed);

    free(pBuffImagen);
    free(pBlue);
    free(pGreen);
    free(pRed);

    // Mostar la imagen en color
    MdispSelectWindow(m_Mildisplay,m_MilRGB,m_control);
	// Inicializar Overlay la primera vez que se carga una imagen
	// Esto se hace aqui porque no funciona si no hay un buffer asociado con el display
	// ha de usarse la variable global M_overlay_normal para que funcionen las funciones graficas
    // y porque puede ser que no se haya hecho al cargar las imagenes pancromaticas (en el caso
    // de que la primera imagen mostrada sea la pancromatica, ver CAnalisisDlg::AbrirTodas y CargarImagen)
	if (M_overlay_normal==NULL)
	{
		MdispInquire(m_Mildisplay, M_OVERLAY_ID, &M_overlay_normal);

		// Relleno el buffer overlay con el color TRANSPARENTE
		MbufClear(M_overlay_normal, TRANSPARENTE );
	}

    return true;
}