JavaRush /Blog Java /Random-FR /Harvard CS50 : devoirs de la semaine 4 (cours 9 et 10)
Masha
Niveau 41

Harvard CS50 : devoirs de la semaine 4 (cours 9 et 10)

Publié dans le groupe Random-FR
Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 1

Préparation au travail

Comme toujours, ouvrez d’abord une fenêtre de terminal et exécutez la commande. update50 pour vous assurer que votre candidature est déjà à jour. Avant de commencer, suivez ceci cd ~ / workspace wget http://cdn.cs50.net/2015/fall/psets/4/pset4/pset4.zip pour télécharger une archive ZIP de cette tâche. Maintenant, si vous exécutez ls , vous verrez que vous avez un fichier appelé pset4.zip dans votre répertoire ~/workspace . Extrayez-le à l'aide de la commande : Si vous exécutez unzip pset4.zip à nouveau la commande ls , vous verrez qu'un autre répertoire est apparu. Vous pouvez maintenant supprimer le fichier zip comme indiqué ci-dessous : rm -f pset4.zip Ouvrons le répertoire pset4 cd pset4 , exécutons ls et assurons-nous que le répertoire contient bmp / jpg / questions.txt

polar ou "Qui a fait ça?"

Si vous avez déjà vu le bureau Windows XP par défaut (https://en.wikipedia.org/wiki/Bliss_(image)) (collines et ciel bleu), alors vous avez vu BMP. Sur les pages Web, vous avez probablement vu des GIF. Avez-vous regardé des photos numériques ? Nous avons donc eu la joie de voir JPEG. Si vous avez déjà pris une capture d'écran sur un Mac, vous avez probablement vu un fichier PNG. Renseignez-vous sur Internet sur les formats BMP, GIF, JPEG, PNG et répondez à ces questions :
  1. Combien de couleurs chaque format prend-il en charge ?

  2. Quel format prend en charge l’animation ?

  3. Quelle est la différence entre la compression avec et sans perte ?

  4. Lequel de ces formats utilise la compression avec perte ?

Il est conseillé à ceux qui parlent anglais de se référer à l'article du MIT . Si vous l'étudiez (ou trouvez d'autres ressources sur Internet sur le stockage de fichiers sur des disques et des systèmes de fichiers), vous pouvez répondre aux questions suivantes :
  1. Que se passe-t-il d'un point de vue technique lorsqu'un fichier est supprimé dans un système de fichiers FAT ?

  2. Que peut-on faire pour garantir (avec une forte probabilité) que les fichiers supprimés ne pourront pas être récupérés ?

Et maintenant - passons à notre histoire, qui se déroule en douceur dans la première tâche de la quatrième semaine. Bienvenue au manoir Tudor ! Le propriétaire du domaine, M. John Boddy, nous a quitté subitement, victime d'un jeu obscur. Pour découvrir ce qui s'est passé, vous devez définir polar . Malheureusement pour vous (mais encore plus malheureusement pour M. Boddy), la seule preuve dont vous disposez est le fichier BMP 24 bits Clue.bmp . C'est son contenu que vous voyez ci-dessous. M. Boddy a réussi à le créer et à le sauvegarder sur son ordinateur dans ses derniers instants. Le fichier contient une image de polar cachée parmi le bruit rouge . Vous devez maintenant travailler sur la solution comme un véritable spécialiste technique. Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 2Mais d'abord, quelques informations. Il est probablement plus simple de considérer une image comme une grille de pixels (c'est-à-dire des points), dont chacun peut être une couleur spécifique. Pour définir la couleur d'un point dans une image en noir et blanc, il nous faut 1 bit. 0 peut représenter le noir et 1 peut représenter le blanc, comme le montre l'image ci-dessous. Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 3Ainsi, les images ainsi représentées sont simplement une carte de bits (bitmap ou bitmap, comme on dit en anglais ou en argot). Avec le noir et blanc, tout est aussi simple que possible, mais pour obtenir des images en couleur, nous avons juste besoin de plus de bits par pixel. Un format de fichier (tel que GIF) prenant en charge la « couleur 8 bits » utilise 8 bits par pixel. Un format de fichier (par exemple, BMP, JPG, PNG) qui prend en charge les « couleurs 24 bits » utilise 24 bits par pixel (BMP prend en charge les couleurs 1, 4, 8, 16, 24 et 32 ​​bits). . Dans le BMP 24 bits utilisé par M. Boddy, il faut 8 bits pour indiquer la quantité de rouge, la même quantité pour le vert, et encore 8 bits pour indiquer la quantité de bleu dans chaque pixel. Si vous avez déjà entendu parler des couleurs RVB , c'est ça (R=rouge, G=vert, B=bleu). Si les valeurs R, V et B d'un pixel dans BMP sont, disons, 0xff, 0x00 et 0x00 en hexadécimal, alors le pixel sera d'un rouge pur, puisque 0xff (autrement connu sous le nom de 255 en décimal) signifie « beaucoup de rouge ». " à ce moment-là, car 0x00 et 0x00 signifient respectivement "pas de vert" et "bleu aussi des zéros". Étant donné la façon dont l'image BMP de M. Boddy nous apparaît rouge, il est intuitif que le « compartiment » rouge a une valeur nettement plus grande que les « compartiments » rouge et bleu. Cependant, tous les pixels ne sont pas rouges ; certains sont clairement d’une couleur différente. À propos, en HTML et CSS (le langage de balisage et les feuilles de style qui l'aident, qui sont utilisées pour créer des pages Web), les modèles de couleurs sont disposés de la même manière. Si vous êtes intéressé, consultez le lien : https://ru.wikipedia.org/wiki/Colors_HTMLpour plus de détails. Abordons maintenant le problème de manière plus technique. Rappelez-vous qu'un fichier est simplement une séquence de bits disposés dans un certain ordre. Un fichier BMP 24 bits est une séquence de bits, dont tous les 24 (enfin, presque) déterminent la couleur de quel pixel. En plus des données de couleur, un fichier BMP contient également des métadonnées : des informations sur la largeur et la hauteur de l'image. Ces métadonnées sont stockées au début du fichier sous la forme de deux structures de données communément appelées « en-têtes » (à ne pas confondre avec les fichiers d'en-tête C). Le premier de ces en-têtes est BITMAPFILEHEADER, qui fait 14 octets (ou 14*8 bits). Le deuxième en-tête est BITMAPINFOHEADER (40 octets de long). Après ces en-têtes vient le bitmap : un tableau d'octets dont les triplets représentent la couleur du pixel (1, 4 et 16 bits en BMP, mais pas 24 ou 32, ils ont un en-tête supplémentaire juste après le BITMAPINFOHEADER. Il s'appelle le tableau RGBQUAD, définissant la « valeur d’intensité » pour chacune des couleurs de la palette). Cependant, BMP stocke ces triplets à l'envers (on pourrait dire comme BGR), avec 8 bits pour le bleu, 8 bits pour le vert et 8 bits pour le rouge. À propos, certains BMP stockent également l'intégralité du bitmap à l'envers, en commençant par la ligne supérieure de l'image à la fin du fichier BMP. Dans notre tâche, nous avons enregistré le VMR comme décrit ici, d'abord la rangée du haut de l'image, puis celles du bas. En d’autres termes, nous avons transformé un emoji d’un bit en un emoji de 24 bits en remplaçant le noir par du rouge. Un BMP 24 bits stockera ce bitmap, où 0000ff représente le rouge et ffffff représente le blanc ; nous avons mis en évidence toutes les instances de 0000ff en rouge. Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 4Puisque nous avons présenté ces éléments de gauche à droite, de haut en bas, vous pouvez voir le smiley rouge dans ces lettres si vous vous éloignez un peu du moniteur. Rappelons qu'un chiffre dans le système numérique hexadécimal représente 4 bits. En conséquence, ffffff en hexadécimal signifie en fait 1111111111111111111111111 en binaire. Maintenant, ralentissez et n'allez pas plus loin jusqu'à ce que vous soyez sûr de comprendre pourquoi 0000ff représente un pixel rouge dans un fichier BMP 24 bits. Dans la fenêtre CS50 IDE, développez (par exemple, en cliquant sur le petit triangle) le dossier pset4 et dedans - bmp . Dans ce dossier vous trouverez smiley.bmp , double-cliquez sur le fichier et vous y trouverez un petit smiley de 8x8 pixels. Dans le menu déroulant, modifiez l'échelle de l'image, par exemple de 100 % à 400 %, cela vous permettra de voir une version plus grande, mais en même temps plus « floue » de l'émoticône. Bien qu'en réalité cette même image ne doive pas être floue même lorsqu'elle est agrandie. C'est juste que l'IDE CS50 essaie de vous rendre service (à la manière de la série CIA) en lissant l'image (en floutant visuellement les bords). Voici à quoi ressemblera notre smiley si on l'agrandit sans le lisser : Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 5Les pixels se sont transformés en grands carrés. Nous allons continuer. Dans le terminal, accédez à ~/workspace/pset4/bmp . Nous pensons que vous savez déjà comment procéder. Examinons les octets alloués dans smiley.bmp . Cela peut être fait à l'aide de l'éditeur hexadécimal de ligne de commande, le programme xxd . Pour l'exécuter, exécutez la commande : xxd -c 24 -g 3 -s 54 smiley.bmp Vous devriez voir ce qui est affiché ci-dessous ; Nous avons à nouveau surligné en rouge toutes les instances de 0000ff. Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 6Dans l'image de la colonne la plus à gauche, vous pouvez voir les adresses du fichier, qui sont équivalentes au décalage par rapport au premier octet du fichier. Tous sont donnés dans un système de nombres hexadécimaux. Si nous convertissons l'hexadécimal 00000036 en décimal, nous obtenons 54. Vous regardez donc le 54ème octet de smiley.bmp . Rappelons que dans les fichiers BMP 24 bits, les 14 + 40 = 54 octets sont remplis de métadonnées. Donc si vous voulez voir les métadonnées, exécutez la commande suivante : xxd -c 24 -g 3 smiley.bmp Si smiley.bmp contient des caractères ASCII , nous les verrons dans la colonne la plus à droite de xxd au lieu de tous ces points. Ainsi, le smiley est un BMP 24 bits (chaque pixel est représenté par 24 ÷ 8 = 3 octets) avec une taille (résolution) de 8x8 pixels. Chaque ligne (ou "Scanline" comme on l'appelle) occupe ainsi (8 pixels) x (3 octets par pixel) = 24 octets. Ce nombre est un multiple de quatre, ce qui est important car le fichier BMP est stocké légèrement différemment si le nombre d'octets dans la ligne n'est pas un multiple de quatre. Ainsi, dans small.bmp, un autre fichier BMP 24 bits dans notre dossier, vous pouvez voir une boîte verte de 3x3 pixels. Si vous l'ouvrez dans une visionneuse d'images, vous verrez qu'elle ressemble à l'image ci-dessous, mais en plus petite taille. Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 7Chaque ligne de small.bmp occupe ainsi (3 pixels) × (3 octets par pixel) = 9 octets, ce qui n'est pas un multiple de 4. Pour obtenir une longueur de ligne multiple de 4, elle est complétée par des zéros supplémentaires : entre 0 et 3 octets, nous remplissons chaque ligne au format BMP 24 bits (pouvez-vous deviner pourquoi ?). Pour small.bmp , 3 octets de zéros sont nécessaires, puisque (3 pixels) x (3 octets par pixel) + (3 octets de remplissage) = 12 octets, ce qui est en réalité un multiple de 4. Pour "voir" ce remplissage, faites ce qui suit. xxd -c 12 -g 3 -s 54 small.bmp Notez que nous utilisons une valeur différente pour -c qu'avec smiley.bmp , donc xxd ne génère cette fois que 4 colonnes (3 pour le carré vert et 1 pour le remplissage). Pour plus de clarté, nous avons mis en surbrillance toutes les instances de 00ff00 en vert. Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 8Par contraste, utilisons xxd pour le fichier large.bmp . Il ressemble exactement à small.bmp, seule sa résolution est de 12x12 pixels, soit quatre fois plus grande. Exécutez la commande ci-dessous. Vous devrez peut-être agrandir la fenêtre pour éviter le transfert. xxd -c 36 -g 3 -s 54 large.bmp Vous verrez quelque chose comme ceci : Harvard CS50 : devoirs de la semaine 4 (cours 9 et 10) - 9Attention, il n'y a aucune digression dans ce BMP ! Après tout, (12 pixels) × (3 octets par pixel) = 36 octets, et c'est un multiple de 4. L'éditeur hexadécimal xxd nous a montré les octets dans nos fichiers BMP. Comment pouvons-nous les obtenir par programmation ? Dans copy.c, il existe un programme dont le seul but dans la vie est de créer une copie du BMP, pièce par pièce. Oui, vous pouvez utiliser cp pour cela . Cependant, cp ne pourra pas aider M. Boddy. Espérons que copy.c fasse cela, alors c'est parti : ./copy smiley.bmp copy.bmp si vous exécutez maintenant ls (avec l'indicateur approprié), vous verrez que smiley.bmp et copy.bmp ont effectivement la même taille. Vérifions à nouveau si cela est réellement vrai ? diff smiley.bmp copy.bmp Si cette commande n'affiche rien à l'écran, cela signifie que les fichiers sont bien identiques (important : certains programmes, comme Photoshop, incluent des zéros à la fin de certains VMP. Notre version de copie les supprime, alors ne le faites pas vous inquiétez si, en cas de copie d'autres BMP que vous avez téléchargés ou créés pour les tests, la copie sera quelques octets plus petite que l'original). Vous pouvez ouvrir les deux fichiers dans la visionneuse d'images de Ristretto (double-clic) pour le confirmer visuellement. Mais diff fait cette comparaison octet par octet, donc sa vision est plus nette que la vôtre ! Comment cette copie a-t-elle été créée ? Il s'avère que copy.c est lié à bmp.h . Assurons-nous-en : ouvrez bmp.h. Vous y verrez les définitions réelles de ces en-têtes que nous avons déjà mentionnés, adaptées des propres implémentations de Microsoft. De plus, ce fichier définit les types de données BYTE, DWORD, LONG et WORD, qui sont les types de données généralement trouvés dans le monde de la programmation Win32 (c'est-à-dire Windows). Notez qu’il s’agit essentiellement d’alias de primitives que vous connaissez (espérons-le) déjà. Il s'avère que BITMAPFILEHEADER et BITMAPINFOHEADER utilisaient ces types. Ce fichier définit également une structure appelée RGBTRIPLE. Il « encapsule » trois octets : un bleu, un vert et un rouge (c'est l'ordre dans lequel on va chercher les triplets RVB sur le disque). En quoi ces structures sont-elles utiles ? Pour récapituler, un fichier est simplement une séquence d'octets (ou finalement de bits) sur le disque. Cependant, ces octets sont généralement ordonnés de manière à ce que les premiers représentent quelque chose, puis les suivants représentent autre chose, et ainsi de suite. Les « formats » de fichiers existent parce que nous avons des normes, ou des règles, qui définissent la signification des octets. Désormais, nous pouvons simplement lire le fichier du disque vers la RAM sous la forme d'un grand tableau d'octets. Et nous nous souvenons que l'octet en position [i] représente une chose, tandis que l'octet en position [j] est autre chose. Mais pourquoi ne pas donner des noms à certains de ces octets afin que nous puissions les récupérer plus facilement de la mémoire ? C’est exactement pour cela que les structures de bmp.h nous aident. Au lieu de considérer un fichier comme une longue séquence d’octets, nous le voyons décomposé en blocs plus compréhensibles – des séquences de structures. Rappelez-vous que smiley.bmp a une résolution de 8x8 pixels, il occupe donc 14 + 40 + (8 × 8) × 3 = 246 octets sur le disque (vous pouvez vérifier cela en utilisant la commande ls). Voici à quoi cela ressemble sur le disque selon Microsoft : Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 10Nous pouvons voir que l'ordre est important lorsqu'il s'agit des membres des structures. L'octet 57 est rgbtBlue (pas, disons, rgbtRed) car rgbtBlue est défini en premier dans RGBTRIPLE. Soit dit en passant, notre utilisation de l'attribut packagé garantit que clang n'essaie pas d'« aligner les mots » des membres (l'adresse du premier octet de chaque membre étant un multiple de 4), afin que nous ne nous retrouvions pas avec des trous dans nos structures qui n'existent pas du tout sur disque. Allons-nous en. Recherchez les URL qui correspondent à BITMAPFILEHEADER et BITMAPINFOHEADER, selon les commentaires dans bmp.h. Attention, grand moment : vous commencez à utiliser MSDN (Microsoft Developer Network) ! Au lieu de faire défiler plus loin copy.c , répondez à quelques questions pour comprendre comment fonctionne le code. Comme toujours, la commande man est votre véritable amie, et maintenant aussi MSDN. Si vous ne connaissez pas les réponses, recherchez-les sur Google et réfléchissez-y. Vous pouvez également vous référer au fichier stdio.h sur https://reference.cs50.net/.
  1. Définissez un point d'arrêt dans main (en cliquant à gauche de la règle avec les numéros de ligne principale).

  2. Dans un onglet de terminal , accédez à ~/workspace/pset4/bmp et compilez copy.c dans le programme de copie à l'aide de make.

  3. Exécutez debug50 copy smiley.bmp copy.bmp , cela ouvrira le panneau du débogueur sur la droite.

  4. Parcourez le programme étape par étape en utilisant le panneau de droite. Notez bf et bi . Dans ~/workspace/pset4/questions.txt , répondez aux questions :

  • Qu'est-ce que stdint.h ?

  • Quel est l'intérêt d'utiliser uint8_t , uint32_t , int32_t et uint16_t dans un programme ?

  • Combien d'octets BYTE , DWORD , LONG et WORD contiennent respectivement (en supposant une architecture 32 bits) ?

  • Que doivent être (ASCII, décimal ou hexadécimal) les deux premiers octets d'un fichier BMP ? (les octets de tête, qui sont utilisés pour identifier le format de fichier (avec une forte probabilité) sont souvent appelés « nombres magiques »).
  • Quelle est la différence entre bfSize et biSize ?

  • Que signifie un biHeight négatif ?

  • Quel champ dans BITMAPINFOHEADER définit la profondeur de couleur en BMP (c'est-à-dire bits par pixel) ?

  • Pourquoi la fonction fopen peut-elle renvoyer NULL dans copy.c 37 ?

  • Pourquoi le troisième argument à fread dans notre code est-il égal à 1 ?

  • Quelle valeur dans copy.c 70 définit le remplissage si bi.biWidth est 3 ?

  • Que fait fseek ?

  • Qu'est-ce que SEEK_CUR ?

Revenons à M. Boddy. Exercice:

Écrivez un programme appelé whodunit dans un fichier appelé whodunit.c qui montre le dessin de M. Boddy. Hummm, quoi ? Comme pour la copie, le programme doit prendre exactement deux arguments de ligne de commande, et si vous exécutez votre programme comme indiqué ci-dessous, le résultat sera stocké dans verdict.bmp, dans lequel le dessin de M. Boddy ne sera pas bruyant. ./whodunit clue.bmp verdict.b Laissez-nous vous suggérer de commencer à résoudre ce mystère en exécutant la commande ci-dessous. cp copy.c whodunit.c Vous pourriez être étonné du nombre de lignes de code que vous devez écrire pour aider M. Boddy. Il n'y a rien d'inutile caché dans smiley.bmp , alors n'hésitez pas à tester le programme sur ce fichier. C'est petit, et vous pouvez comparer la sortie de votre programme et la sortie de xxd pendant le développement (ou peut-être qu'il y a quelque chose de caché dans smiley.bmp ? En fait, non). Soit dit en passant, ce problème peut être résolu de différentes manières. Une fois que vous aurez identifié le dessin de M. Boddy, il reposera en paix. Étant donné que Whodunit peut être implémenté de plusieurs manières, vous ne pourrez pas vérifier l'exactitude des implémentations avec check50 . Et laissez cela gâcher votre plaisir, mais la solution des assistants n'est pas non plus disponible pour le problème du polar . Enfin, dans le fichier In ~/workspace/pset4/questions.txt , répondez à la question suivante : Whodunit? //ктоэтосделал?

redimensionner

Eh bien, maintenant – le prochain test ! Écrivons un programme appelé resize dans resize.c . Il redimensionnera une image BMP 24 bits non compressée par étapes de n. Votre application doit accepter exactement trois arguments de ligne de commande, le premier (n) étant un nombre entier ne dépassant pas 100, le deuxième étant le nom du fichier qui sera modifié et le troisième étant le nom de la version enregistrée du fichier modifié. déposer. Usage: ./resize n infile outfile Avec un tel programme, nous pourrions créer large.bmp à partir de small.bmp en redimensionnant ce dernier par 4 (c'est-à-dire en multipliant à la fois la largeur et la hauteur par 4), comme indiqué ci-dessous. ./resize 4 small.bmp large.bmp Pour plus de simplicité, vous pouvez démarrer la tâche en copiant à nouveau copy.c et en nommant la copie resize.c . Mais d'abord, posez-vous et répondez à ces questions : que signifie changer la taille du BMP (vous pouvez supposer que n fois la taille du fichier entrant ne dépassera pas 232 - 1) . Déterminez les champs de BITMAPFILEHEADER et BITMAPINFOHEADER que vous devez modifier. Déterminez si vous devez ajouter ou supprimer des champs de lignes de balayage . Et oui, soyez reconnaissant que nous ne vous demandions pas de considérer toutes les valeurs possibles de n de 0 à 1 ! (même si, si cela vous intéresse, c'est un problème issu du livre d'un hacker ;)). Cependant, nous supposons que pour n = 1, le programme fonctionnera correctement et le fichier de sortie aura la même taille que le fichier d'entrée d'origine. Voulez-vous vérifier le programme à l’aide de check50 ? Tapez la commande suivante : check50 2015.fall.pset4.resize bmp.h resize.c Voulez-vous jouer avec l'implémentation d'application réalisée par les assistants CS50 ? Exécutez ce qui suit : ~cs50/pset4/resize Eh bien, si vous souhaitez voir, par exemple, les en-têtes large.bmp (sous une forme plus conviviale que ne le permet xxd), vous devez exécuter la commande suivante : ~cs50/pset4/peek large.bmp Encore mieux, si vous souhaitez comparer vos headers avec les en-têtes des fichiers assistants CS50. Vous pouvez exécuter des commandes dans votre répertoire ~/workspace/pset4/bmp (pensez à ce que fait chaque commande). Si vous avez utilisé malloc , assurez-vous d'utiliser free pour éviter les fuites de mémoire. Essayez d'utiliser valgrind pour vérifier les fuites. ./resize 4 small.bmp student.bmp
~cs50/pset4/resize 4 small.bmp staff.bmp
~cs50/pset4/peek student.bmp staff.bmp

Comment décider ?

  • Ouvrez le fichier que nous devons agrandir, ainsi que créez et ouvrez un nouveau fichier dans lequel l'image agrandie sera enregistrée ;

  • mettre à jour les informations d’en-tête du fichier de sortie. Puisque notre image est au format BMP et que nous modifions sa taille, nous devons écrire l'en-tête du nouveau fichier avec les nouvelles dimensions. Qu'est-ce qui va changer ? La taille du fichier, ainsi que la taille de l’image – sa largeur et sa hauteur.

Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 11Si nous regardons la description de l'en-tête, nous verrons la variable biSizeImage . Il indique la taille totale de l'image en octets, biWidth est la largeur de l'image moins l'alignement, biHeight est la hauteur. Ces variables se trouvent dans les structures BITMAPFILEHEADER et BITMAPINFOHEADER. Vous pouvez les trouver si vous ouvrez le fichier bmp.h. Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 12La description de la structure BITMAPINFOHEADER contient une liste de variables. Pour écrire le titre du fichier de sortie, vous devrez modifier les valeurs de hauteur et de largeur. Mais il est également possible que vous ayez besoin plus tard de la hauteur et de la largeur d'origine du fichier d'origine. Il est donc préférable de conserver les deux. Soyez prudent avec les noms de variables afin de ne pas écrire accidentellement des données erronées dans l'en-tête du fichier de sortie.
  • Nous lisons le fichier sortant, ligne par ligne, pixel par pixel. Pour ce faire, nous nous tournons à nouveau vers notre bibliothèque d'E/S de fichiers et la fonction fread. Il faut un pointeur vers une structure qui contiendra les octets lus, la taille de l'élément unique que nous allons lire, le nombre de ces éléments, et un pointeur vers le fichier à partir duquel nous allons lire.

    Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 13
  • Nous augmentons chaque ligne horizontalement selon l'échelle spécifiée et écrivons le résultat dans le fichier de sortie.

    Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 14

    Comment écrivons-nous des fichiers ? Nous avons une fonction fwrite, à laquelle nous transmettons un indicateur sur la structure où se trouvent les données à écrire dans le fichier, la taille des éléments, leur numéro et un pointeur vers le fichier de sortie. Pour organiser la boucle, nous pouvons utiliser la boucle for que nous connaissons déjà .

    Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 15
  • Remplir les trous! Si le nombre de pixels dans une ligne n'est pas un multiple de quatre, il faut ajouter "l'alignement" - zéro octet. Nous aurons besoin d'une formule pour calculer la taille de l'alignement. Pour écrire des octets nuls dans un fichier de sortie, vous pouvez utiliser la fonction fputc, en lui passant le caractère que vous souhaitez écrire et un pointeur vers le fichier de sortie.

    Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 16

    Maintenant que nous avons étiré la chaîne horizontalement et ajouté un alignement au fichier de sortie, nous devons déplacer la position actuelle dans le fichier de sortie car nous devons sauter par-dessus l'alignement.

    Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 17
  • Augmentez la taille verticale. C'est plus compliqué, mais nous pouvons utiliser l'exemple de code de copy.c (copy.c ouvre le fichier de sortie, écrit un en-tête dans le fichier de sortie, lit l'image du fichier source ligne par ligne, pixel par pixel, et les écrit au fichier de sortie). Sur cette base, la première chose que vous pouvez faire est d'exécuter la commande suivante : cp copy.c resize.c

    Étirer une image verticalement signifie copier chaque ligne plusieurs fois. Il existe plusieurs manières différentes de procéder. Par exemple, en utilisant la réécriture, lorsque nous enregistrons tous les pixels d'une ligne en mémoire et écrivons cette ligne dans le fichier de sortie en boucle autant de fois que nécessaire. Une autre méthode consiste à recopier : après avoir lu une ligne du fichier sortant, l'avoir écrite dans le fichier de sortie et l'avoir alignée, renvoyez la fonction fseek au début de la ligne du fichier sortant et répétez tout plusieurs fois.

    Harvard CS50 : devoirs de la semaine 4 (cours 9 et 10) - 18
  • récupérer

    En prévision du document de travail de la semaine 4, j'ai passé ces derniers jours à regarder des photos enregistrées au format JPEG par mon appareil photo numérique sur une carte mémoire CompactFlash (CF) de 1 Go. S'il vous plaît, ne me dites pas plutôt que j'ai passé ces derniers jours sur Facebook. Malheureusement, mes compétences en informatique laissent beaucoup à désirer, et sans le savoir, j'ai accidentellement supprimé toutes les photos ! Heureusement, dans le monde informatique, « supprimé » n’équivaut généralement pas à « tué ». Mon ordinateur insiste sur le fait que la carte mémoire est désormais vide, mais je sais qu'il ment. Devoir : Écrivez un programme dans ~/workspace/pset4/jpg/recover.c qui récupérera ces photos. Hmmm. D'accord, voici encore une précision. Bien que le format JPEG soit plus complexe que le BMP, le format JPEG possède des « signatures », des modèles d'octets qui permettent de le distinguer des autres formats de fichiers. La plupart des fichiers JPEG commencent par les trois octets suivants : 0xff 0xd8 0xff Du premier octet au troisième, de gauche à droite. Le quatrième octet sera très probablement l'une des combinaisons suivantes : 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,0xe8, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef. En d’autres termes, les quatre premiers bits du quatrième octet d’un fichier JPEG sont 1110. Il y a de fortes chances que si vous trouvez l'un de ces motifs sur le lecteur où les photos ont été stockées (comme ma carte mémoire), ce sera le début du fichier JPEG. Bien sûr, vous pouvez rencontrer ce problème sur quel disque par hasard ; la récupération de données ne peut pas être qualifiée de science exacte.

    Comment décider

    1. Ouvrez le fichier avec le contenu de la carte mémoire.

    2. Recherchez le début du fichier JPEG. Tous les fichiers de cette carte sont des images au format JPEG.

    Vous connaissez déjà les marqueurs JPEG : Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 19il est important (et agréable) de savoir que chaque fichier JPEG est stocké en mémoire sous la forme d'un seul bloc et que les fichiers eux-mêmes se succèdent. Dessinons une carte mémoire schématique. Chaque rectangle est un bloc de 512 octets de long. Les rectangles gris sont des zones où il n'y a pas de fichiers JPEG ; les astérisques indiquent le début du fichier JPEG. Nous pensons qu'il n'y a pas de blocs gris entre les fichiers. Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 20Comment lire ces données, ces 512 octets, pour en comparer le début avec l'en-tête JPEG ? Nous pouvons utiliser la fonction fread , qui nous est déjà familière, qui prend un pointeur vers la structure de données dans laquelle les octets lus seront écrits, ainsi que la taille de l'élément en cours de lecture, le nombre de ces éléments et un pointeur vers le fichier à partir duquel nous lisons les données. Harvard CS50 : devoirs de la quatrième semaine (cours 9 et 10) - 21Nous voulons lire 512 octets et les stocker dans un tampon. Ce sera le pointeur &data, et le pointeur inptr pointera vers le fichier ouvert avec le contenu de la carte mémoire. Revenons donc à la structure de notre fichier, dans lequel nous enregistrons
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION