/**
 * \file Dilatation.cpp
 * Implante un filtre de dilatation en morphologie mathematique.
 * 
 * @author Nicolas Janey
 * @author nicolas.janey@univ-fcomte.fr
 * @version 1.0, 12/01/06
 */

#include <stdio.h>
#include <stdlib.h>

#include "Image.h"
#include "ElementStructurant.h"

static int acceptePixelDilatationLignePaire(struct image *src,int cc,int ll,struct elementStructurant *e) {
  register int i = (ll*src->tx+cc)*3;
  if ( ( e->sg == src->p[i] ) || ( e->sg == -1 ) )
    return(1);
  if ( ( e->sd == src->p[i+3] ) || ( e->sd == -1 ) )
    return(1);
  int inc;
  i += (inc = src->tx*3);
  if ( ( e->g == src->p[i] ) || ( e->g == -1 ) )
    return(1);
  if ( ( e->c == src->p[i+3] ) || ( e->c == -1 ) )
    return(1);
  if ( ( e->d == src->p[i+6] ) || ( e->d == -1 ) )
    return(1);
  i += inc;
  if ( ( e->sg == src->p[i] ) || ( e->sg == -1 ) )
    return(1);
  if ( ( e->sd == src->p[i+3] ) || ( e->sd == -1 ) )
    return(1);
  return(0);
}
  
static void dilateLignePaire(struct image *src,struct image *dst,int nc,int l,struct elementStructurant *e) {
  register int i = ((l+1)*dst->tx+1)*3;
  for ( int c = 0 ; c < nc ; c++ ) {
    if ( acceptePixelDilatationLignePaire(src,c,l,e) )
      dst->p[i] = dst->p[i+1] = dst->p[i+2] = src->max;
      else
      dst->p[i] = dst->p[i+1] = dst->p[i+2] = 0;
    i += 3; }
}
  
static int acceptePixelDilatationLigneImpaire(struct image *src,int cc,int ll,struct elementStructurant *e) {
  register int i = (ll*src->tx+cc)*3;
  if ( ( e->sg == src->p[i+3] ) || ( e->sg == -1 ) )
    return(1);
  if ( ( e->sd == src->p[i+6] ) || ( e->sd == -1 ) )
    return(1);
  int inc;
  i += (inc = src->tx*3);
  if ( ( e->g == src->p[i] ) || ( e->g == -1 ) )
    return(1);
  if ( ( e->c == src->p[i+3] ) || ( e->c == -1 ) )
    return(1);
  if ( ( e->d == src->p[i+6] ) || ( e->d == -1 ) )
    return(1);
  i += inc+3;
  if ( ( e->ig == src->p[i] ) || ( e->ig == -1 ) )
    return(1);
  if ( ( e->id == src->p[i+3] ) || ( e->id == -1 ) )
    return(1);
  return(0);
}
  
static void dilateLigneImpaire(struct image *src,struct image *dst,int nc,int l,struct elementStructurant *e) {
  register int i = ((l+1)*dst->tx+1)*3;
  for ( int c = 0 ; c < nc ; c++ ) {
    if ( acceptePixelDilatationLigneImpaire(src,c,l,e) )
      dst->p[i] = dst->p[i+1] = dst->p[i+2] = src->max;
      else
      dst->p[i] = dst->p[i+1] = dst->p[i+2] = 0;
    i += 3; }
}

/**
 * Filtre une image par dilatation.
 *
 * @param src l'image a filtrer.
 * @param dst l'image resultat apres filtrage.
 * @param e l'elementStructurant de dilatation.
 * @author Nicolas Janey
 * @author nicolas.janey@univ-fcomte.fr
 * @version 1.0, 12/01/06
 */
void filtreImageDilatation(struct image *src,struct image *dst,struct elementStructurant *e) {
  struct image dst2;
  allocationImage(src->tx,src->ty,src->bits,&dst2);
  int nl = src->ty-2;
  int nc = src->tx-2;
  for ( int l = 0 ; l < nl ; l++ ) {
    if ( l%2 == 0 )
      dilateLignePaire(src,&dst2,nc,l,e);
      else
      dilateLigneImpaire(src,&dst2,nc,l,e); }
  if ( src == dst )
    desallocationImage(dst);
  *dst = dst2;
}

/**
 * Filtre une image par dilatation.
 *
 * @param src l'image a filtrer.
 * @param dst l'image resultat apres filtrage.
 * @param e l'elementStructurant de dilatation.
 * @author Nicolas Janey
 * @author nicolas.janey@univ-fcomte.fr
 * @version 1.0, 12/01/06
 */
void filtreImageDilatation(int callage,struct image *src,struct image *dst,struct elementStructurant *e) {
  struct image dst2;
  allocationImage(src->tx,src->ty,src->bits,&dst2);
  int nl = src->ty-2;
  int nc = src->tx-2;
  for ( int l = 0 ; l < nl ; l++ ) {
    if ( (l+callage)%2 == 0 )
      dilateLignePaire(src,&dst2,nc,l,e);
      else
      dilateLigneImpaire(src,&dst2,nc,l,e); }
  if ( src == dst )
    desallocationImage(dst);
  *dst = dst2;
}

/**
 * Filtre une image par dilatation.
 *
 * @param src l'image a filtrer.
 * @param dst l'image resultat apres filtrage.
 * @param deb le numero de la ligne de debut du filtrage.
 * @param fin le numero de la ligne de fin du filtrage.
 * @param e l'elementStructurant de dilatation.
 * @author Nicolas Janey
 * @author nicolas.janey@univ-fcomte.fr
 * @version 1.0, 12/01/06
 */
void filtreImageDilatation(struct image *src,struct image *dst,int deb,int fin,struct elementStructurant *e) {
  int nc = src->tx-2;
  for ( int l = deb ; l < fin ; l++ ) {
    if ( l%2 == 0 )
      dilateLignePaire(src,dst,nc,l,e);
      else
      dilateLigneImpaire(src,dst,nc,l,e); }
}

/**
 * Filtre une image par dilatation.
 *
 * @param src l'image a filtrer.
 * @param dst l'image resultat apres filtrage.
 * @param deb le numero de la ligne de debut du filtrage.
 * @param fin le numero de la ligne de fin du filtrage.
 * @param e l'elementStructurant de dilatation.
 * @author Nicolas Janey
 * @author nicolas.janey@univ-fcomte.fr
 * @version 1.0, 12/01/06
 */
void filtreImageDilatation(int callage,struct image *src,struct image *dst,int deb,int fin,struct elementStructurant *e) {
  int nc = src->tx-2;
  for ( int l = deb ; l < fin ; l++ ) {
    if ( (l+callage)%2 == 0 )
      dilateLignePaire(src,dst,nc,l,e);
      else
      dilateLigneImpaire(src,dst,nc,l,e); }
}
