/*-----------------------------------------------------------------------------
Bibliotheque minimaliste de manipulation d'une image
Public vise : etudiants de 1ere annee universitaire
Christian Nguyen - 2012
-----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <gd.h>
#include "utv_gd.h"

static gdImagePtr imsrc = NULL; /* image principale */
static gdImagePtr imdes = NULL; /* image secondaire */
static gdImagePtr image = NULL; /* image en cours */
static utv_gd_image flag; /* drapeau pour l'image courante */
static char nomsrc[256]; /* nom du fichier image source */
static char nomdes[256]; /* nom du fichier image destination */

/*---------------------------------------------------------------------------*/
/* IMAGE SOURCE */
/*---------------------------------------------------------------------------*/
/* chargement d'une image source */
/* Remarque : pour une image PNG, la commande "file" doit donner colormap */
/* A FAIRE pour une image JPEG : convert -colors 256 *.jpg *.png */
void utv_gd_charger_image(char* pnom)
{
  FILE* fd = fopen(pnom, "rb");
  int nb;

  if (fd == NULL) {
    fprintf(stderr, "File error for %s (code %d)\n", pnom, errno);
    exit(errno);
  }

  /* si l'imsrc existe deja */
  if (imsrc != NULL)
    gdImageDestroy(imsrc);

  /* creation d'une image a partir d'un fichier PNG */
  imsrc = gdImageCreateFromPng(fd);
  strcpy(nomsrc, pnom);

  fclose(fd);

  if (imsrc == NULL) {
    fprintf(stderr, "The image is not in PNG format\n");
    exit(1);
  }

  /* flag mis a jour */
  utv_gd_image_courante(SOURCE);

  /* verification du nombre de couleurs (corruption du fichier) */
  nb = utv_gd_combien_couleurs();
  if (nb < 1 || nb > 256) {
    fprintf(stderr, "The image has the wrong number of colors (%d)\n", nb);
    exit(2);
  }
}

/*---------------------------------------------------------------------------*/
/* IMAGE DESTINATION */
/*---------------------------------------------------------------------------*/
/* creation d'une image destination */
static void utv_gd_new(char* pn)
{
  if (imsrc == NULL) {
    fprintf(stderr, "Source image not defined\n");
    exit(1);
  }

  if (imdes != NULL)
    gdImageDestroy(imdes);

  strcpy(nomdes, pn);
}
/* creation d'une image destination de taille identique a l'image source */
void utv_gd_copie_image(char* pnom)
{
  utv_gd_new(pnom);
  imdes = gdImageCreate(gdImageSX(imsrc), gdImageSY(imsrc));
}
/* creation d'une image destination de taille pl x ph */
void utv_gd_nouvelle_image(char* pnom, int pl, int ph)
{
  utv_gd_new(pnom);
  imdes = gdImageCreate(pl, ph);
}

/*---------------------------------------------------------------------------*/
/* ajouter une nouvelle couleur RVB a l'image destination */
/* A FAIRE ? gerer la couleur de fond qui est la 1ere couleur */
int utv_gd_nouvelle_couleur(int pr, int pv, int pb)
{
  int ic = 0;

  if (imdes != NULL) {
    if ((ic = gdImageColorExact(imdes, pr, pv, pb)) == -1)
      return gdImageColorAllocate(imdes, pr, pv, pb);
    else
      return ic;
  } else {
    fprintf(stderr, "Destination image not defined\n");
    exit(1);
  }
}

/*---------------------------------------------------------------------------*/
/* changer la couleur pc d'un pixel a la position (px, py) */
void utv_gd_pixel(int px, int py, int pc)
{
  if (imdes != NULL)
    gdImageSetPixel(imdes, px, py, pc);
}

/*---------------------------------------------------------------------------*/
/* sauver l'image destination au format PNG */
void utv_gd_sauver_image(char* pnom)
{
  FILE* fd;

  /* l'image destination existe-t'elle ? */
  if (imdes == NULL) {
    fprintf(stderr, "Source image not defined\n");
    exit(1);
  }

  /* ouverture d'un fichier en ecriture */
  fd = fopen(pnom, "wb");
  if (fd == NULL) {
    fprintf(stderr, "File error for %s (code %d)\n", pnom, errno);
    exit(errno);
  }

  /* l'image imdes existe : on la sauve */
  gdImagePng(imdes, fd);

  fclose(fd);
}

/*---------------------------------------------------------------------------*/
/* FONCTIONS COMMUNES */
/* toutes, sauf quitter(), sont conditionnees par image_courante() */
/*---------------------------------------------------------------------------*/
/* avant de quitter le programme */
void utv_gd_quitter(void)
{
  if (imsrc != NULL)
    gdImageDestroy(imsrc);
  if (imdes != NULL)
    gdImageDestroy(imdes);
}

/*---------------------------------------------------------------------------*/
/* passage d'une image a l'autre */
void utv_gd_image_courante(utv_gd_image pf)
{
  flag = pf;

  if (flag == SOURCE)
    if (imsrc != NULL)
      image = imsrc;
    else {
      fprintf(stderr, "Source image not defined\n");
      exit(1);
    }
  else
    if (imdes != NULL)
      image = imdes;
    else {
      fprintf(stderr, "Destination image not defined\n");
      exit(1);
    }
}

/*---------------------------------------------------------------------------*/
/* retourne la largeur de l'image courante */
int utv_gd_quelle_largeur(void)
{
  return gdImageSX(image);
}
 
/*---------------------------------------------------------------------------*/
/* retourne la hauteur de l'image courante */
int utv_gd_quelle_hauteur(void)
{
  return gdImageSY(image);
}

/*---------------------------------------------------------------------------*/
/* retourne le nombre de couleurs */
int utv_gd_combien_couleurs(void)
{
  return gdImageColorsTotal(image);
}

/*---------------------------------------------------------------------------*/
/* recupere les 3 composantes R, V, B d'un pixel */
void utv_gd_quelle_couleur(int px, int py, int* pr, int* pv, int* pb)
{
  int c = gdImageGetPixel(image, px, py);

  *pr = image->red[c];
  *pv = image->green[c];
  *pb = image->blue[c];
}

/*---------------------------------------------------------------------------*/
/* retourne l'index de la couleur du pixel a la position (px, py) */
int utv_gd_quel_index(int px, int py)
{
  return gdImageGetPixel(image, px, py);
}

/*---------------------------------------------------------------------------*/
/* retourne le nom de l'image courante */
char* utv_gd_quel_nom(void)
{
  if (flag == SOURCE)
    return nomsrc;
  else
    return nomdes;
}

