#include #include #include #include void unexpected_eof () { fprintf (stderr, "Unexpected end of file.\n"); exit (EXIT_FAILURE); } unsigned char xget_char (FILE* f) { int read_c = fgetc (f); if (read_c == EOF) unexpected_eof (); return (unsigned char)read_c; } void unexpected_char (unsigned char c) { fprintf (stderr, "Unexpected char: %c\n", c); exit (EXIT_FAILURE); } void accept_char (FILE* f, unsigned char c) { unsigned char read_c = xget_char (f); if (read_c != c) unexpected_char (read_c); return; } void accept_whitespace (FILE* f) { unsigned char read_c = xget_char (f); switch (read_c) { case ' ': case '\t': case '\n': return; default: unexpected_char (read_c); } return; } int read_int (FILE* f) { int read_i = 0; if (fscanf (f, "%d", &read_i) == EOF) unexpected_eof (); return read_i; } int read_point_as_byte (FILE* f) { unsigned char r = xget_char (f); unsigned char g = xget_char (f); unsigned char b = xget_char (f); return /*((int)r << 16) + ((int)g << 8) +*/ (int)b; } void charge_image_ppm (const char* filename, int width, int height, int* image) { FILE* f = fopen (filename, "r"); int i, rwidth, rheight, max_val; // L'ouverture du fichier a pu échouer, dans ce cas, f == NULL. // On utilise les fonctions standards du système pour afficher // l'erreur correspondante. if (f == NULL) { perror ((const char*)strerror (errno)); exit (EXIT_FAILURE); } // Sinon, le fichier a bien été ouvert. On va pouvoir l'analyser. // On suit le format décrit dans "man ppm". // Il commence par une séquence qui caractérise les fichiers ppm. // (magic number). accept_char (f, 'P'); accept_char (f, '6'); // Suivi d'un espace. accept_whitespace (f); // La largeur. rwidth = read_int (f); accept_whitespace (f); // La hauteur. rheight = read_int (f); accept_whitespace (f); // On verifie la correspondance des tailles. if (rwidth != width || rheight != height) { fprintf (stderr, "Dimensions invalides (%d, %d) <> (%d, %d).\n", rwidth, rheight, width, height); exit (EXIT_FAILURE); } // La valeur maximale des couleurs. max_val = read_int (f); accept_whitespace (f); // Determine le nombre d'octets pour chaque couleur. // Cette fonction ne gère que les max_val <= 255. if (max_val > 255) { fprintf (stderr, "This format is not handled.\n"); exit (EXIT_FAILURE); } // Lit les donnees. for (i = 0; i < rwidth * rheight; ++i) image[i] = read_point_as_byte (f); // Ferme le fichier. fclose (f); } void enregistre_image_ppm (const char* filename, int width, int height, const int* image) { int i, j, color; FILE* f; f = fopen (filename, "w"); if (f == NULL) { perror ((const char*)strerror (errno)); exit (EXIT_FAILURE); } // Tout d'abord, on stocke les informations descriptives du fichier. fputs ("P6\n", f); fprintf (f, "%d %d\n255\n", width, height); for (j = 0; j < height; ++j) for (i = 0; i < width; ++i) { color = image[j * width + i]; fputc (color /*>> 16*/, f); fputc (/*(*/color /*>> 8) % 256*/, f); fputc(color /*% 256*/, f); } fclose (f); }