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




/* ----------------------------------- */
/*     Definition du type pixel        */
/* ----------------------------------- */


struct sPixel
{
  unsigned char red;
  unsigned char green;
  unsigned char blue;
};
typedef struct sPixel pixel;




/* -------------------------------------------------------------- */
/*     Declarations des procedures que vous pouvez appeler        */
/* (deja ecrites, code disponible pour information apres le main) */
/* -------------------------------------------------------------- */


/* Precondition : nomFichier est le nom d'un fichier au format Bitmap, 
   24-bit par pixel (donc pas de palette), non compresse. 
   Postconditions : largeur et hauteur contiennent la largeur (nombre de colonnes) 
   et la hauteur (nombre de lignes) de l'image, en nombre de pixels. 
*/
void lireEntete(const char nomFichier[], unsigned long * largeur, unsigned long * hauteur);



/* Preconditions : tab est un tableau 1D de pixels, suffisamment grand pour contenir 
   tous les pixels de l'image. nomFichier est le nom d'un fichier au format Bitmap, 
   24-bit par pixel (donc pas de palette), non compresse. largeur et hauteur 
   sont les dimensions de l'image en nombre de pixels.
   Postcondition : Chaque case de tab correspond a un pixel de l'image et contient
   ainsi les valeurs RGB de ce pixel. Les premieres cases de tab contiennent la ligne 
   de pixels tout en bas de l'image. Les cases suivantes contiennent les pixels de la 
   ligne juste au-dessus (2e ligne en partant du bas), etc, jusqu'a la ligne du haut 
   de l'image.
*/
void remplirTableauPixelsDepuisFichier(const char nomFichier[], pixel tab[], \
                                       unsigned long largeur, unsigned long hauteur);




/* Preconditions : tab est un tableau contenant largeur*hauteur pixels.
   Postconditions : Un nouveau fichier est cree, nomme comme precise dans la chaine
   de caracteres nomFic. Il est au format Bitmap, 24 bits par pixel, non compresse.
   Si un fichier de ce nom existait deja, il est ecrase.
 */
void ecrireFichier(const char nomFic[], const pixel tab[], \
                   unsigned long largeur, unsigned long hauteur);





/* -------------------------------------------------------------- */
/*     Ecrivez ci-dessous les codes des procedures demandees      */
/* -------------------------------------------------------------- */










/* -------------------------- */
/*     Completez le main      */
/* -------------------------- */


int main()
{ 

  char nomFicImage1[] = "grey_wolf.bmp";






  return 0;
}








/* Procedure auxiliaire utile pour lire les fichiers */
void fskip(FILE *fp, int num_bytes)
{
  int i;
  for (i=0; i<num_bytes; i++) {fgetc(fp);}
}




void lireEntete(const char nomFichier[], unsigned long * largeur, unsigned long * hauteur)
{
  
  FILE * fic = fopen(nomFichier, "rb");
  unsigned short bitsparpixel;
  unsigned long compression, nbcolorsinpalette, nbimportantcolors;

  if (fgetc(fic)!='B' || fgetc(fic)!='M')
  {
    fclose(fic);
    fprintf(stderr, "%s n'est pas au format BMP.\n",nomFichier);
    exit(EXIT_FAILURE);
  }

  fskip(fic,16);
  fread(largeur, sizeof(unsigned long), 1, fic);
  fread(hauteur,sizeof(unsigned long), 1, fic);

  fskip(fic, 2); /* skipping the number of color planes (always 1) */
  fread(&bitsparpixel,sizeof(unsigned short), 1, fic);

  if(bitsparpixel != 24) 
    {
      fclose(fic);      
      fprintf(stderr, "Erreur: le nombre de bits par pixel n'est pas 24, \n");
      fprintf(stderr, "ce format d'image n'est pas supporte par ce programme. \n");
      exit(EXIT_FAILURE);
    }
  fread(&compression,sizeof(unsigned long), 1, fic);
  if(compression != 0) 
    {
      fclose(fic);
      fprintf(stderr, "Erreur: le mode de compression n'est pas 0, \n");
      fprintf(stderr, "ce format d'image n'est pas supporte par ce programme. \n");
      exit(EXIT_FAILURE);
    }

  fskip(fic,12);
  fread(&nbcolorsinpalette,sizeof(unsigned long), 1, fic);
  if(nbcolorsinpalette != 0) 
    {
      fclose(fic);
      fprintf(stderr, "Erreur: le nombre de couleurs dans la palette n'est pas 0, \n");
      fprintf(stderr, "ce format d'image n'est pas supporte par ce programme. \n");
      exit(EXIT_FAILURE);
    }

  fread(&nbimportantcolors,sizeof(unsigned long), 1, fic);
  if(nbimportantcolors != 0) 
    {
      fclose(fic);
      fprintf(stderr, "Erreur: le nombre de couleurs importantes n'est pas 0, \n");
      fprintf(stderr, "ce format d'image n'est pas supporte par ce programme. \n");
      exit(EXIT_FAILURE);
    }


  fclose(fic);
}





void remplirTableauPixelsDepuisFichier(const char nomFichier[], pixel tab[], \
                                       unsigned long largeur, unsigned long hauteur)
{
  FILE * fic = fopen(nomFichier, "rb");
  unsigned long ligne, colonne, padding;

  fskip(fic, 54);
  for(ligne = 0; ligne < hauteur; ligne ++)
    {
      for (colonne = 0; colonne < largeur; colonne ++)
        {
          tab[(ligne*largeur) + colonne].red = fgetc(fic);
          tab[(ligne*largeur) + colonne].green = fgetc(fic);
          tab[(ligne*largeur) + colonne].blue = fgetc(fic);
        }

      /* Padding for 4 byte alignment */
      if( (3*largeur)%4 == 0) padding = 0;
      else padding = 4 - ((3*largeur)%4);
      fskip(fic, padding);
    }

  fclose(fic);
}



void ecrireFichier(const char nomFic[], const pixel tab[], \
                   unsigned long largeur, unsigned long hauteur)
{
  FILE * fic = fopen(nomFic, "wb");
  unsigned long monLong;
  unsigned short monShort;
  unsigned char monChar, i;
  unsigned long padding, ligne, colonne, index;

  char format[] = {'B', 'M'};
  unsigned long tailleFic = 54 + largeur*hauteur*3;

  
  fwrite(format, sizeof(char), 2, fic);

  /* size of the file in bytes */
  fwrite(&tailleFic, sizeof(unsigned long), 1, fic);

  /* Unused, app specific */
  monShort = 0;
  fwrite(&monShort, sizeof(unsigned short), 1, fic);
  fwrite(&monShort, sizeof(unsigned short), 1, fic);

  /* Offset for pixel data */
  monLong = 54;
  fwrite(&monLong, sizeof(unsigned long), 1, fic);

  /* Nb of bytes in the header from this point */
  monLong = 40;
  fwrite(&monLong, sizeof(unsigned long), 1, fic);

  fwrite(&largeur, sizeof(unsigned long), 1, fic);
  fwrite(&hauteur, sizeof(unsigned long), 1, fic);

  /* Nb of color planes (always 1) */
  monShort = 1;
  fwrite(&monShort, sizeof(unsigned short), 1, fic);

  /* Nb of bits per pixel */
  monShort = 24;
  fwrite(&monShort, sizeof(unsigned short), 1, fic);
  
  /* Compression mode */
  monLong = 0;
  fwrite(&monLong, sizeof(unsigned long), 1, fic);


  /* Size of the raw BMP data (after this header), including padding */
  if( (3*largeur)%4 == 0) padding = 0;
  else padding = 4 - ((3*largeur)%4);
  monLong = (largeur*3 + padding)*hauteur;
  fwrite(&monLong, sizeof(unsigned long), 1, fic);


  /* Horiz and vertic resolutions (pixel per metre) */
  monLong = 2835;
  fwrite(&monLong, sizeof(unsigned long), 1, fic);
  fwrite(&monLong, sizeof(unsigned long), 1, fic);


  /* Numbers of colors in the palette & number of important colors */ 
  monLong = 0;
  fwrite(&monLong, sizeof(unsigned long), 1, fic);
  fwrite(&monLong, sizeof(unsigned long), 1, fic);
 

  /* Pixel data */
  
  for(ligne = 0; ligne < hauteur; ligne ++)
    {
      for (colonne = 0; colonne < largeur; colonne ++)
        {
          index = largeur*ligne + colonne;
          fwrite(&tab[index].red, sizeof(char), 1, fic);
          fwrite(&tab[index].green, sizeof(char), 1, fic);
          fwrite(&tab[index].blue, sizeof(char), 1, fic);
        }

      /* Padding for 4 byte alignment */
      if( (3*largeur)%4 == 0) padding = 0;
      else padding = 4 - ((3*largeur)%4);
      monChar = 0;
      for (i = 0; i < padding; i++) fwrite(&monChar, sizeof(char), 1, fic);
    }

  fclose(fic);
}
