[Powered by Google Translate] [Procédure pas à pas - 4 Set problème] [Zamyla Chan - Université de Harvard] [C'est CS50. - CS50.TV] Très bien. Bonjour à tous et bienvenue dans Procédure pas à pas 4. Aujourd'hui, notre pset est Forensics. Forensics est un pset vraiment amusant qui consiste à traiter les fichiers bitmap de découvrir qui a commis un crime. Ensuite, nous allons redimensionner certains fichiers bitmap, puis nous allons aussi faire face à une partie vraiment fun appelé Recover, dans laquelle nous sommes fondamentalement remis une carte mémoire dans laquelle quelqu'un a accidentellement supprimé tous leurs fichiers, et nous a demandé de récupérer ces fichiers. Mais d'abord, avant d'entrer dans le pset, je veux simplement féliciter tout le monde. Nous sommes sur au milieu de ce cours. Quiz 0 est derrière nous, et nous sommes à pset4, si essentiellement, nous sommes à mi-chemin. Nous avons parcouru un long chemin, si vous regardez en arrière à vos psets, PSET0 et pset1, si vous féliciter à ce sujet, et nous allons entrer dans quelque chose de vraiment amusant. Donc, notre boîte à outils pour ce pset, encore une fois, au lieu de courir sudo yum-y update, nous sommes en mesure de simplement exécuter update50 si vous êtes à la version 17.3 et au-dessus de l'appareil. Assurez-vous donc à courir update50 - c'est beaucoup plus facile, quelques personnages moins - afin de s'assurer que vous êtes à la dernière version de l'appareil. Surtout, il est important de update50 lorsque nous commençons à utiliser CS50 Check. Donc, assurez-vous que vous faites cela. Pour toutes les sections de ce pset, nous allons avoir affaire avec des entrées et sorties de fichiers, File I / O. Nous allons aller sur un grand nombre de programmes qui traitent avec des tableaux pointant vers des fichiers et des choses comme ça, Nous voulons donc nous assurer que nous sommes vraiment familier et confortable traitant de la façon de l'entrée et de sortie dans des fichiers. Dans le code de distribution de ce pset est un fichier appelé copy.c, et c'est ce que nous allons trouver va être vraiment utile pour nous parce que nous allons finir par copier l'copy.c et il suffit de modifier légèrement pour être en mesure d'atteindre les 2 premières parties du problème posé. Et alors que je l'ai mentionné plus tôt, nous avons affaire à des bitmaps ainsi que JPEG. Alors, vraiment comprendre la structure de la façon dont ces fichiers sont organisés, comment nous pouvons vraiment traduire le 0 et de 1 dans structs et les choses que nous pouvons réellement comprendre et d'interpréter et de modifier, qui sera très important, afin d'entrer dans les fichiers JPEG et bitmap et la compréhension de la structure de celles-ci. Pset4, comme d'habitude, commence par une section de questions. Ceux-ci traitent avec le fichier d'E / S et de vous habitués à cela. Ensuite, la partie 1 est Whodunit, dans lequel on vous donne un fichier bitmap qui ressemble un peu à points rouges partout. Et puis, fondamentalement ce que nous allons faire est de prendre ce fichier et il suffit de modifier légèrement dans une version que l'on peut lire. Essentiellement, une fois terminer, nous aurons le même fichier, sauf que nous serons en mesure de voir le message caché caché par tous ces points rouges. Puis Resize est un programme qui, étant donné un fichier et alors le nom du fichier qui l'émet et reçoit un numéro et, sera effectivement redimensionner ce bitmap par cette valeur entière. Puis enfin, nous avons le pset Recover. On nous donne une carte mémoire et ensuite de récupérer toutes les photos qui ont été accidentellement supprimés, mais, comme nous allons apprendre, pas réellement supprimés et retirés du dossier; nous avons juste un peu perdu là où ils étaient dans le dossier, mais nous allons récupérer cela. Grande. Donc, allez dans le dossier I / O précisément, il s'agit de toute une liste de fonctions que vous allez utiliser. Vous avez déjà vu un peu les bases de la fonction fopen, fread fwrite, et, mais nous allons approfondir certains fichiers I / O fonctions telles que fputc, dans lequel vous venez d'écrire un caractère à la fois, à fseek, où vous sorte de déplacer l'indicateur de position avant et arrière, et puis quelques autres. Mais nous en discuterons un peu plus tard au cours de la pset. Alors d'abord, juste pour entrer dans le fichier I / O avant d'aller dans le pset, pour ouvrir un fichier, par exemple, ce que vous avez à faire est de définir un pointeur vers ce fichier. Nous avons donc un pointeur FILE *. Dans ce cas, je vais l'appeler un pointeur parce que ça va être mon infile. Et donc je vais utiliser la fonction fopen, puis le nom du fichier puis le mode dans lequel je vais être en charge du dossier. Il ya donc "r" dans ce cas pour la lecture, "w" pour l'écriture, puis «a» pour l'ajout. Par exemple, lorsque vous avez affaire à un infile et tout ce que vous voulez faire est de lire les bits et les octets qui y sont stockées, alors vous allez probablement vouloir utiliser "r" comme mode. Lorsque vous voulez vraiment écrire, sorte de créer un nouveau fichier, alors qu'est-ce que nous allons faire, c'est que nous allons ouvrir le nouveau fichier et utiliser le "w" en mode d'écriture. Alors quand vous êtes en train de lire dans les fichiers, la structure est la suivante. D'abord vous incluez le pointeur vers la structure qui contiendra les octets que vous lisez. Alors que va être la position de fin des octets que vous lisez. Vous êtes alors va pour indiquer la taille, comme essentiellement le nombre d'octets votre programme est à lire dans le fichier, la taille essentiellement un élément est, et puis vous allez spécifier le nombre d'éléments que vous souhaitez lire. Et puis enfin, vous devez savoir où vous lisez, de sorte que ça va être votre pointeur dans. J'ai un code de couleur, car ceux-ci fread est également très similaire à fwrite, sauf que vous voulez vous assurer que vous utilisez le bon ordre, assurez-vous que vous êtes en train d'écrire ou de lire à partir du fichier de droite. Alors que précédemment, si nous avons la taille de l'élément ainsi que le nombre d'éléments, alors on peut jouer ici un peu. Dire que j'ai une struct DOG et alors j'ai envie de lire deux chiens à la fois. Ce que je pourrais faire est de dire la taille d'un élément va être la taille d'un chien et je vais lire quand même deux d'entre eux. Sinon, ce que je pourrais faire est de dire que je vais tout simplement lire un élément et qu'un élément va être la taille de deux chiens. Donc, c'est la façon dont vous pouvez analogue genre de jeu autour de la taille et du nombre selon ce qui est plus intuitif. Très bien. Alors maintenant, nous arrivons à des fichiers d'écriture. Lorsque vous voulez écrire un fichier, le premier argument est en fait où vous lisez. Donc, c'est à peu près les données que vous allez écrire dans le fichier, qui est le pointeur à la fin. Ainsi, lorsque vous faites affaire avec le pset, assurez-vous de ne pas confondre. Peut-être que le côté définitions de l'autre. Vous pouvez tirer sur les définitions dans le manuel en tapant man et fwrite, par exemple, dans le terminal, ou vous pouvez vous référer à cette diapositive et assurez-vous que vous utilisez la bonne. Encore une fois, pour fwrite, quand vous avez un fichier que vous voulez écrire dans, qui va être le dernier argument et que ça va être un pointeur vers ce fichier. Alors c'est comme ça que nous traitons avec l'écriture peut-être plusieurs octets à la fois, mais disons que vous voulez juste écrire en un seul caractère. Comme nous le verrons plus tard dans cet exemple, les bitmaps nous devrons utiliser. C'est alors que nous pouvons utiliser fputc, essentiellement juste en mettant un caractère à la fois, chr, dans le pointeur de fichier, et c'est notre pointeur là-bas. Alors chaque fois que nous cherchons ou écrire dans un fichier, le fichier est garder la trace de l'endroit où nous sommes. Donc, c'est une sorte de curseur, l'indicateur de position. Et donc, chaque fois que nous écrivons ou relire dans un fichier, le fichier se souvient effectivement là où il est, et il continue de l'endroit où se trouve le curseur. Cela peut être utile lorsque vous souhaitez, par exemple, de lire dans un certain laps de faire quelque chose puis lire dans le montant suivant, mais parfois nous pourrions revenir en arrière ou en fait de partir d'une certaine valeur de référence. Alors la fonction fseek, ce qu'il fait est nous permet de déplacer le curseur dans un fichier donné un certain nombre d'octets. Et puis, ce que nous avons à faire est de spécifier l'endroit où la valeur de référence. Alors, soit il se déplace vers l'avant ou vers l'arrière de l'endroit où le curseur se trouve actuellement, ou nous pouvons spécifier qu'il doit simplement déplacer à partir du début du fichier ou à partir de la fin de l'image. Et afin que vous puissiez passer des valeurs négatives ou positives à la quantité, et qui sorte de déplacer le curseur vers l'avant ou vers l'arrière. Avant d'entrer dans les psets autres, des questions sur le fichier I / O? D'accord. Comme nous entrons dans d'autres exemples, n'hésitez pas à m'arrêter pour les questions. Donc, en Whodunit, vous êtes remis un fichier bitmap semblable à celui-rouge sur la diapositive, et il semble que cela - un tas de points rouges - et vous ne savez pas vraiment ce qui est écrit. Si vous strabisme, vous pourriez être en mesure de voir une légère coloration bleutée à l'intérieur du milieu. Essentiellement, c'est là où le texte est stocké. Il y avait une assassiner ce qui s'est passé, et nous avons besoin de savoir qui a fait ça. Pour ce faire, nous devons genre de convertir cette image en un format lisible. Si vous jamais rencontré ce, parfois, il serait petits kits où vous auriez une loupe avec un film rouge. N'importe qui? Ouais. Donc, vous serait quelque chose comme ceci mains, vous auriez une loupe avec le film rouge dessus, vous serait-il mis sur l'image, et vous serez en mesure de voir le message caché dedans. Nous n'avons pas une loupe avec un film rouge, de sorte qu'au lieu que nous allons sorte de créer notre propre dans ce jeu de processeurs. Et afin que l'utilisateur va polar entrée, puis l'indice,. Bmp, de sorte que c'est la infile, c'est le message red dot, et puis ils disent verdict.bmp va être notre fichier de sortie. Donc, il va créer une nouvelle image bitmap similaire à l'indice une sauf dans un format lisible où l'on peut voir le message caché. Puisque nous allons avoir affaire à éditer et manipuler des bitmaps d'une certaine sorte, nous allons type de plongée dans la structure de ces fichiers bitmap. Nous sommes allés sur ces bits un peu en cours, mais nous allons les examiner un peu plus. Les bitmaps sont essentiellement juste un arrangement d'octets où nous avons spécifié les octets dire quoi. Voici donc un peu comme une carte de l'image bitmap dire que cela commence avec certains fichiers d'en-tête, commence avec quelques informations là-dedans. Vous voyez que, à propos de l'octet numéro 14, la taille est indiquée sur l'image bitmap, et il continue son chemin. Mais alors qu'est-ce qui nous intéresse vraiment ici commence autour de l'octet numéro 54. Nous avons ces triplets RVB. Qu'est-ce que ça va faire, c'est de contenir les pixels réels, les valeurs de couleur. Tout ce qui précède que, dans l'en-tête est une information correspondant à la taille de l'image, la largeur de l'image, et la hauteur. Quand nous allons en rembourrage plus tard, nous verrons pourquoi la taille de l'image peut être différente de la largeur ou de la hauteur. Alors pour représenter celles-ci - ces images bitmap sont des séquences d'octets - ce que nous pourrions faire est de dire ok, je vais me souviens qu'à l'indice 14, c'est là que la taille est, par exemple, mais plutôt ce que nous allons faire pour rendre cela plus facile est de l'encapsuler dans une structure. Et nous avons donc deux structures faites pour nous, un BITMAPFILEHEADER et un BITMAPINFOHEADER, et donc, chaque fois que nous lisons dans ce fichier, par défaut, il va se passer dans l'ordre, et ainsi de suite afin qu'elle va aussi à remplir dans des variables telles que biWidth et biSize. Et puis enfin, chaque pixel est représenté par trois octets. La première est la quantité de bleu dans le pixel, le second est la quantité de vert, et enfin, la quantité de rouge, où 0 est essentiellement pas de vert bleu ou rouge ou aucun puis ss est la valeur maximale. Ce sont des valeurs hexadécimales. Alors si nous avons ff0000, puis qui correspond à la quantité maximale de bleu et puis pas de vert et pas de rouge, oui, alors cela nous donnerait un pixel bleu. Alors, si nous avons tous ff de toute la ligne, cela signifie que nous avons un pixel blanc. C'est une sorte de face à généralement lorsque nous disons RVB. Il va vraiment BGR. Donc, si nous avons effectivement se pencher sur l'exemple d'une image bitmap - permettez-moi d'arracher ici. C'est un petit peu. Je suis un zoom avant, et nous pouvons voir qu'il est pixélisé. Il ressemble à des blocs de couleur. Vous avez blocs blancs, puis les blocs rouges. Si vous jouez dans Microsoft Paint, par exemple, vous pourriez faire quelque chose comme ça par tout simplement de peindre certaines cases dans un ordre spécifique. Alors, que cela se traduit dans le bitmap est la suivante. Ici, nous avons premiers pixels blancs, que tous les 6 sont f, puis nous avons pixels rouges, indiqué par 0000ff. Et si la séquence d'octets que nous avons indique comment l'image bitmap va regarder. Alors qu'est-ce que j'ai fait ici est juste d'écrire sur tous les octets et coloré dans le rouge de sorte que vous pouvez sorte de le voir, si vous strabisme un peu, comment ce genre de montre un visage souriant. La façon dont le travail bitmap images est je l'avais envisagée essentiellement comme une grille. Et si par défaut, chaque ligne de la grille doit être un multiple de 4 octets. Si l'on regarde une image bitmap, vous remplissez dans chaque valeur. Par exemple, vous pourriez avoir un rouge ici, ici un vert, un bleu ici, mais vous devez vous assurer que l'image est rempli avec un multiple de quatre octets. Donc, si je veux que mon image soit trois blocs de large, alors je dois mettre une valeur vide dans le dernier pour en faire un multiple de quatre. Alors, je voudrais ajouter quelque chose que nous appelons rembourrage. Je vais juste pour indiquer qu'il ya un x. Maintenant, disons que nous voulons une image qui est de 7 pixels de long, par exemple. Nous avons 1, 2, 3, 4, 5, 6, 7, et tout cela est rempli avec la couleur. La façon dont les images bitmap travail est que nous avons besoin d'un 8. Actuellement, nous avons 1, 2, 3, 4, 5, 6, 7. Nous avons besoin de 8 places pour l'image bitmap à lire correctement. Alors que nous avons à faire est d'ajouter dans un peu de rembourrage afin de s'assurer que toutes les largeurs sont uniformes et que toutes les largeurs sont un multiple de 4. Et si je l'ai déjà indiqué, rembourrage comme x ou une ligne ondulée, mais dans les images réelles bitmap le rembourrage est indiqué par un 0 en hexadécimal. Ce serait donc un caractère unique, 0. Quel pourrait être utile est la commande xxd. Ce qu'il fait est fait, vous montre, comme semblable à ce que je faisais avant avec le smiley quand j'ai fait imprimer ce que chaque couleur serait pour le pixel puis un code de couleur, lorsque vous exécutez xxd avec les commandes suivantes, alors il va vraiment imprimer ce que les couleurs sont pour ces pixels. Qu'est-ce que vous avez à faire est ici j'indique, comme le s-54 me dit que je vais commencer à l'octet 54ème car avant cela, rappelez-vous, si nous regardons en arrière sur la carte des bitmaps, c'est tout ce que les informations d'en-tête et des choses comme ça. Mais ce qui nous intéresse vraiment, c'est sur les pixels réels qui indiquent la couleur. Donc, en ajoutant que le drapeau,-s 54, alors nous sommes en mesure de voir les valeurs de couleur. Et ne vous inquiétez pas les drapeaux compliquées et des choses comme ça. Dans la spécification problème posé, vous aurez des instructions sur la façon d'utiliser xxd pour afficher les pixels. Donc, si vous voyez ici, il sorte de ressemble à une boîte verte, cette petite chose. J'ai un code de couleur du 00ff00 que revient à dire pas de bleu, beaucoup de vert, et non rouge. Alors qui correspond au vert. Comme vous le voyez ici, nous voyons un rectangle vert. Ce rectangle vert est à seulement 3 pixels de large, de sorte que ce que nous avons à faire afin de s'assurer que l'image est un multiple de 4 de large est d'ajouter dans un rembourrage supplémentaire. Et alors c'est comme ça que vous voyez ces 0s ici. Ce sera effectivement le résultat de votre pset Redimensionner, prenant essentiellement la petite image, puis en l'agrandissant par 4. Et si ce que nous voyons, c'est que vraiment cette image est de 12 pixels de large, mais 12 est un multiple de 4, et si nous avons effectivement ne vois pas de 0s à la fin parce que nous n'avons pas besoin d'ajouter de car il est entièrement rembourré. Il n'a pas de place non plus. D'accord. Une question sur votre padding? D'accord. Cool. Comme je l'ai mentionné précédemment, les bitmaps sont juste une séquence d'octets. Et donc ce que nous avons est au lieu de devoir suivre exactement quel numéro de l'octet correspond à un élément spécifique, nous avons effectivement créé une structure pour représenter cela. Donc, ce que nous avons est une struct RGBTRIPLE. Chaque fois que vous avez une instance d'un triplet RVB, parce que c'est un type définissent struct, vous pouvez accéder à la variable rgbtBlue, de même, les variables de vert et rouge, qui indiquent combien bleu,, vert et rouge respectivement, que vous avez. Donc, si nous avons l'ensemble de variables bleu à 0, l'ensemble vert et suivants, qui est la valeur maximale que vous pouvez avoir, et puis le rouge variable à 0, alors quelle couleur serait-ce particulier RVB triple représentent-ils? >> [L'élève] Green. Vert. Exactement. Il va être intéressant de savoir que chaque fois que vous avez une instance d'un triplet RVB, vous pouvez accéder à la quantité de couleur - bleu, vert et rouge - séparément. Maintenant que nous avons parlé de la structure de cela, nous allons jeter un oeil au fichier BMP. Ce sont structs faites pour vous. Ici, nous avons une structure BITMAPFILEHEADER. D'intérêt est la taille. Plus tard, nous avons l'entête d'info, qui a un peu plus de choses qui sont intéressantes pour nous, à savoir la taille, la largeur et la hauteur. Comme nous allons passer à plus tard, quand vous lisez dans le fichier, il lit automatiquement parce que nous avons mis de l'ordre d'être le même. Si la biSize contiendra les octets bons qui correspondent à la taille réelle de l'image. Et puis voilà, enfin, comme nous en avons parlé, nous avons la struct typedef RGBTRIPLE. Nous avons un rgbtBlue, vert, rouge et qui lui est associé. Grande. D'accord. Maintenant que nous comprenons un peu bitmaps, de comprendre que nous avons un fichier d'en-tête et un collecteur d'informations qui lui est associé et puis après ça, nous avons les choses intéressantes des couleurs, et ces couleurs sont représentées par des structs RGBTRIPLE, et ceux qui, à leur tour, ont trois valeurs associées au bleu, le vert et le rouge. Alors maintenant, nous pouvons type de pensez à récupérer un peu. Désolé. Pensez à Whodunit. Quand nous avons notre fichier indice, alors ce que nous voulons faire est de lire pour elle, pixel par pixel puis changer quelque chose à ces pixels pour que nous puissions le sortir dans un format lisible. Et donc de le sortir, nous allons écrire pixel par pixel dans le fichier verdict.bmp. C'est le genre de beaucoup à faire. Nous sommes conscients que. Donc, ce que nous avons fait, c'est que nous avons effectivement mis à votre disposition copy.c. Qu'est-ce copy.c fait est fait juste une copie exacte d'un fichier bitmap donné, puis il sort. Donc, ce qui ouvre déjà le fichier pour vous, se lit en pixel par pixel, et écrit ensuite dans dans un fichier de sortie. Jetons un coup d'oeil. Ce n'est assurant le bon usage, obtenir les noms des fichiers ici. Qu'est-ce que cela fait est qu'il définit le fichier d'entrée à ce que nous avons adoptée en la infile ici, qui est notre deuxième ligne de commande argument. Vérifie que l'on peut ouvrir le fichier. Vérifie que nous pouvons faire une outfile nouveau ici. Alors qu'est-ce le cas ici, ça commence essentiellement de lecture dans le fichier bitmap depuis le début. Le début, comme nous le savons, contient le BITMAPFILEHEADER, et si ces séquences de bits sera directement remplir le BITMAPFILEHEADER. Donc, ce que nous avons ici est dire que bf BITMAPFILEHEADER - c'est notre nouvelle variable de BITMAPFILEHEADER type - nous allons mettre à l'intérieur bf ce que nous lisons à partir de pointeur, qui est notre infile. Combien avons-nous lu? Nous lisons dans le nombre d'octets que nous devons contenir la BITMAPFILEHEADER ensemble. De la même manière, c'est ce que nous faisons pour l'entête d'info. Nous continuons donc notre fichier long dans le infile, et nous lisons les bits et les octets, et nous sommes les branchant directement dans dans ces cas, des variables que nous faisons. Ici, nous sommes juste s'assurer que le bitmap est un bitmap. Maintenant nous avons un fichier de sortie, non? Donc, en l'état où nous la créons, c'est essentiellement vide. Nous devons donc essentiellement de créer un nouveau bitmap à partir de zéro. Ce que nous faisons est que nous devons nous assurer que nous copier dans le fichier d'en-tête et l'entête d'info comme l'a infile. Ce que nous faisons est que nous écrivons - et n'oubliez pas que bf est la variable BITMAPFILEHEADER de type, de sorte que nous faisons est que nous venons d'utiliser ce contenu d'écrire dans le fichier de sortie. Ici, rappelez-vous, nous avons parlé de rembourrage, comment il est important de s'assurer que la quantité de pixels que nous avons est un multiple de 4. Il s'agit d'une formule très utile pour calculer combien vous avez rembourrage compte tenu de la largeur de votre dossier. Je veux que vous de se rappeler que dans copy.c nous avons une formule pour le calcul de rembourrage. Okay? Alors rappelez-vous que tout le monde. Grande. Alors, que fait copy.c prochain est-il une itération sur toutes les lignes de balayage. Elle passe par les lignes d'abord, puis stocke chaque triplet qu'il lit et écrit ensuite dans le fichier de sortie. Alors ici nous lisons une seule RGB triple à un moment et en mettant ensuite que les trois mêmes dans le fichier de sortie. Le point délicat est que le rembourrage n'est pas un triplet RVB, et si nous ne pouvons pas lire ce montant rembourrage de triplets RVB. Ce que nous avons à faire est de simplement déplacer notre indicateur de position, déplacez le curseur notre, de sorte de sauter par-dessus tout le rembourrage de sorte que nous sommes à la ligne suivante. Et alors qu'est-ce que cela fait est exemplaire vous montre comment vous pouvez ajouter du rembourrage. Nous avons donc calculé combien nous avons besoin de rembourrage, ce qui signifie que nous avons besoin de rembourrage nombre de 0. Qu'est-ce que cela fait est une boucle qui met numéro de rembourrage de 0s dans notre fichier de sortie. Et puis enfin, vous fermez les deux fichiers. Vous fermez la infile ainsi que le fichier de sortie. C'est comme ça que copy.c travaux, et que ça va être très utile. Au lieu de simplement fait directement copier-coller ou tout simplement regarder et en tapant ce que vous voulez, vous pourriez vouloir exécuter cette commande dans le terminal, cp copy.c whodunit.c, ce qui va créer un nouveau fichier, whodunit.c, qui contient le contenu exactement la même que la copie ne. Alors ce que nous pouvons faire, c'est de l'utiliser comme un cadre sur lequel construire et modifier pour notre fichier polar. Ce sont nos listes de tâches à faire pour Whodunit, mais ce ne copy.c est s'occupe effectivement de la plupart de nous. Donc, tout ce que nous devons faire maintenant est de changer les pixels en fonction des besoins de faire réellement le fichier lisible. Rappelez-vous que pour un pixel donné triple, donc pour une variable donnée RGBTRIPLE type, vous pouvez accéder aux bleus, les valeurs vertes et rouges. Cela va venir dans maniable parce que si vous pouvez y accéder, ce qui signifie que vous pouvez également les consulter, ce qui signifie que vous pouvez également les modifier. Alors, quand nous sommes retournés à notre exemple loupe rouge, essentiellement, qui agissait comme une sorte de filtre pour nous. Donc, ce que nous voulons faire, c'est que nous voulons filtrer tous les triplets qui sont à venir po Il ya plusieurs façons de le faire. Fondamentalement, vous pouvez avoir n'importe quel type de filtre que vous souhaitez. Peut-être que vous voulez changer tous les pixels rouges ou peut-être que vous voulez changer un pixel de couleur différente d'une couleur différente. C'est à vous. N'oubliez pas que vous pouvez vérifier quelle est la couleur du pixel est et puis vous pouvez également le modifier comme vous le vivez. D'accord. Donc, c'est Whodunit. Une fois que vous exécutez Whodunit, vous saurez qui est le coupable du crime était. Maintenant, nous allons aller à redimensionner. Nous allons encore avoir affaire avec des bitmaps. Ce que nous allons faire, c'est que nous allons avoir un bitmap d'entrée puis nous allons passer dans un certain nombre, puis faire une image bitmap outfile où c'est essentiellement notre infile mise à l'échelle par n. Dis mon dossier était juste un gros pixel. Ensuite, si mon n est 3, mise à l'échelle par 3, alors je tiens à répéter que pixel n certain nombre de fois, donc 3 fois, et puis aussi le réduire 3 fois aussi. Donc, vous voyez que je suis en train de mise à l'échelle aussi bien verticalement qu'horizontalement. Et puis, voici un exemple. Si vous avez n = 2, on voit que le premier pixel bleu il répété deux fois aussi bien horizontalement que verticalement deux fois. Et puis qui se poursuit sur, et si vous avez une mise à l'échelle directe de votre image originale par deux. Alors, si nous étions au détail le pseudo-code pour cela, nous voulons ouvrir le fichier. Et puis, sachant que si nous revenons ici, nous voyons que la largeur de la outfile va être différente de la largeur de la infile. Qu'est-ce que ça veut dire? Cela signifie que nos informations d'en-tête va changer. Et donc ce que nous voudrons faire est de mettre à jour les informations d'en-tête, sachant que quand nous lisons dans les fichiers si vous vous trouvez sur le cadre copy.c, nous avons déjà une variable qui indique ce qui est de la taille et des choses comme ça. Donc, une fois que vous avez, ce que vous pouvez faire est de changer ces variables particulières. Rappelez-vous, si vous avez une structure, comment accéder à des variables au sein de cette. Vous pouvez utiliser l'opérateur point, non? Alors que l'aide, vous savez que vous aurez besoin de changer l'information d'en-tête. Alors, voici juste une liste des éléments réels qui vont se modifier dans votre fichier. La taille de fichier va changer, l'image, ainsi que la largeur et la hauteur. Donc, on peut ensuite revenir à la carte des bitmaps, regarde si c'est l'en-tête du fichier ou l'entête d'info qui contient l'information puis effectuez les modifications nécessaires. Encore une fois, dire cp copy.c resize.c. Cela signifie que resize.c contient maintenant tout ce qui est contenu à l'intérieur copie parce copie nous donne une façon de lire pour chaque pixel par pixel scanline. Sauf que maintenant, au lieu de simplement changer les valeurs comme nous l'avons fait dans Whodunit, ce que nous voulons faire, c'est que nous voulons écrire en pixels multiples aussi longtemps que notre n est supérieur à 1. Alors ce que nous voulons faire, c'est que nous voulons pour l'étirer horizontalement par n, ainsi que l'étirer verticalement par n. Comment pourrions-nous faire cela? Supposons que votre n est 2 et que vous avez cette donnée infile. Votre curseur va commencer à la première, et ce que vous voulez faire si n est 2, vous souhaitez imprimer en 2 de ceux-ci. Ainsi, vous imprimez en 2 de ceux-ci. Ensuite, le curseur va se déplacer au pixel suivant, qui est le rouge, et il va imprimer 2 de ces rouges, en l'ajoutant sur ce qu'il a fait avant. Ensuite, le curseur se déplace vers le pixel suivant et tirer dans 2 d'entre eux. Si vous regardez en arrière à la copy.c cadre, ce que cela fait ici il est crée une nouvelle instance d'un triplet RVB, une nouvelle variable appelée triple. Et là, quand il lit en lui, il lit le infile 1 RGBTRIPLE et les stocke à l'intérieur de cette variable triple. Alors vous avez réellement une variable représentant ce pixel particulier. Puis, quand vous écrivez, ce que vous pouvez faire est envelopper la déclaration fwrite dans une boucle for qu'il écrit dans votre fichier de sortie autant de fois que nécessaire. C'est assez simple. Juste essentiellement répéter le processus d'écriture n fois à l'échelle horizontalement. Mais nous devons nous rappeler que notre padding va changer. Auparavant, dire que nous avions quelque chose de longueur 3. Ensuite, nous avons voudrais simplement ajouter dans la marge intérieure? Un pas de plus pour en faire un multiple de 4. Mais dire que nous sommes l'extension de cette image particulière en n = 2. Alors combien de pixels bleus aurions-nous à la fin? Nous aurions 6. 1, 2, 3, 4, 5, 6. Très bien. 6 n'est pas un multiple de 4. Quelle est la plus proche multiple de 4? Cela va être 8. Donc, nous allons en fait d'avoir 2 caractères de rembourrage là. Est-ce que quelqu'un se souvient si nous avons une formule pour calculer rembourrage et où cela pourrait être? [Réponse de l'élève inaudible] >> Ouais, copy.c. Droite. Il existe une formule en copy.c de calculer combien vous avez rembourrage étant donné une certaine largeur de l'image bitmap. Alors qui va être utile lorsque vous avez besoin d'ajouter une certaine quantité de rembourrage pour vraiment comprendre à quel point vous avez besoin de rembourrage à ajouter. Mais on note, cependant, c'est que vous voulez vous assurer que vous utilisez la bonne taille. Il suffit de faire attention parce que vous êtes essentiellement allez avoir affaire avec deux images bitmap. Vous voulez vous assurer que vous utilisez la bonne. Lorsque vous calculez le rembourrage pour le fichier de sortie, vous souhaitez utiliser la largeur de la outfile et pas la largeur de la précédente. Grande. Ce genre de prend soin d'étirer une image bitmap entière horizontalement. Mais ce que nous voulons faire, c'est effectivement l'étirer verticalement. Cela va être un peu plus compliqué parce que quand nous avons fini de copier une ligne et de l'écriture de cette ligne, notre curseur va être à la fin. Donc, si nous lisons encore, alors il va tout simplement à lire à la ligne suivante. Alors qu'est-ce que nous voulons faire est une sorte de trouver un moyen de copier ces lignes à nouveau ou juste une sorte de prendre cette ligne, puis le réécrire à nouveau. Comme je l'ai mentionné genre d', il existe plusieurs façons différentes de faire ça. Qu'est-ce que vous pourriez faire, c'est que vous vivez et de la lecture à travers la ligne de balayage particulière et le changer si nécessaire, puis type de magasin tous les pixels dans un tableau. Puis, plus tard, vous savez que vous aurez besoin d'imprimer ce tableau encore, et si vous pouvez simplement utiliser ce tableau pour le faire. Une autre façon de le faire est que vous pourriez copier une ligne plus bas, comprendre que vous avez besoin de copier ce nouveau, donc en fait déplacer le curseur, et qui va être en utilisant la méthode fseek. Vous pouvez déplacer votre curseur complètement vers l'arrière, puis répétez le processus de copie. Donc, si notre numéro de mise à l'échelle est n, alors combien de fois devrions-nous revenir en arrière et réécrire une droite? >> [L'élève] n - 1. >> Ouais, parfait. n - 1. Nous l'avons fait une fois déjà, oui, alors nous voulons répéter le processus de retour en arrière n - 1 nombre de fois. D'accord. Donc là vous avez votre fonction de redimensionnement. Maintenant, nous pouvons arriver à une partie vraiment fun, mon pset favori, qui est Recover. Au lieu de bitmaps, cette fois nous avons affaire à des fichiers JPEG. Nous sommes effectivement pas donné d'un fichier, de JPEG, on nous donne essentiellement un format brut carte mémoire. Et si celui-ci contient un peu de valeurs d'information et d'ordures au début, et ensuite il commence et il a un tas de fichiers JPEG. Toutefois, nous a remis une carte où nous avons supprimé les photos; pour l'essentiel, nous avons oublié d'où les photos se trouvent dans la carte. Alors notre tâche dans Recover est de passer par ce format de carte et de trouver les images à nouveau. Heureusement, la structure des fichiers JPEG et le fichier de carte est un peu utile. Il a certainement aurait pu être un peu plus compliqué si ce n'était pas dans ce format particulier. Chaque fichier JPEG commence réellement avec deux séquences possibles, listés ci-dessus. Fondamentalement, lorsque vous avez un nouveau fichier JPEG, elle commence par la séquence supporte ffd8 FFE0 ou ​​l'autre, ffd8 FFE1. Une autre chose utile de savoir, c'est que les fichiers JPEG sont stockées de façon contiguë. Donc, chaque fois qu'un fichier JPEG se termine, l'autre commence. Il n'y a donc pas n'importe quel type d'entre-deux valeurs de y. Dès que vous atteignez le début d'un JPEG, si vous avez déjà lu un JPEG, vous savez que vous avez atteint la fin de la précédente et le début de la suivante. Pour genre de visualiser cela, j'ai fait un schéma. Une autre chose à propos de JPEG est que nous pouvons les lire dans des séquences de 512 octets à la fois, De la même façon avec le début de la carte. Nous n'avons pas besoin d'être vérifié chaque octet unique parce que ce serait sucer. Ainsi, au lieu, ce que nous pouvons faire, c'est en fait juste lu dans 512 octets à la fois puis, au lieu de vérifier entre ceux dans les tranches minuscules, nous pouvons simplement vérifier le début des 512 octets. Essentiellement, dans ce tableau, ce que vous voyez est à l'origine de la carte, vous avez des valeurs qui ne sont pas vraiment pertinentes pour les fichiers JPEG eux-mêmes. Mais alors qu'est-ce que j'ai, c'est une étoile pour indiquer l'une des deux séquences à partir d'un fichier JPEG. Donc, chaque fois que vous voyez une étoile, vous savez que vous avez un fichier JPEG. Et puis chaque fichier JPEG va être un multiple de 512 octets mais pas nécessairement le même multiple. La façon dont vous savez que vous avez touché un autre format JPEG est si vous frappez une autre étoile, une autre séquence d'octets de départ. Alors qu'est-ce que vous avez ici est que vous avez le fichier JPEG rouge continue jusqu'à ce que vous appuyez sur une étoile, qui est indiqué par une couleur différente. Vous continuez et puis vous cliquez sur une autre étoile, vous touchez un autre JPEG, vous continuez tout le chemin jusqu'à la fin. Vous êtes à la dernière image ici, la rose. Vous allez à la fin jusqu'à ce que vous atteignez le caractère de fin de fichier. Cela va être vraiment utile. A emporter quelques grandes ici: Le fichier de la carte ne démarre pas avec un fichier JPEG, mais une fois commence JPEG, toutes les images JPEG sont stockés côte à côte les uns aux autres. Certains pseudo-code pour le récupérer. Tout d'abord, nous allons ouvrir notre fichier de carte, et qui va être en utilisant notre fichier d'E / S des fonctions. Nous allons répéter le processus ci-dessous jusqu'à ce que nous avons atteint la fin du fichier. Nous allons lire 512 octets à la fois. Et ce que j'ai dit ici, c'est que nous allons les stocker dans une mémoire tampon, Donc, fondamentalement, conserver ces 512 octets jusqu'à ce que nous savons exactement quoi faire avec eux. Alors ce que nous voulons faire, c'est que nous voulons vérifier si nous avons touché une étoile ou pas. Si nous avons touché une étoile, si nous avons atteint l'une des séquences de départ, alors nous savons que nous avons atteint un nouveau fichier JPEG. Ce que nous allons veux faire, c'est que nous allons vouloir créer un nouveau fichier dans notre annuaire pset4 de continuer à faire ce fichier. Mais aussi, si nous avons déjà fait un JPEG avant, alors nous voulons mettre fin à ce fichier et poussez-le vers le dossier pset4, où nous aurons ce fichier stocké parce que si on ne précise pas que nous avons terminé ce fichier JPEG, puis nous avons essentiellement un montant indéterminé. Les fichiers JPEG ne finira jamais. Donc, nous voulons nous assurer que lorsque nous lisons dans un fichier JPEG et d'écriture qui, on veut précisément près que, pour ouvrir le suivant. Nous voulons vérifier plusieurs choses. Nous voulons vérifier si nous sommes au début d'un nouveau JPEG avec notre tampon et même si nous avons déjà trouvé un JPEG avant d' parce que cela va changer votre processus légèrement. Alors une fois que vous passer par tout le chemin et vous frappez la fin du fichier, alors qu'est-ce que vous voulez faire, c'est que vous aurez envie de fermer tous les fichiers qui sont actuellement ouverts. Ce sera probablement le dernier fichier JPEG que vous avez, ainsi que le fichier de la carte que vous avez fait affaire. Le dernier obstacle que nous devons résoudre est comment faire réellement un fichier JPEG et comment fait pousser dans le dossier. Le pset exige que tous les JPEG que vous trouverez soit dans le format suivant, où vous avez le numéro. jpg. Le nombre, même si c'est 0, on appelle cela 000.jpg. Lorsque vous trouvez un fichier JPEG dans votre programme, vous allez avoir à le nommer dans l'ordre dans lequel il se trouve. Qu'est-ce que cela signifie? Nous devons sorte de garder la trace de combien nous en avons trouvé et que le nombre de chacun JPEG devrait être. Ici, nous allons profiter de la fonction sprintf. Similaire à printf, qui vient de genre d'impressions sur une valeur dans le terminal, sprintf imprime le fichier sur dans le dossier. Et qu'est-ce que cela ferait si j'avais sprintf, le titre, puis la chaîne de là, il imprimer 2.jpg. En supposant que j'ai fermé mes fichiers correctement, qui contient le fichier que j'avais écrit sur. Mais une chose est que le code que j'ai ici n'est pas tout à satisfaire ce qui nécessite le pset. Le pset nécessite que le second fichier JPEG devrait être nommé 002 au lieu de seulement 2. Ainsi, lorsque vous imprimez le nom, alors peut-être que vous voudrez peut-être modifier légèrement l'espace réservé. Est-ce que quelqu'un se souvient de la façon dont nous permettent espaces supplémentaires lorsque nous imprimons quelque chose? Ouais. >> [L'élève] Tu mets un 3 entre le signe pour cent et le 2. >> Ouais, parfait. Vous mettrez un 3 dans ce cas parce que nous voulons l'espace pour 3. 3d% serait probablement vous donner 002.jpg lieu de 2. Le premier argument dans la fonction sprintf est en fait un tableau de caractères, que nous avons précédemment connu en tant que chaînes. Ceux volonté, un peu plus comme un stockage temporaire, simplement stocker la chaîne résultante. Vous ne serez pas vraiment avoir affaire à cela, mais vous avez besoin de l'inclure. Sachant que chaque nom de fichier comporte le nombre, qui occupe trois caractères, puis. jpg, combien de temps devrait être ce tableau? Jetez un certain nombre. Combien de caractères dans le titre, dans le nom? Donc, il ya 3 hashtags, période, jpg. >> [L'élève] 7. >> 7. Pas tout à fait. Nous allons vouloir 8 parce que nous voulons pour permettre la terminaison nulle aussi. Enfin, il suffit de tirer sur le processus que vous allez faire pour les récupérer, vous avez des informations commencement. Vous continuez jusqu'à ce que vous trouver le début d'un fichier JPEG, et qui peut être soit une des deux séquences de départ. Vous continuez à lire. Chaque barre représente ici 512 octets. Vous continuez à lire, continuez à lire jusqu'à ce que vous rencontrez une autre séquence de démarrage. Une fois que vous avez cela, vous mettez fin à l'actuel JPEG - dans ce cas, c'est le rouge, si vous souhaitez mettre fin à cela. Vous voulez sprintf le nom de ce dossier dans votre pset4, alors vous voulez ouvrir une nouvelle JPEG, puis continuez à lire jusqu'à ce que vous rencontrez l'autre. Continuez à lire, continuez votre lecture, et enfin, par la suite, vous allez arriver à la fin du fichier, et si vous voulez fermer la dernière JPEG que vous travaillez avec, sprintf que dans votre dossier pset4, puis regarder toutes les photos que vous avez reçu. Ces images sont en fait des photos de CS50 personnel, et c'est donc là que la partie la plus amusante de bonus du jeu de processeurs vient en c'est que vous êtes en compétition dans vos sections pour trouver les facteurs de transcription dans les images et prendre des photos avec eux de prouver que vous avez fait le pset et afin que vous puissiez voir quels membres du personnel sont dans les images. Alors vous prenez des photos avec le personnel. Parfois, vous aurez à les pourchasser. Probablement certains d'entre eux va essayer de s'enfuir de chez vous. Vous prenez des photos avec eux. Ceci est en cours. Ce n'est pas exigible lorsque le pset est due. La date limite seront annoncés dans les spécifications. Puis, avec votre section, la section qui prend le plus de photos avec les membres du personnel la plupart gagneront un prix assez impressionnant. C'est le genre d'incitation pour obtenir votre pset4 fini aussi vite que possible car alors vous pouvez passer aux choses sérieuses traquer tous les CS50 différents membres du personnel. Ce n'est pas obligatoire, mais, une fois que vous obtenez les photos, alors vous avez terminé avec pset4. Et j'en aurai fini avec Walkthrough 4, alors je vous remercie tous d'être venus. Bonne chance avec Forensics. [Applaudissements] [CS50.TV]