Mode
Slides
Presentation
Remote control
Send
Listen
Press F11 to switch to fullscreen.
C: Cours 6
1
Projet
2
3
Makefile
4
Images
5
Images
6
Images
7
JPEG
8
Fichiers
9
fopen
10
fgets
11
fread
12
fseek
13
5min
14
Low-level
15
mmap
16
readdir
17
mv, rm, stat
18
19
Semaine 6
Projet, images,
lire et écrire des fichiers
SSIE Programmation en C, Thomas Lochmatter, 2019
1

Projet

Série d'images + question
2

Pour commencer le projet

projet-linux.zip

projet.c
image.c
image.h
Makefile
Les bibliothèques libpng et libjpeg sont déjà installées.

projet-windows.zip

projet.c
image.c
image.h
Makefile
libpng
libjpeg
Compilées pour MinGW sous Windows.

projet-mac.zip

projet.c
image.c
image.h
Makefile
libpng
libjpeg
Compilées pour Mac OS.
3
Makefile projet.c image.c image.h projet gcc projet.c image.c ... -o projet projet: projet.c image.c image.h gcc -Wall -std=gnu11 projet.c image.c -ljpeg -lpng -lm -o projet Règles pour produire des fichiers avec la commande "make"
4
Image width = 8 height = 6 r g b Pixel 68 153 238 HTML/CSS: #4499ee ou rgba(68, 153, 238, 1.0) rouge vert bleu 0 1 2 ... 8 9 ... 47 ... i = y * width + x x = i % widthy = i / width Valeur de0 à 255 a 255 opacité 0x44 0x99 0xee Notationhex 0xff 27% 60% 93% Notation% 100%
5

Image

			struct Image {
				int width;
				int height;
				struct Pixel * pixels;
			};

		
			// Fonctions
			struct Image image;
			image_create(&image, 1000, 600);
			image_read(&image, "image.jpg");
			image_write_to_png(&image, "modifie.png");
			image_write_to_jpeg(&image, "modifie.jpeg", 95);
			image_free(&image);
		

Pixel

			struct Pixel {
				unsigned char r;
				unsigned char g;
				unsigned char b;
				unsigned char a;
			};
		
			// Modifier un pixel
			image.pixels[i].r = 68;
			image.pixels[i].g = 153;
			image.pixels[i].b = 238;
		
6
SVG

image vectorielle

fichier texte avec des polygones

PNG

image matricielle

compression sans pertes (lossless)

60x17 pixels
JPEG

image matricielle

compression avec pertes (lossy)
pour les photos

60x17 pixels
qualité 80
7

JPEG

8
Lire et écrire des fichiers fopen Ouvrir le fichier fread Lire ou écrire fclose Fermer le fichier fgets fwrite fprintf fflush Lire des bytes Lire une ligne de texte Ecrire des bytes Ecrire des valeurs comme printf Ecrire tous les buffers internes sur le disque
9

Ouvrir et fermer des fichiers

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

		// SHOW
		// Ouvrir un fichier pour le lire ("r"),
		// pour l'écrire ("w"), ou pour ajouter ("a")
		FILE * fichier = fopen("earthquake1", "r");

		// Vérification
		if (fichier == NULL) {
			printf("Impossible d'ouvrir 'earthquake1'.\n");
			return 1;
		}

		// Lire ou écrire
		...

		// Fermer le fichier
		fclose(fichier);
	
Le mode "w" détruit le fichier s'il existe. Le mode "a" garde le, et ajoute à la fin.
10

Lire et écrire des fichiers texte: fgets, fprintf

		// HIDE
		#include <stdio.h>
		#include <stdlib.h>
		FILE * fichier = ...;

		// SHOW
		char ligne[100];
		while (fgets(ligne, 100, fichier) != NULL) {
			// Traiter la ligne
			double valeur = atof(ligne);
			...
		}
	
		// HIDE
		#include <stdio.h>
		#include <stdlib.h>
		FILE * fichier = ...;

		// SHOW
		double valeur = 0.661;
		fprintf(fichier, "Valeur: %0.3f\n", valeur);
	
A chaque appel, fgets lit la prochaine ligne du fichier.
11

