/**
 * \file Erosion.cpp
 * Implante un filtre d'erosion 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 "Erosion.h"
#include "Image.h"
#include "ElementStructurant.h"

static int acceptePixelErosionLignePaire(struct image *src,int cc,int ll,struct elementStructurant *e) {
  register int *sp = &src->p[(ll*src->tx+cc)*3];
  if ( ( e->sg != *sp ) && ( e->sg != -1 ) )
    return(0);
  if ( ( e->sd != sp[3] ) && ( e->sd != -1 ) )
    return(0);
  sp += (src->tx*3);
  if ( ( e->g != *sp ) && ( e->g != -1 ) )
    return(0);
  if ( ( e->c != sp[3] ) && ( e->c != -1 ) )
    return(0);
  if ( ( e->d != sp[6] ) && ( e->d != -1 ) )
    return(0);
  sp += (src->tx*3);
  if ( ( e->ig != *sp ) && ( e->ig != -1 ) )
    return(0);
  if ( ( e->id != sp[3] ) && ( e->id != -1 ) )
    return(0);
  return(1);
}
  
static void erodeLignePaire(struct image *src,struct image *dst,int nc,int l,struct elementStructurant *e) {
  register int *dp = &dst->p[((l+1)*dst->tx+1)*3];
  for ( int c = 0 ; c < nc ; c++ ) {
    if ( acceptePixelErosionLignePaire(src,c,l,e) ) {
      *dp = src->max;
      dp++;
      *dp = src->max;
      dp++;
      *dp = src->max;
      dp++; }
      else {
      *dp = 0;
      dp++;
      *dp = 0;
      dp++;
      *dp = 0;
      dp++; } }
}
  
static int acceptePixelErosionLigneImpaire(struct image *src,int cc,int ll,struct elementStructurant *e) {
  register int *sp = &src->p[(ll*src->tx+cc)*3];
  if ( ( e->sg != sp[3] ) && ( e->sg != -1 ) )
    return(0);
  if ( ( e->sd != sp[6] ) && ( e->sd != -1 ) )
    return(0);
  sp += (src->tx*3);
  if ( ( e->g != *sp ) && ( e->g != -1 ) )
    return(0);
  if ( ( e->c != sp[3] ) && ( e->c != -1 ) )
    return(0);
  if ( ( e->d != sp[6] ) && ( e->d != -1 ) )
    return(0);
  sp += (src->tx*3);
  if ( ( e->ig != sp[3] ) && ( e->ig != -1 ) )
    return(0);
  if ( ( e->id != sp[6] ) && ( e->id != -1 ) )
    return(0);
  return(1);
}
  
static void erodeLigneImpaire(struct image *src,struct image *dst,int nc,int l,struct elementStructurant *e) {
  register int *dp = &dst->p[((l+1)*dst->tx+1)*3];
  for ( int c = 0 ; c < nc ; c++ ) {
    if ( acceptePixelErosionLigneImpaire(src,c,l,e) ) {
      *dp = src->max;
      dp++;
      *dp = src->max;
      dp++;
      *dp = src->max;
      dp++; }
      else {
      *dp = 0;
      dp++;
      *dp = 0;
      dp++;
      *dp = 0;
      dp++; } }
}

/**
 * Filtre une image par erosion.
 *
 * @param src l'image a filtrer.
 * @param dst l'image resultat apres filtrage.
 * @param e l'elementStructurant d'erosion.
 * @author Nicolas Janey
 * @author nicolas.janey@univ-fcomte.fr
 * @version 1.0, 12/01/06
 */
void filtreImageErosion(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 )
      erodeLignePaire(src,&dst2,nc,l,e);
      else
      erodeLigneImpaire(src,&dst2,nc,l,e); }
  if ( src == dst )
    desallocationImage(dst);
  *dst = dst2;
}

/**
 * Filtre une image par erosion.
 *
 * @param src l'image a filtrer.
 * @param dst l'image resultat apres filtrage.
 * @param e l'elementStructurant d'erosion.
 * @author Nicolas Janey
 * @author nicolas.janey@univ-fcomte.fr
 * @version 1.0, 12/01/06
 */
void filtreImageErosion(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 )
      erodeLignePaire(src,&dst2,nc,l,e);
      else
      erodeLigneImpaire(src,&dst2,nc,l,e); }
  if ( src == dst )
    desallocationImage(dst);
  *dst = dst2;
}

/**
 * Filtre une image par erosion.
 *
 * @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 d'erosion.
 * @author Nicolas Janey
 * @author nicolas.janey@univ-fcomte.fr
 * @version 1.0, 12/01/06
 */
void filtreImageErosion(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 )
      erodeLignePaire(src,dst,nc,l,e);
      else
      erodeLigneImpaire(src,dst,nc,l,e); }
}

/**
 * Filtre une image par erosion.
 *
 * @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 d'erosion.
 * @author Nicolas Janey
 * @author nicolas.janey@univ-fcomte.fr
 * @version 1.0, 12/01/06
 */
void filtreImageErosion(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 )
      erodeLignePaire(src,dst,nc,l,e);
      else
      erodeLigneImpaire(src,dst,nc,l,e); }
}
