Пример #1
0
    void GlobalsCollector::collect()
    {
        start_chrono();

        for (const auto arg : macrodef.getIn())
        {
            locals.emplace(arg);
        }

        macrodef.getBody().accept(*this);

        for (const auto & out : macrodef.getOut())
        {
            if (locals.find(out) == locals.end())
            {
                globals.emplace(out);
            }
        }

        stop_chrono();
    }
Пример #2
0
/* ==================================== */
int32_t lpropgeolong(
        struct xvimage *img1,
        struct xvimage *mask, 
        int32_t connex, 
        int32_t function
)
/* ==================================== */
#undef F_NAME
#define F_NAME "lpropgeolong"
{
  int32_t k;
  int32_t w;
  int32_t x;
  int32_t y;
  int32_t min;
  int32_t max;
  int32_t moy;
  uint8_t valcomp;
  int32_t valcomplong;
  int32_t mintrouve;
  int32_t maxtrouve;
  int32_t moytrouve;
  int32_t incr_vois;
  int32_t incr_voisb;
  int32_t sumndg;        /* pour calculer la moyenne sur la composante */
  int32_t surf;          /* pour calculer la surface de la composante */
  int32_t *SOURCE = SLONGDATA(img1);
  uint8_t *MASK = UCHARDATA(mask);
  int32_t *MASKLONG = SLONGDATA(mask);
  int32_t rs = rowsize(img1);
  int32_t cs = colsize(img1);
  int32_t N = rs * cs;
  Lifo * LIFO;
#ifdef PERF
  chrono chrono1;
#endif

  if (depth(img1) != 1) 
  {
    fprintf(stderr, "%s: cette version ne traite pas les images volumiques\n", F_NAME);
    return 0;
  }

  if (img1->data_storage_type != VFF_TYP_4_BYTE)
  {
    fprintf(stderr, "%s: datatype for arg1 must be int32_t\n", F_NAME);
    return 0;
  }

  if ((rowsize(mask) != rs) || (colsize(mask) != cs))
  {
    fprintf(stderr, "%s: incompatible image sizes\n", F_NAME);
    return 0;
  }

  switch (connex)
  {
    case 4: incr_vois = 2; incr_voisb = 1; break;
    case 8: incr_vois = 1; incr_voisb = 2; break;
    default: 
      fprintf(stderr, "%s: mauvaise connexite: %d\n", F_NAME, connex);
      return 0;
  } /* switch (connex) */

#ifdef PERF
  /* pour l'analyse de performances */
  start_chrono(&chrono1);
#endif

  IndicsInit(N);

  LIFO = CreeLifoVide(N);
  if (LIFO == NULL)
  {   fprintf(stderr, "%s: CreeLifoVide failed\n", F_NAME);
      return(0);
  }

  if (mask->data_storage_type == VFF_TYP_1_BYTE)
  {
    for (x = 0; x < N; x++)       /* recherche dans toute l'image */
    {
      if (!MASK[x]) SOURCE[x] = 0;
      if (MASK[x] && (!IsSet(x, TRAITE1)))   /* on est dans une CC non traitee */
      {
        valcomp = MASK[x];
        LifoPush(LIFO, x);
        Set(x, TRAITE1);
        min = SOURCE[x];
        max = SOURCE[x];
        surf = 0;

        while (! LifoVide(LIFO))  /* parcourt la CC */
        {
          w = LifoPop(LIFO);
          if ((SOURCE[w] < min)) min = SOURCE[w];
          if ((SOURCE[w] > max)) max = SOURCE[w];
          surf += 1;
          sumndg += SOURCE[w];
          for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */
          {
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASK[y] == valcomp) && (!IsSet(y, TRAITE1)))
            {
              LifoPush(LIFO, y);
              Set(y, TRAITE1);
            } 
          } /* for k ... */
        } /* while (! LifoVide(LIFO)) */
        moy = (int32_t)(sumndg/surf);

        LifoPush(LIFO, x);
        Set(x, TRAITE2);
        mintrouve = 0;
        maxtrouve = 0;
        moytrouve = 0;
        while (! LifoVide(LIFO))  /* RE-parcourt la CC */
        {
          w = LifoPop(LIFO);
          switch (function)
          {
            case MIN:
              SOURCE[w] = min;
              break;
            case MAX:
              SOURCE[w] = max;
              break;
            case MOY:
              SOURCE[w] = moy;
              break;
	    default:
              fprintf(stderr, "%s: bad argument\n", F_NAME);
              return(0);
          }
          for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */
          {                                   /* pour les demarquer (TRAITE1) */
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASK[y] == 0) && (IsSet(y, TRAITE1)))
              UnSet(y, TRAITE1);
          } /* for k ... */
          for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */
          {
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASK[y] == valcomp) && (!IsSet(y, TRAITE2)))
            {
              LifoPush(LIFO, y);
              Set(y, TRAITE2);
            } 
          } /* for k ... */
        } /* while (! LifoVide(LIFO)) */
  
      } /* if (MASK[x] && (!IsSet(x, TRAITE1))) */

    } /* for (x = 0; x < N; x++) */
  } /* if (mask->data_storage_type == VFF_TYP_1_BYTE) */
  else if (mask->data_storage_type == VFF_TYP_4_BYTE)
  {
    for (x = 0; x < N; x++)       /* recherche dans toute l'image */
    {
      if (!MASKLONG[x]) SOURCE[x] = NDG_MIN;
      if (MASKLONG[x] && (!IsSet(x, TRAITE1)))   /* on est dans une CC non traitee */
      {
        valcomplong = MASKLONG[x];
        LifoPush(LIFO, x);
        Set(x, TRAITE1);
#ifdef DEBUG
printf("Set TRAITE1 %d (%d,%d)\n",x, x%rs, x/rs);
#endif
        min = SOURCE[x];
        max = SOURCE[x];
        sumndg = 0;
        surf = 0;
  
        while (! LifoVide(LIFO))  /* parcourt la CC */
        {
          w = LifoPop(LIFO);
          if ((SOURCE[w] < min)) min = SOURCE[w];
          if ((SOURCE[w] > max)) max = SOURCE[w];
          surf += 1;
          sumndg += SOURCE[w];
          for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */
          {
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASKLONG[y] == valcomplong) && (!IsSet(y, TRAITE1)))
            {
              LifoPush(LIFO, y);
              Set(y, TRAITE1);
#ifdef DEBUG
printf("Set TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs);
#endif
            } 
          } /* for k ... */
        } /* while (! LifoVide(LIFO)) */
        moy = (int32_t)(sumndg/surf);
  
        LifoPush(LIFO, x);
        Set(x, TRAITE2);
        mintrouve = 0;
        maxtrouve = 0;
        moytrouve = 0;
        while (! LifoVide(LIFO))  /* RE-parcourt la CC */
        {
          w = LifoPop(LIFO);
          switch (function)
          {
            case MIN:
              SOURCE[w] = min;
              break;
            case MAX:
              SOURCE[w] = max;
              break;
            case MOY:
              SOURCE[w] = moy;
              break;
	    default:
              fprintf(stderr, "%s: bad argument\n", F_NAME);
              return(0);
          }
          for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */
          {                                   /* pour les demarquer (TRAITE1) */
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASKLONG[y] == 0) && (IsSet(y, TRAITE1)))
	    {
              UnSet(y, TRAITE1);
#ifdef DEBUG
printf("UnSet TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs);
#endif
	    }
          } /* for k ... */
          for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */
          {
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASKLONG[y] == valcomplong) && (!IsSet(y, TRAITE2)))
            {
              LifoPush(LIFO, y);
              Set(y, TRAITE2);
            } 
          } /* for k ... */
        } /* while (! LifoVide(LIFO)) */
  
      } /* if (MASKLONG[x] && (!IsSet(x, TRAITE1))) */

    } /* for (x = 0; x < N; x++) */
  } /* if (mask->data_storage_type == VFF_TYP_4_BYTE) */
  else
  {   fprintf(stderr, "%s: bad storage type\n", F_NAME);
      return(0);
  }

  LifoTermine(LIFO);
  IndicsTermine();
  return(1);
} /* lpropgeolong() */
Пример #3
0
/* ==================================== */
int32_t lpropgeo(
        struct xvimage *img1,
        struct xvimage *mask, 
        int32_t connex, 
        int32_t function
)
/* ==================================== */
#undef F_NAME
#define F_NAME "lpropgeo"
{
  int32_t k;
  int32_t w;
  int32_t x;
  int32_t y;
  uint8_t min;
  uint8_t max;
  uint8_t moy;
  uint8_t minb;
  uint8_t maxb;
  uint8_t moyb;
  uint8_t valcomp;
  int32_t valcomplong;
  int32_t mintrouve;
  int32_t maxtrouve;
  int32_t moytrouve;
  int32_t incr_vois;
  int32_t incr_voisb;
  int32_t sumndg;        /* pour calculer la moyenne sur la composante */
  int32_t surf;          /* pour calculer la surface de la composante */
  int32_t sumndgb;       /* pour calculer la moyenne sur le bord */
  int32_t sumndgc;       /* pour calculer la variance sur le bord */
  int32_t surfb;         /* pour calculer la surface du bord */
  double moybd;      /* moyenne sur le bord */
  double devb;       /* deviation (ecart-type) sur le bord */
  int32_t tmp;
  uint8_t *SOURCE = UCHARDATA(img1);
  uint8_t *MASK = UCHARDATA(mask);
  int32_t *MASKLONG = SLONGDATA(mask);
  int32_t rs = rowsize(img1);
  int32_t cs = colsize(img1);
  int32_t N = rs * cs;
  Lifo * LIFO;
#ifdef PERF
  chrono chrono1;
#endif

  if (depth(img1) != 1) 
  {
    fprintf(stderr, "%s: cette version ne traite pas les images volumiques\n", F_NAME);
    return 0;
  }

  if (img1->data_storage_type != VFF_TYP_1_BYTE)
    return lpropgeolong(img1, mask, connex, function);

  if ((rowsize(mask) != rs) || (colsize(mask) != cs))
  {
    fprintf(stderr, "%s: incompatible image sizes\n", F_NAME);
    return 0;
  }

  switch (connex)
  {
    case 4: incr_vois = 2; incr_voisb = 1; break;
    case 8: incr_vois = 1; incr_voisb = 2; break;
    default: 
      fprintf(stderr, "%s: mauvaise connexite: %d\n", F_NAME, connex);
      return 0;
  } /* switch (connex) */

#ifdef PERF
  /* pour l'analyse de performances */
  start_chrono(&chrono1);
#endif

  IndicsInit(N);

  LIFO = CreeLifoVide(N);
  if (LIFO == NULL)
  {   fprintf(stderr, "%s: CreeLifoVide failed\n", F_NAME);
      return(0);
  }

  if (mask->data_storage_type == VFF_TYP_1_BYTE)
  {
    for (x = 0; x < N; x++)       /* recherche dans toute l'image */
    {
      if (!MASK[x]) SOURCE[x] = NDG_MIN;
      if (MASK[x] && (!IsSet(x, TRAITE1)))   /* on est dans une CC non traitee */
      {
        valcomp = MASK[x];
        LifoPush(LIFO, x);
        Set(x, TRAITE1);
        min = SOURCE[x];
        max = SOURCE[x];
        minb = NDG_MAX;
        maxb = NDG_MIN;
        sumndg = 0;
        surf = 0;
        sumndgb = 0;
        sumndgc = 0;
        surfb = 0;

        while (! LifoVide(LIFO))  /* parcourt la CC */
        {
          w = LifoPop(LIFO);
          if ((SOURCE[w] < min)) min = SOURCE[w];
          if ((SOURCE[w] > max)) max = SOURCE[w];
          surf += 1;
          sumndg += SOURCE[w];
          for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */
          {
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASK[y] == valcomp) && (!IsSet(y, TRAITE1)))
            {
              LifoPush(LIFO, y);
              Set(y, TRAITE1);
            } 
          } /* for k ... */
          for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */
          {
            y = voisin(w, k, rs, N);
#ifdef VALEURTABOUE
            if ((y != -1) && (MASK[y] == 0) && (!IsSet(y, TRAITE1)) && (SOURCE[y] != VALEURTABOUE))
#else
            if ((y != -1) && (MASK[y] == 0) && (!IsSet(y, TRAITE1)))
#endif
            {
              if ((SOURCE[y] < minb)) minb = SOURCE[y];
              if ((SOURCE[y] > maxb)) maxb = SOURCE[y];
              surfb += 1;
              sumndgb += SOURCE[y];
              sumndgc += SOURCE[y] * SOURCE[y];
              Set(y, TRAITE1);
            } 
          } /* for k ... */
        } /* while (! LifoVide(LIFO)) */
        moy = (uint8_t)(sumndg/surf);
        if (surfb > 0) { moyb = (uint8_t)(sumndgb/surfb); moybd = ((double)sumndgb)/surfb; }
        else           { moyb = 0; moybd = 0.0; }
        devb = sqrt(((double)sumndgc)/surfb - ((double)sumndgb * sumndgb)/(surfb * surfb));

#ifdef DEBUG
printf("composante %d - surf=%d ; sumndg=%d ; surfb=%d ; sumndgb=%d ; max=%d\n", 
        valcomplong, surf, sumndg, surfb, sumndgb, max);
#endif

        LifoPush(LIFO, x);
        Set(x, TRAITE2);
        mintrouve = 0;
        maxtrouve = 0;
        moytrouve = 0;
        while (! LifoVide(LIFO))  /* RE-parcourt la CC */
        {
          w = LifoPop(LIFO);
          switch (function)
          {
            case MIN1:
              if ((SOURCE[w] == min) && !mintrouve) { Set(w, MINIMUM); mintrouve = 1; }
              break;
            case MAX1:
              if ((SOURCE[w] == max) && !maxtrouve) { Set(w, MAXIMUM); maxtrouve = 1; }
              break;
            case MOY1:
              if ((SOURCE[w] == moy) && !moytrouve) { Set(w, MOYEN); moytrouve = 1; }
              break;
            case MIN:
              SOURCE[w] = min;
              break;
            case MAX:
              SOURCE[w] = max;
              break;
            case MOY:
              SOURCE[w] = moy;
              break;
            case MINB:
              SOURCE[w] = minb;
              break;
            case MAXB:
              SOURCE[w] = maxb;
              break;
            case MOYB:
              SOURCE[w] = moyb;
              break;
            case RANDB:
              tmp = (int32_t)Normal(moybd, devb);
              if (tmp > (int32_t)NDG_MAX) tmp = (int32_t)NDG_MAX;
              if (tmp < (int32_t)NDG_MIN) tmp = (int32_t)NDG_MIN;
              SOURCE[w] = (uint8_t)tmp;
              break;
	    default:
              fprintf(stderr, "%s: bad argument\n", F_NAME);
              return(0);
          }
          for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */
          {                                   /* pour les demarquer (TRAITE1) */
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASK[y] == 0) && (IsSet(y, TRAITE1)))
              UnSet(y, TRAITE1);
          } /* for k ... */
          for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */
          {
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASK[y] == valcomp) && (!IsSet(y, TRAITE2)))
            {
              LifoPush(LIFO, y);
              Set(y, TRAITE2);
            } 
          } /* for k ... */
        } /* while (! LifoVide(LIFO)) */
  
      } /* if (MASK[x] && (!IsSet(x, TRAITE1))) */

    } /* for (x = 0; x < N; x++) */
  } /* if (mask->data_storage_type == VFF_TYP_1_BYTE) */
  else if (mask->data_storage_type == VFF_TYP_4_BYTE)
  {
    for (x = 0; x < N; x++)       /* recherche dans toute l'image */
    {
      if (!MASKLONG[x]) SOURCE[x] = NDG_MIN;
      if (MASKLONG[x] && (!IsSet(x, TRAITE1)))   /* on est dans une CC non traitee */
      {
        valcomplong = MASKLONG[x];
        LifoPush(LIFO, x);
        Set(x, TRAITE1);
#ifdef DEBUG
printf("Set TRAITE1 %d (%d,%d)\n",x, x%rs, x/rs);
#endif
        min = SOURCE[x];
        max = SOURCE[x];
        sumndg = 0;
        surf = 0;
        sumndgb = 0;
        sumndgc = 0;
        surfb = 0;
  
        while (! LifoVide(LIFO))  /* parcourt la CC */
        {
          w = LifoPop(LIFO);
          if ((SOURCE[w] < min)) min = SOURCE[w];
          if ((SOURCE[w] > max)) max = SOURCE[w];
          surf += 1;
          sumndg += SOURCE[w];
          for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */
          {
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASKLONG[y] == valcomplong) && (!IsSet(y, TRAITE1)))
            {
              LifoPush(LIFO, y);
              Set(y, TRAITE1);
#ifdef DEBUG
printf("Set TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs);
#endif
            } 
          } /* for k ... */
          for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */
          {
            y = voisin(w, k, rs, N);
#ifdef VALEURTABOUE
            if ((y != -1) && (MASKLONG[y] == 0) && (!IsSet(y, TRAITE1)) && (SOURCE[y] != VALEURTABOUE))
#else
            if ((y != -1) && (MASKLONG[y] == 0) && (!IsSet(y, TRAITE1)))
#endif
            {
              if ((SOURCE[y] < minb)) minb = SOURCE[y];
              if ((SOURCE[y] > maxb)) maxb = SOURCE[y];
              surfb += 1;
              sumndgb += SOURCE[y];
              sumndgc += SOURCE[y] * SOURCE[y];
              Set(y, TRAITE1);
#ifdef DEBUG
printf("Set TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs);
#endif
            } 
          } /* for k ... */
        } /* while (! LifoVide(LIFO)) */
        moy = (uint8_t)(sumndg/surf);
        if (surfb > 0) { moyb = (uint8_t)(sumndgb/surfb); moybd = ((double)sumndgb)/surfb; }
        else           { moyb = 0; moybd = 0.0; }
        devb = sqrt(((double)sumndgc)/surfb - ((double)sumndgb * sumndgb)/(surfb * surfb));

#ifdef DEBUG
printf("composante %d - surf=%d ; sumndg=%d ; surfb=%d ; sumndgb=%d ; max=%d\n", 
        valcomplong, surf, sumndg, surfb, sumndgb, max);
#endif
  
        LifoPush(LIFO, x);
        Set(x, TRAITE2);
        mintrouve = 0;
        maxtrouve = 0;
        moytrouve = 0;
        while (! LifoVide(LIFO))  /* RE-parcourt la CC */
        {
          w = LifoPop(LIFO);
          switch (function)
          {
            case MIN1:
              if ((SOURCE[w] == min) && !mintrouve) { Set(w, MINIMUM); mintrouve = 1; }
              break;
            case MAX1:
              if ((SOURCE[w] == max) && !maxtrouve) { Set(w, MAXIMUM); maxtrouve = 1; }
              break;
            case MOY1:
              if ((SOURCE[w] == moy) && !moytrouve) { Set(w, MOYEN); moytrouve = 1; }
              break;
            case MIN:
              SOURCE[w] = min;
              break;
            case MAX:
              SOURCE[w] = max;
              break;
            case MOY:
              SOURCE[w] = moy;
              break;
            case MINB:
              SOURCE[w] = minb;
              break;
            case MAXB:
              SOURCE[w] = maxb;
              break;
            case MOYB:
              SOURCE[w] = moyb;
              break;
            case RANDB:
              tmp = (int32_t)Normal(moybd, devb);
              if (tmp > (int32_t)NDG_MAX) tmp = (int32_t)NDG_MAX;
              if (tmp < (int32_t)NDG_MIN) tmp = (int32_t)NDG_MIN;
              SOURCE[w] = (uint8_t)tmp;
              break;
	    default:
              fprintf(stderr, "%s: bad argument\n", F_NAME);
              return(0);
          }
          for (k = 0; k < 8; k += incr_voisb) /* parcourt les voisins dans le complementaire */
          {                                   /* pour les demarquer (TRAITE1) */
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASKLONG[y] == 0) && (IsSet(y, TRAITE1)))
	    {
              UnSet(y, TRAITE1);
#ifdef DEBUG
printf("UnSet TRAITE1 %d (%d,%d)\n",y, y%rs, y/rs);
#endif
	    }
          } /* for k ... */
          for (k = 0; k < 8; k += incr_vois) /* parcourt les voisins */
          {
            y = voisin(w, k, rs, N);
            if ((y != -1) && (MASKLONG[y] == valcomplong) && (!IsSet(y, TRAITE2)))
            {
              LifoPush(LIFO, y);
              Set(y, TRAITE2);
            } 
          } /* for k ... */
        } /* while (! LifoVide(LIFO)) */
  
      } /* if (MASKLONG[x] && (!IsSet(x, TRAITE1))) */

    } /* for (x = 0; x < N; x++) */
  } /* if (mask->data_storage_type == VFF_TYP_4_BYTE) */
  else
  {   fprintf(stderr, "%s: bad storage type\n", F_NAME);
      return(0);
  }

  if (function == MIN1)
    for (x = 0; x < N; x++)
      if (IsSet(x, MINIMUM))
        SOURCE[x] = NDG_MAX;
      else
        SOURCE[x] = NDG_MIN;

  if (function == MAX1)
    for (x = 0; x < N; x++)
      if (IsSet(x, MAXIMUM))
        SOURCE[x] = NDG_MAX;
      else
        SOURCE[x] = NDG_MIN;

  if (function == MOY1)
    for (x = 0; x < N; x++)
      if (IsSet(x, MOYEN))
        SOURCE[x] = NDG_MAX;
      else
        SOURCE[x] = NDG_MIN;

  LifoTermine(LIFO);
  IndicsTermine();
  return(1);
} /* lpropgeo() */
Пример #4
0
/* ==================================== */
int32_t lsquel(struct xvimage *image, int32_t seuil, int32_t niseuil)
/* ==================================== */
{ 
  int32_t x;                       /* index muet de pixel */
  int32_t y;                       /* index muet (generalement un voisin de x) */
  int32_t rs = rowsize(image);     /* taille ligne */
  int32_t cs = colsize(image);     /* taille colonne */
  int32_t N = rs * cs;             /* taille image */
  uint8_t *SOURCE = UCHARDATA(image);      /* l'image de depart */
  struct xvimage *lab;
  int32_t *M;            /* l'image d'etiquettes de composantes connexes */
  int32_t nminima;                 /* nombre de minima differents */
  Fifo * FIFOn;
  Fifo * FIFOs;
  Fifo * FIFOe;
  Fifo * FIFOo;
  Fifo * FIFOna;
  Fifo * FIFOsa;
  Fifo * FIFOea;
  Fifo * FIFOoa;
  Fifo * FIFOtmp;
  Fifo * FIFO;
  int32_t niter;
#ifdef PERF
  chrono chrono1;
#endif

  if (depth(image) != 1) 
  {
    fprintf(stderr, "lsquel: cette version ne traite pas les images volumiques\n");
    exit(0);
  }

#ifdef PERF  
  start_chrono(&chrono1);  /* pour l'analyse de performances */
#endif

  lab = allocimage(NULL, rs, cs, 1, VFF_TYP_4_BYTE);
  if (lab == NULL)
  {   
    fprintf(stderr, "lhtkern: allocimage failed\n");
    return 0;
  }
  M = SLONGDATA(lab);

  if (!llabelextrema(image, 4, LABMIN, lab, &nminima))
  {   
    fprintf(stderr, "lhtkern: llabelextrema failed\n");
    return 0;
  }

  IndicsInit(N);

  FIFO = CreeFifoVide(N);
  FIFOn = CreeFifoVide(N/2);
  FIFOs = CreeFifoVide(N/2);
  FIFOe = CreeFifoVide(N/2);
  FIFOo = CreeFifoVide(N/2);
  if ((FIFO == NULL) && (FIFOn == NULL) && (FIFOs == NULL) && (FIFOe == NULL) && (FIFOo == NULL))
  {   fprintf(stderr, "lsquel() : CreeFifoVide failed\n");
      return(0);
  }

  /* ================================================ */
  /*                  DEBUT ALGO                      */
  /* ================================================ */

  /* ========================================================= */
  /*   INITIALISATION DES FIFOs: empile les voisins des minima */
  /* ========================================================= */

  for (x = 0; x < N; x++)
  {
    if (M[x] != 0)                  /* le pixel appartient a un minimum */
    {
        Set(x, MINI);
        y = voisin(x, NORD, rs, N);
        if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N))
          { FifoPush(FIFOn, y); Set(y, EN_FIFO); }
#ifdef DIAG
        y = voisin(x, NORD+1, rs, N);
        if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N))
          { FifoPush(FIFOn, y); Set(y, EN_FIFO); }