Lire et écrire des tableaux: fread, fwrite

		// HIDE
		#include <stdio.h>
		FILE * fichier = ...;

		// SHOW
		double donnes[1000];
		int lu = fread(donnes, sizeof (double), 1000, fichier);

		if (lu < 1000) {
			// Seulement "lu" doubles ont été lus
		}
	
		// HIDE
		#include <stdio.h>
		FILE * fichier = ...;

		// SHOW
		int ecrit = fwrite(donnes, sizeof (double), 1000, fichier);

		if (ecrit != 1000) {
			// Erreur
		}
	
12

fseek, feof, ...

		// HIDE
		#include <stdio.h>
		#include <inttypes.h>
		#include <arpa/inet.h>
		FILE * fichier = ...;

		// SHOW
		// Aller à la position 36
		fseek(fichier, 36, SEEK_SET);

		// Lire un entier 32 bits (big endian) à cette position
		uint32_t beLength;
		int readInts = fread(&beLength, 4, 1, fichier);

		// Transformation big endian -> int sur notre système
		uint32_t length = ntohl(beLength);

		// Vérifier si on est à la fin du fichier
		if (feof(fichier)) return 1;

		// Vérifier s'il y a eu une erreur de lecture
		if (ferror(fichier)) return 1;
	
fseek met la position de la prochaine lecture. feof returne 1 si on est arrivé à la fin du fichier.
13

5 min

Quand est-ce qu'on ne peut pas lire/écrire un fichier?
Qu'est-ce qu'il peut y avoir comme erreurs?
14
fopen Ouvrir le fichier fread Lire ou écrire fclose Fermer le fichier fgets fwrite fprintf fflush open read / pread close write / pwrite mmap / munmap fsync FILE * stream int fd Kernel (système d'exploitation) stdio.h unistd.h, fcntl.h, sys/stat.hsys/mman.h, sys/types.h file descriptor, file handle fcntl / ioctl
15
		// HIDE
		#include <stdio.h>
		#include <unistd.h>
		#include <fcntl.h>
		#include <sys/mman.h>

		// SHOW
		int fd = open("mnt-suisse-romande", O_RDWR);
		if (fd == -1) {
			printf("Impossible d'ouvrir le fichier.\n");
			return 1;
		}

		int longueur = 2501 * 3601 * sizeof(double);
		int type = PROT_READ | PROT_WRITE;
		double * altitudes = mmap(NULL, longueur, type, MAP_SHARED, fd, 0);

		close(fd);

		// Altitude est maintenant un tableau
		// Les changements sont écrites dans le fichier
		int altitude = altitudes[0];
		altitudes[1] = 2000;
		...

		// Libérer le tableau
		munmap(altitudes, longueur);
	

mmap est disponible sous Linux (y compris Android), Mac OS et iOS. Sous Windows, il y a MapViewOfFile.

Pour créer un tableau read-only (verrouillé), remplacer O_RDWR par O_RDONLY, et enlever PROT_WRITE.

16

Lire un répertoire: opendir, readdir, closedir

		// HIDE
		#include <stdio.h>
		#include <dirent.h>

		// SHOW
		DIR * repertoire = opendir("images");
		if (repertoire == NULL) {
			printf("Impossible de lire le répertoire 'images'.\n");
			return 1;
		}

		while (1) {
			struct dirent * fichier = readdir(repertoire);
			if (fichier == NULL) break;
			if (fichier->d_type == DT_REG) {
				printf("Fichier: %s\n", fichier->d_name);
			} else if (fichier->d_type == DT_DIR) {
				...
			}
		}

		closedir(repertoire);
	
17

rename, unlink, stat

		// HIDE
		#include <stdio.h>
		#include <unistd.h>
		#include <time.h>
		#include <sys/stat.h>

		// SHOW
		// Renommer un fichier (mv image.jpg photo.jpg)
		rename("image.jpg", "photo.jpg");

		// Effacer un fichier (rm image.jpg)
		unlink("image.jpg");

		// Informations sur un fichier (ls -l, stat image.jpg)
		struct stat info;
		int erreur = stat("image.jpg", &info);
		if (erreur) ...;

		printf("Taille: %0.2f MB\n", (double) info.st_size / 1000 / 1000);
		printf("Dernière modification: %s", ctime(&info.st_mtime));
	
Autres: link, symlink, readlink, (f)chmod, (f)chown
18

Documentation

C file input/output sur Wikipedia

unistd.h sur Wikipedia

mmap sur Wikipedia

19