--- jupytext: text_representation: extension: .md format_name: myst format_version: 0.13 kernelspec: display_name: Python 3 (ipykernel) language: python name: python3 --- +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "d6b46a0a95cd43ae80dbc181dc125671", "grade": false, "grade_id": "cell-10", "locked": true, "schema_version": 3, "solution": false, "task": false}} # Semaine 8 : fichiers et flux de données +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "dc414efeceffd39f0262e39fbf550a1d", "grade": false, "grade_id": "cell-20", "locked": true, "schema_version": 3, "solution": false, "task": false}} ## <a name=Cours/>[Cours](cours.md) - Cours : [flux de données](cours-flux.md) - Cours : [fichiers](cours-fichiers.md) - Cours : [état d'un fichier](cours-etat-fichier.md) - Cours : [lecture et écriture dans des chaînes de caractères](cours-flux-chaines-de-caracteres.md) +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "dbf5500bedb753c425b378e4748347d6", "grade": false, "grade_id": "cell-30", "locked": true, "schema_version": 3, "solution": false, "task": false}} ## [TD : fichiers et images numériques](TD.md) +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "bf4d86ed29ba34ce66bdbc753d794093", "grade": false, "grade_id": "cell-40", "locked": true, "schema_version": 3, "solution": false, "task": false}} ## TP +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "6ff5819dcd18e689494acb0ba1af242e", "grade": false, "grade_id": "cell-49", "locked": true, "schema_version": 3, "solution": false, "task": false}} ### Exercice 0 : Jupyter : l'indentation À faire chez vous! - [Jupyter : l'indentation](00-jupyter-indentation.md) +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "9dd26fe469908352fac43de3f823d14a", "grade": false, "grade_id": "cell-50", "locked": true, "schema_version": 3, "solution": false, "task": false}} ### Exercice 1 : écrire dans un fichier - 20 minutes +++ ::::{hint} Rappels - Pour exécuter un programme, il faut d’abord avoir compilé le fichier `.cpp` avec la commande `clang++` puis lancer l’exécutable créé par la compilation. Consultez au besoin les instructions des TP précédents. - Pensez à organiser votre espace de travail et à ajuster la taille des caractères (avec <kbd>Ctrl</kbd>-<kbd>+</kbd> et <kbd>Ctrl</kbd>-<kbd>-</kbd>) pour avoir une vue confortable simultanée de tous les éléments requis : consignes, code, terminal. :::{figure} https://nicolas.thiery.name/Enseignement/Info111/media/screencast-espace-de-travail-compilation.gif Vidéo: organiser son espace de travail avec JupyterLab ::: :::: +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "8124382c9ab91f1d2004315ed95e82c1", "grade": false, "grade_id": "cell-60", "locked": true, "schema_version": 3, "solution": false, "task": false}} 1. Consultez le fichier [fichier-ecriture.cpp](fichier-ecriture.cpp). 2. Essayez de deviner ce que fait ce programme. 3. Exécutez ce programme. 4. Trouvez le fichier `.txt` qui a été créé à l’exécution et l’ouvrir avec un éditeur de texte. Que contient-il? 5. Copiez le contenu de [fichier-ecriture.cpp](fichier-ecriture.cpp) dans [fichier-ecriture-v2.cpp](fichier-ecriture-v2.cpp), et adaptez le pour qu’à l’exécution il écrive un fichier nommé `essai.txt` contenant le texte «17 fois 23 vaut» suivi de la valeur de ce nombre (valeur que le programme calcule par lui-même). 6. Exécutez ce programme puis ouvrez le fichier `essai.txt` afin de vérifier son contenu. 7. Lisez et essayez à nouveau dans le cours l'exemple de [lecture depuis le clavier](cours-flux.md) avec `cin`. 8. En vous en inspirant, complétez le programme [cin.cpp](cin.cpp) pour que, à l’exécution, il demande à l’utilisateur d’entrer deux entiers, puis qu’il écrive un fichier nommé `multiplication.txt` contenant un texte similaire au fichier `essai.txt` de la question précédente, avec 17 et 23 remplacés respectivement par les deux entiers choisis par l’utilisateur. :::{note} Pour faire des affichages à l’écran et pour faire saisir des données depuis le clavier, il faut inclure la bibliothèque `iostream` en écrivant `#include <iostream>`. Pour lire et écrire dans un fichier de texte, il faut inclure la bibliothèque `fstream` en écrivant `#include <fstream>` ::: 9. Exécutez le programme puis ouvrez le fichier `multiplication.txt` pour vérifier son contenu. +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "cb2c18e19c408b69d4d8589c8f7649cd", "grade": false, "grade_id": "cell-70", "locked": true, "schema_version": 3, "solution": false, "task": false}} ### Exercice 2 : ouvrir le smiley - 5 minutes +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "5f1d313afad6f51ebf42d10eb2ea7a42", "grade": false, "grade_id": "cell-80", "locked": true, "schema_version": 3, "solution": false, "task": false}} Le fichier [media/smiley.pbm](media/smiley.pbm) (dans le répertoire `media` donc!) contient l’image en noir et blanc du TD. 1. Ouvrez ce fichier d’abord avec un éditeur de texte. Depuis le navigateur de fichiers de JupyterLab: clic droit -> Ouvrir avec -> Éditeur. 2. Ouvrez ce même fichier avec un logiciel de vision d’images. Pour cela, depuis Jupyter, vous pouvez utiliser la cellule ci-dessous : ```{code-cell} from open_ppm import open_ppm # importe la commande open_ppm fournie im = open_ppm("media/smiley.pbm") # charge l'image im.resize((256*im.width // im.height, 256)) # affiche l'image avec une taille donnée ``` :::{admonition} Pour les curieux :class: dropdown Python et Jupyter ne savent pas manipuler nativement les fichiers aux formats PBM, PGM ou PPM non compressés. La commande `open_ppm('xxx.ppm')` fournie dans le fichier [open_ppm.py](open_ppm.py) commence par utiliser l'utilitaire `convert` de `ImageMagick` avec `convert xxx.ppm xxx.png` pour convertir l'image en format PNG. ::: Alternativement : - Sous Windows, vous pouvez utiliser l’application `irfanview`. - Sous Linux, vous pouvez utiliser l’application `xviewer` : utilisez «Control +» et «Control -» pour zoomer / dezoomer. Vous remarquerez que l’image est lissée / floutée. Allez dans le menu «Edit -> Preferences» et décochez «Smooth images when zoomed in» pour mieux voir les pixels. ### Exercice 3 : petit damier - 15 minutes +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "7a193c543e70cced08244a1a71520334", "grade": false, "grade_id": "cell-90", "locked": true, "schema_version": 3, "solution": false, "task": false}} 1. Utilisez un éditeur de texte pour écrire à la main un **fichier texte** `damier.pbm` contenant une image au format PBM ([*Portable Bit Map*](http://fr.wikipedia.org/wiki/Portable_bitmap)) de taille 10×10 représentant un damier : :::{image} media/damier_svg.png :width: 10% :alt: un damier ::: 2. Visualisez le résultat, par exemple avec : ```{code-cell} from open_ppm import open_ppm im = open_ppm("damier.pbm") im.resize((256*im.width // im.height, 256)) ``` (indications_images)= :::{hint} Indications en cas d'erreur à la visualisation ou d'image incorrecte :class: dropdown - Vérifiez que le fichier existe, dans le répertoire `Semaine8`, avec le bon nom et la bonne extension (`.pbm`, `.pgm`, ou `.ppm` selon l'exercice). - Ouvrez le fichier avec un éditeur de texte. - Vérifiez l'entête de l'image: - la première ligne contient `P1` (format PBM), `P2` (format PGM) ou `P3` (format PPM); - la deuxième ligne (sans compter les lignes de commentaires commençant par `#`) contient deux entiers: le nombre $c$ de colonnes et le nombre $l$ de lignes; - pour les fichiers `pbm` ou `ppm`: la troisième ligne contient un entier $m$. - Vérifiez que le reste du fichier consiste d'entiers séparés par des espaces ou des sauts de ligne: - format `pbm`: $cl$ entiers $0$ ou $1$; - format `pgm`: $cl$ entiers entre $0$ et $m$; - format `ppm`: $3cl$ entiers entre $0$ et $m$. - Vérifiez que les valeurs sont adéquates. ::: Tests automatiques : ```{code-cell} assert im.size == (10, 10), "l'image n'est pas de taille 10×10" ``` ```{code-cell} import numpy as np M = np.array(im, dtype=int) assert np.all(M[1:,:] + M[:-1,:] == 1), "l'image n'est pas un damier horizontalement" assert np.all(M[:,1:] + M[:,:-1] == 1), "l'image n'est pas un damier verticalement" ``` +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "65237cca3ba3cf9fb579a874a7f3f6b1", "grade": false, "grade_id": "cell-100", "locked": true, "schema_version": 3, "solution": false, "task": false}} ### Exercice 4 : grand damier +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "792992fb2ce3f4d9bf342c4bee84e65a", "grade": false, "grade_id": "cell-110", "locked": true, "schema_version": 3, "solution": false, "task": false}} Complétez le **programme C++** [damier.cpp](damier.cpp) qui, lorsqu’on l’exécute, écrit un fichier image `damier-automatique.pbm` comme le précédent, mais cette fois pour un damier 100x100. Visualisez et vérifiez au fur et à mesure le résultat avec : ```{code-cell} im = open_ppm("damier-automatique.pbm") im.resize((512*im.width // im.height, 512)) ``` +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "8b8ba5a75745c14276324532d144a1fe", "grade": false, "grade_id": "cell-120", "locked": true, "schema_version": 3, "solution": false, "task": false}} :::{hint} Indications - Vous pouvez vous inspirer de [fichier-ecriture.cpp](fichier-ecriture.cpp). - Commencez par un programme pour un damier 10×10 avant de passer à 100×100. - L'exécution de votre programme devrait être instantanée ou presque. Si ce n'est pas le cas, interrompez le avec <kbd>Ctrl</kbd>-<kbd>C</kbd>. - Vérifiez la taille du fichier produit en tapant la commande suivante dans le terminal : ``` ls -lh *.pbm ``` Il devrait faire dans les 20 kilo octets (20K). Veillez à le supprimer s'il fait nettement plus que cela. - Si le fichier produit ne donne pas l’image attendue, ou si vous n'arrivez pas à le visualiser: reportez vous aux [indications de l'exercice précédent](#indications_images). - Si cela vous aide, vous pouvez aussi dans un premier temps afficher le texte produit à l’écran avec `cout`; puis écrivez le dans le fichier dans un deuxième temps. ::: +++ Tests automatiques : ```{code-cell} assert im.size == (100, 100), "l'image produite n'est pas de taille 100×100" ``` ```{code-cell} import numpy as np M = np.array(im, dtype=int) assert np.all(M[1:,:] + M[:-1,:] == 1), "l'image n'est pas un damier horizontalement" assert np.all(M[:,1:] + M[:,:-1] == 1), "l'image n'est pas un damier verticalement" ``` +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "fec81568499bca600d3cae6fb9dc41c0", "grade": false, "grade_id": "cell-130", "locked": true, "schema_version": 3, "solution": false, "task": false}} ### Exercice 5 : dégradé de gris Pour créer une image avec des nuances de gris, il faut enregistrer un fichier de texte au format PGM ([Portable Gray Map](http://fr.wikipedia.org/wiki/Portable_graymap)). Ce fichier doit contenir des nombres entre 0 et une valeur maximale (au choix) qui représenteront les différentes nuances de gris. +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "3175edfdcd2ba6f573443ce9504466dd", "grade": false, "grade_id": "cell-140", "locked": true, "schema_version": 3, "solution": false, "task": false}} 1. Écrivez à la main, dans un éditeur de texte, un fichier `essai.pgm` représentant une image de taille 10×10 contenant différentes nuances de gris de votre choix. Vérifiez au fur et à mesure le résultat avec : ```{code-cell} im = open_ppm("essai.pgm") im.resize((256*im.width // im.height, 256)) ``` Tests automatiques : ```{code-cell} assert im.size == (10, 10), "l'image produite n'est pas de taille 10×10" ``` +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "65f16b8b10337cf30c2a8273bd57ff79", "grade": false, "grade_id": "cell-150", "locked": true, "schema_version": 3, "solution": false, "task": false}} 2. Implantez un programme [degrade.cpp](degrade.cpp) qui écrit un fichier contenant une image `degrade.pgm` de taille 128x128, avec un dégradé de gris comme celui-ci : :::{image} media/degrade.png :width: 20% :alt: un dégradé de gris ::: ```{code-cell} im = open_ppm("degrade.pgm") im.resize((256*im.width // im.height, 256)) ``` Tests automatiques : ```{code-cell} assert im.size == (128, 128), "l'image produite n'est pas de taille 128×128" ``` +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "4f500798eefc2a87622c29ef17e57230", "grade": false, "grade_id": "cell-160", "locked": true, "schema_version": 3, "solution": false, "task": false}} 3. Répétez, avec une image de taille 100×100 +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "9c9224e94d136176282b95357c8edd88", "grade": false, "grade_id": "cell-170", "locked": true, "schema_version": 3, "solution": false, "task": false}} ### Exercice 6 : inversion d’image +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "f3fa5bea0ea3429d63f52fd66e7d3369", "grade": false, "grade_id": "cell-180", "locked": true, "schema_version": 3, "solution": false, "task": false}} Implantez un programme [videoInverse.cpp](videoInverse.cpp) qui lit un fichier contenant une image au format PGM (par exemple le fichier `media/image.pgm` fourni), et écrit un fichier contenant la même image en vidéo inverse (clair remplacé par sombre et réciproquement). +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "2a4cc77ee0d0dcd169aad954bff7fd0a", "grade": false, "grade_id": "cell-190", "locked": true, "schema_version": 3, "solution": false, "task": false}} :::{hint} Indication Implantez une fonction ``` c++ /** Image en vidéo inverse * @param image1: le nom du fichier contenant l'image à lire * @param image2: le nom du fichier pour l'image à écrire **/ void videoInverse(string image1, string image2); ``` ::: +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "8e4c6932227912a0021029a54216d0ec", "grade": false, "grade_id": "cell-200", "locked": true, "schema_version": 3, "solution": false, "task": false}} ### Exercice 7 : dégradé circulaire de rouge ♣ +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "a4badd45d2e8d7c755437d2bcc49f9bc", "grade": false, "grade_id": "cell-210", "locked": true, "schema_version": 3, "solution": false, "task": false}} 1. Implantez un programme [degrade-circulaire.cpp](degrade-circulaire.cpp) qui écrit un fichier contenant une image `degrade-circulaire.ppm` au format PPM de taille 255×255, avec un dégradé circulaire de rouge: :::{image} media/degrade-circulaire.png :width: 20% :alt: un dégradé circulaire ::: 2. Répétez, avec une image de taille 100×100.