#endif
        y = voisin(x, EST, rs, N);
        if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N))
          { FifoPush(FIFOe, y); Set(y, EN_FIFO); }
#ifdef DIAG
        y = voisin(x, EST+1, rs, N);
        if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N))
          { FifoPush(FIFOe, y); Set(y, EN_FIFO); }
#endif
        y = voisin(x, SUD, rs, N);
        if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N))
          { FifoPush(FIFOs, y); Set(y, EN_FIFO); }
#ifdef DIAG
        y = voisin(x, SUD+1, rs, N);
        if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N))
          { FifoPush(FIFOs, y); Set(y, EN_FIFO); }
#endif
        y = voisin(x, OUEST, rs, N);
        if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N))
          { FifoPush(FIFOo, y); Set(y, EN_FIFO); }
#ifdef DIAG
        y = voisin(x, OUEST+1, rs, N);
        if ((y!=-1) && (M[y]==0) && !IsSet(y,EN_FIFO) && nonbord(y,rs,N))
          { FifoPush(FIFOo, y); Set(y, EN_FIFO); }
#endif
    } /* if (M[x] != 0) */
  } /* for x */

  freeimage(lab);

  FIFOna = CreeFifoVide(N/4);
  FIFOsa = CreeFifoVide(N/4);
  FIFOea = CreeFifoVide(N/4);
  FIFOoa = CreeFifoVide(N/4);
  if ((FIFOna == NULL) && (FIFOsa == NULL) && (FIFOea == NULL) && (FIFOoa == NULL))
  {   fprintf(stderr, "lsquel() : CreeFifoVide failed\n");
      return(0);
  }

  /* ================================================ */
  /*                  DEBUT SATURATION                */
  /* ================================================ */

  niter = 0;
  while (! (FifoVide(FIFOn) && FifoVide(FIFOe) && FifoVide(FIFOs) && FifoVide(FIFOo)))
  {
    niter++;
    while (! FifoVide(FIFOn))
    {
      x = FifoPop(FIFOn);
      UnSet(x, EN_FIFO);
      if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil))
      {                                    /* modifie l'image le cas echeant */
        testmini(SOURCE, x, rs, N, FIFO);        /* reactualise l'image MINI */
        empilevoisins(x, rs, N, FIFOna, FIFOea, FIFOsa, FIFOoa);
      } /* if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) */
    } /* while (! FifoVide(FIFOn)) */

    while (! FifoVide(FIFOs))
    {
      x = FifoPop(FIFOs);
      UnSet(x, EN_FIFO);
      if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil))
      {                                    /* modifie l'image le cas echeant */
        testmini(SOURCE, x, rs, N, FIFO);        /* reactualise l'image MINI */
        empilevoisins(x, rs, N, FIFOna, FIFOea, FIFOsa, FIFOoa);
      } /* if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) */
    } /* while (! FifoVide(FIFOs)) */

    while (! FifoVide(FIFOe))
    {
      x = FifoPop(FIFOe);
      UnSet(x, EN_FIFO);
      if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil))
      {                                    /* modifie l'image le cas echeant */
        testmini(SOURCE, x, rs, N, FIFO);        /* reactualise l'image MINI */
        empilevoisins(x, rs, N, FIFOna, FIFOea, FIFOsa, FIFOoa);
      } /* if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) */
    } /* while (! FifoVide(FIFOe)) */

    while (! FifoVide(FIFOo))
    {
      x = FifoPop(FIFOo);
      UnSet(x, EN_FIFO);
      if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil))
      {                                    /* modifie l'image le cas echeant */
        testmini(SOURCE, x, rs, N, FIFO);        /* reactualise l'image MINI */
        empilevoisins(x, rs, N, FIFOna, FIFOea, FIFOsa, FIFOoa);
      } /* if (testabaisse(SOURCE, x, rs, N, seuil, niter, niseuil)) */
    } /* while (! FifoVide(FIFOo)) */

    FIFOtmp = FIFOn; FIFOn = FIFOna; FIFOna = FIFOtmp;
    FIFOtmp = FIFOe; FIFOe = FIFOea; FIFOea = FIFOtmp;
    FIFOtmp = FIFOs; FIFOs = FIFOsa; FIFOsa = FIFOtmp;
    FIFOtmp = FIFOo; FIFOo = FIFOoa; FIFOoa = FIFOtmp;

  } /* while (! (FifoVide(FIFOn) && FifoVide(FIFOe) && FifoVide(FIFOs) && FifoVide(FIFOo))) */

  /* ================================================ */
  /* UN PEU DE MENAGE                                 */
  /* ================================================ */

  IndicsTermine();
  FifoTermine(FIFO);
  FifoTermine(FIFOn);
  FifoTermine(FIFOe);
  FifoTermine(FIFOs);
  FifoTermine(FIFOo);
  FifoTermine(FIFOna);
  FifoTermine(FIFOea);
  FifoTermine(FIFOsa);
  FifoTermine(FIFOoa);

#ifdef PERF
  save_time(N, read_chrono(&chrono1), "lsquel", image->name);    
#endif
  return(1);
}