[Powered by Google Translate] [Walkthrough - Probleem Set 4] [Zamyla Chan - Harvard University] [Dit is CS50. - CS50.TV] Oke. Hallo, iedereen, en welkom bij Walkthrough 4. Vandaag is onze PSET is Forensics. Forensics is echt een leuke PSET die inhoudt dat het omgaan met bitmap-bestanden om te ontdekken wie een misdrijf. Dan gaan we een aantal bitmap bestanden vergroten of verkleinen, dan kunnen we gaan ook te maken met een echt leuke deel genaamd Recover, waarin we in feite gaf een geheugenkaart waarin iemand heeft per ongeluk verwijderde al hun bestanden, en we zijn gevraagd om de bestanden te herstellen. Maar eerst, voordat we in de PSET, ik wil gewoon iedereen feliciteren. We staan ​​op het punt in het midden van deze cursus. Quiz 0 is achter ons, en we zijn op pset4, dus in wezen, we zijn halverwege. We hebben een lange weg afgelegd als je kijkt terug naar je psets, pset0 en pset1, dus feliciteer jezelf over, en we gaan krijgen in een aantal echt leuke dingen. Dus onze toolbox voor deze PSET, opnieuw, in plaats van het runnen van sudo yum-y update, we in staat om alleen nog maar update50 als je op versie 17.3 en hoger van het apparaat. Dus zorg ervoor dat update50 lopen - het is een stuk makkelijker, een paar minder tekens - om ervoor te zorgen dat je op de laatste versie van het apparaat. Vooral is het belangrijk om update50 wanneer we beginnen met CS50 Check. Dus zorg ervoor dat je dat doet. Voor alle secties van deze PSET, we gaan te maken hebben met file-en uitgangen, file I / O. We gaan te gaan over een heleboel programma's die omgaan met arrays verwijzen naar bestanden en dat soort dingen, dus we willen ervoor zorgen dat we echt vertrouwd en comfortabel het omgaan met hoe je input en output naar bestanden. In de verdeelsleutel voor deze PSET is een bestand met de naam copy.c, en dat is wat we gaan vinden zal zijn echt nuttig voor ons want we gaan om uiteindelijk daadwerkelijk het kopiëren van het bestand copy.c en net het iets wijzigen kunnen de eerste twee delen van het probleem te verwezenlijken. En zo dan als ik al zei, hebben we te maken met bitmaps als JPEG-bestanden. Dus echt begrijpen van de structuur van hoe deze bestanden worden georganiseerd, hoe kunnen we echt vertalen 0s en 1s in structs en de dingen die we eigenlijk kunnen begrijpen en interpreteren en bewerken, dat zal echt belangrijk, dus in te gaan op JPEG-en bitmap-bestanden en het begrijpen van de structuur van deze. Pset4 zoals gebruikelijk start met een vragen. Die zal zich bezighouden met file I / O en krijg je gewend aan dat. Dan deel 1 is Whodunit, waarin u een bitmap-bestand gegeven dat ziet er een soort rode stippen allemaal voorbij. En dan eigenlijk wat we gaan doen is dit bestand en net iets te bewerken in een versie die we kunnen lezen. In wezen, als we eenmaal klaar, zullen we hetzelfde bestand hebben, tenzij wij u in staat om de verborgen boodschap verborgen door al die rode stippen te zien. Dan Resize is een programma dat, gegeven een bestand en dan de naam van het bestand dat het systeem voert en daarna voorzien van een nummer en, zal dat bitmap eigenlijk verkleinen door die geheel getal. Dan tot slot, hebben we de Recover PSET. We krijgen een geheugenkaart en vervolgens moeten alle foto's terug te die per ongeluk zijn verwijderd, maar, zoals we leren, niet echt verwijderd en verwijderd uit het bestand; we gewoon een soort van verloren, waar ze in het bestand, maar we gaan dat herstellen. Geweldig. Dus ga in het dossier van I / O-specifiek, dit zijn een hele lijst van functies die je zult gebruiken. Je hebt al gezien een beetje de basis van fopen, fread, en fwrite, maar we gaan verder kijken naar een aantal file I / O-functies zoals fputc, waarin je gewoon schrijven een teken per keer, naar fseek, waar u soort verplaatst u de positie-indicator voor-en achteruit, en nog wat anderen. Maar we zullen gaan in dat een beetje later tijdens de PSET. Dus eerst, om gewoon in het dossier van I / O voordat we ingaan op de PSET, om een ​​bestand te openen, bijvoorbeeld, is wat je moet doen in feite zet je een verwijzing naar dat bestand. Dus hebben we een FILE * pointer. In dit geval, ik noemde het een in pointer, want dat gaat worden mijn infile. En dus ga ik om de functie fopen en vervolgens de naam van het bestand te gebruiken en dan de modus waarin ik ga te maken hebben met het bestand. Dus er is "r" in dit geval voor het lezen, "w" voor het schrijven, en vervolgens "a" voor het toevoegen. Bijvoorbeeld, wanneer je te maken hebt met een infile en alles wat je wilt doen is lezen de bits en bytes daar opgeslagen, dan ben je waarschijnlijk gaat te willen "r" als je wilt gebruiken. Als u wilt eigenlijk schrijven, soort van een nieuw bestand, dan wat we gaan doen is gaan we het nieuwe bestand te openen en gebruik de "w"-modus voor het schrijven. Dus toen je eigenlijk aan het lezen bent in de bestanden, de structuur is als volgt. Eerst moet je ook de pointer naar de struct dat bevat de bytes die je aan het lezen bent. Dus dat gaat de eindlocatie van de bytes die u nu leest zijn. Je gaat dan naar de grootte aan te geven, zoals in principe hoeveel bytes uw programma moet in lezen naar het bestand, de grootte in principe een element is, en dan zul je om aan te geven hoeveel elementen u wilt lezen. En dan tot slot, moet je weten waar je het lezen van, zodat dat gaat je in aanwijzer te zijn. Ik kleurcode deze omdat fread is ook zeer vergelijkbaar met fwrite, behalve dat u wilt ervoor zorgen dat u de juiste volgorde te gebruiken, Zorg ervoor dat je eigenlijk aan het schrijven bent naar of het lezen van het juiste bestand. Kortom, zoals voorheen, als we de grootte van het element en het aantal elementen, dan kunnen we hier spelen een beetje rond. Zeggen dat ik een hond struct en dus dan wil ik twee honden tegelijk lezen. Wat ik zou doen is de grootte van een element te zeggen gaat om de grootte van een hond te zijn en ik ga om daadwerkelijk te lezen twee van hen. Als alternatief is wat ik kon doen zeg ik ga gewoon een element lezen en dat ene element zal de grootte van twee honden. Dus dat is analoog hoe je kan soort van zaken rond met de grootte en het aantal afhankelijk van wat meer intuïtief aan u. Oke. Dus nu komen we bij het schrijven van bestanden. Wanneer u een bestand wilt schrijven, het eerste argument is eigenlijk waar je het lezen van. Dus dat is eigenlijk de gegevens die u gaat schrijven in het bestand, die de aanwijsstok eind. Dus als je te maken hebt met de PSET, zorg ervoor dat je niet in de war raken. Misschien de definities naast elkaar. U kunt trekken de definities in de handleiding door man en dan fwrite, bijvoorbeeld, in de terminal, of u kunt terug te verwijzen naar deze dia en zorg ervoor dat je de juiste gebruikt. Dus nogmaals, voor fwrite, wanneer u een bestand hebt dat u wilt schrijven in, dat gaat de laatste argument te zijn en dat gaat met een pointer naar dat bestand te zijn. Dus dan is dat de manier waarop we omgaan met het schrijven van misschien wel enkele bytes in een tijd, maar zeggen dat je gewoon wilt schrijven in slechts een enkel karakter. Zoals we later zullen zien in dit voorbeeld, in de bitmaps we moeten dat gebruiken. Dat is wanneer we kunnen gebruiken fputc wezen zomaar een teken per keer, chr, in de file-pointer, en dat is onze aanwijsstok daar. Dus dan wanneer we vragen of schrijven in een bestand, het bestand is het bijhouden van waar we zijn. Dus het is een soort van de cursor, de positie-indicator. En dus wanneer we schrijven of lezen weer in een bestand, het bestand daadwerkelijk onthoudt wanneer het, en zo verder waar de cursor. Dit kan nuttig zijn wanneer u wilt, zeg, gelezen in een bepaald bedrag om iets te doen en dan lezen in de volgende hoeveelheid, maar soms kunnen we terug willen of daadwerkelijk te gaan van een bepaalde referentiewaarde te starten. Dus dan is de fseek functie, wat het doet is het ons in staat stelt om de cursor in een bepaald bestand een aantal bytes. En dan wat we moeten doen, is bepalen waar de referentiewaarde is. Dus of het beweegt vooruit of achteruit vanaf waar de cursor momenteel, of we kunnen aangeven dat het gewoon zou moeten in gaan vanaf het begin van het bestand of vanaf het einde van het bestand. En zodat je kan passeren in negatieve of positieve waarden bedrag, en dat zal soort verplaatst u de cursor naar voren of naar achteren. Voordat we in de andere psets, vragen over file I / O? Oke. Als we in meer voorbeelden, voel je vrij om me te stoppen voor vragen. Dus in Whodunit, je gaf een bitmap-bestand vergelijkbaar met deze rode op de dia, en het ziet er zo uit - een bos van rode stippen - en je niet echt weet wat er geschreven. Als je scheel, kunt u in staat om een ​​lichte blauwachtige kleur in het midden te zien. In essentie, dat is waar de tekst wordt opgeslagen. Er was een moord die gebeurde, en we moeten om uit te vinden wie het gedaan heeft. Om dat te doen, moeten we soort van om te zetten dit beeld in een leesbaar formaat. Als jullie ooit ontmoet dit, soms zou er weinig kits waar zou je een vergrootglas met een rode folie. Iedereen? Ja. Dus je zou handen iets als dit, zou je een vergrootglas met de rode film over, zou je het over de afbeelding, en je zou in staat zijn om het bericht daarin verborgen. We hebben geen een vergrootglas met rode film, dus in plaats daarvan gaan we soort van onze eigen in deze PSET. En zodat de gebruiker gaat om input detectiveverhaal, dan is de aanwijzing,. Bmp, dus dat is de infile, dat is de rode stip bericht, en dan ze zeggen verdict.bmp gaat onze outfile zijn. Dus het gaat om een ​​nieuwe bitmapafbeelding vergelijkbaar met de aanwijzing een te maken behalve in een leesbaar formaat, waar we kunnen zien de verborgen boodschap. Omdat we gaan te maken hebben met het bewerken en manipuleren van bitmaps van een soort, we gaan voor soort duik in in de structuur van deze bitmap bestanden. We gingen op deze een beetje in college, maar laten we eens kijken naar hen wat meer. Bitmaps zijn in wezen slechts een arrangement van bytes waar we aangegeven welke bytes betekenen wat. Dus hier is een soort een kaart van de bitmapafbeelding te zeggen dat het begint met een aantal header files, begint met wat informatie in. Je ziet dat op ongeveer byte nummer 14 van de grootte wordt aangegeven van de bitmapafbeelding, en het blijft maar door. Maar dan wat we echt geïnteresseerd in hier begint rond byte nummer 54. We hebben deze RGB triples. Wat dat gaat doen, is bevat de eigenlijke pixels, de kleurwaarden. Alles wat boven die in de header is wat informatie overeenkomt met de grootte van het beeld, de breedte van het beeld en de hoogte. Als we gaan later in padding op, we zien waarom de grootte van het beeld kan anders zijn dan de breedte of de hoogte. Dus dan naar deze vertegenwoordigen - deze bitmapafbeeldingen zijn sequenties van bytes - wat we kunnen doen is zeggen: oke, ik ga om te onthouden dat op index 14, dat is waar de grootte is, bijvoorbeeld, maar in plaats daarvan wat we gaan doen om dit gemakkelijker te maken is ingekapseld in een struct. En dus hebben we twee structs voor ons gemaakt, een BITMAPFILEHEADER en een BITMAPINFOHEADER, en dus wanneer we lezen in dat bestand, standaard het zal gaan in orde zijn, en dus met het oog het is ook gaat in te vullen in variabelen zoals biWidth en biSize. En tenslotte, wordt elke pixel vertegenwoordigd door drie bytes. De eerste is de hoeveelheid blauw in de pixel, de tweede is de hoeveelheid groen, en tenslotte de hoeveelheid rood, waarbij 0 wezen geen blauw of groen geen of geen rood en dan ff is de maximale waarde. Dit zijn hexadecimale waarden. Dus dan als we ff0000 dan die overeenkomt met de maximum hoeveelheid blauw en dan geen groen en geen rood, dus dan zou dat ons een blauwe pixel. Dan als we ff's over de hele linie, dan betekent dat dat we een witte pixel te hebben. Dit is een soort tegenovergestelde meestal als we zeggen RGB. Het is eigenlijk aan de hand BGR. Dus als we echt kijken naar een voorbeeld van een bitmapafbeelding - laat me trek een hier boven. Het is een beetje klein. Ik ben in te zoomen, en we kunnen zien dat het korrelig. Het lijkt erop dat blokken van kleur. Je hebt witte blokken en dan rode blokken. Als je speelt in Microsoft Paint, bijvoorbeeld, kon je zoiets door eigenlijk gewoon schilderen bepaalde pleinen in een bepaalde volgorde. Dus wat resulteert dit in de bitmap is als volgt. Hier hebben we eerste witte pixels, dat alle 6 zijn f, en dan hebben we rode pixels, aangegeven 0000FF. En dus is de volgorde van de bytes die we hebben geeft aan hoe de bitmapafbeelding eruit komt te zien. Dus wat ik hier heb gedaan is gewoon uitgeschreven al die bytes en vervolgens gekleurd in het rood zodat u kunt soort te zien, als je scheel een beetje, hoe dat soort van een smiley aangeeft. De manier waarop bitmapafbeeldingen werk is dat ik voor ogen het in feite als een raster. En dus standaard, elke rij van het raster moet een veelvoud van 4 bytes. Als we kijken naar een bitmapafbeelding, je bent het invullen van elke waarde. Bijvoorbeeld, zou je hier een rode, een groene hier, een blauwe hier, maar je moet ervoor zorgen dat het beeld wordt gevuld met een veelvoud van vier bytes. Dus als ik wil dat mijn beeld wel drie blokken breed, dan zou ik naar een lege waarde toe te in de laatste om er een veelvoud van vier. Dus dan zou ik toevoegen in iets wat we noemen padding. Ik ga gewoon om aan te geven dat er met een x. Nu zeggen dat we willen een beeld dat is 7 pixels lang, bijvoorbeeld. Wij hebben 1, 2, 3, 4, 5, 6, 7, en dat alles wordt ingevuld met kleur. De manier waarop bitmap-afbeeldingen te werken is dat we een 8e nodig hebben. Nu hebben we 1, 2, 3, 4, 5, 6, 7. We hebben 8 ruimten voor de bitmapafbeelding om volledig te kunnen lezen. Dus wat we moeten doen is toe te voegen in slechts een beetje padding ervoor zorgen dat alle breedtes uniformiteit en dat alle breedten een veelvoud van 4. En dus heb ik eerder aangegeven, padden als een x of een kronkelende lijn, maar in de feitelijke bitmapafbeeldingen de vulling wordt door een hexadecimale 0. Dus dat zou een enkel karakter, 0 zijn. Wat zou van pas komen is de XXD commando. Wat het doet is eigenlijk laat zien, zoals vergelijkbaar met wat ik gedaan heb voordat met de smiley toen ik eigenlijk uitgeprint wat elke kleur zou zijn voor de pixel en dan een kleurcode het, wanneer u XXD met de volgende commando's, dan is het ook daadwerkelijk uit te printen wat de kleuren zijn voor diegenen pixels. Wat u moet doen is hier geef ik aan, net als de-s 54 zegt dat ik ga beginnen bij de 54e byte want voor dat herinneren als we terugkijken naar de kaart van de bitmaps, dat is alles wat de header-informatie en dat soort dingen. Maar wat we echt zorgen over de feitelijke pixels dat de kleur aan te geven. Dus door het toevoegen van die vlag,-s 54, dan zijn we in staat om de kleurwaarden te zien. En maak je geen zorgen over de ingewikkelde vlaggen en dat soort dingen. In het probleem set spec, dan moet je aanwijzingen over hoe te gebruiken XXD om de pixels weer te geven. Dus als je hier ziet, is het soort van ziet eruit als een groen vierkant, dit kleine ding. Ik heb een kleurcodering de 00FF00 als eigenlijk zeggen geen blauwe, veel groen, en geen rode. Zodat die overeenkomt met groen. Zoals je hier ziet, zien we een groene rechthoek. Deze groene rechthoek ligt op slechts 3 pixels breed, dus dan wat we moeten doen om ervoor te zorgen dat het beeld een veelvoud van 4 breed is toe te voegen in extra vulling. En dus dan is dat hoe je deze 0s hier te zien. Dit ook daadwerkelijk het gevolg zijn van uw Resize PSET, in wezen het nemen van de kleine bitmap en dan vergroten door 4. Wat we dus zien is dat eigenlijk deze afbeelding is 12 pixels breed, maar 12 is een veelvoud van 4, en dus hebben we eigenlijk niet zie geen 0s aan het eind omdat we geen behoefte aan een toe te voegen want het is volledig opgevuld. Het heeft geen meer ruimte. Oke. Heeft u vragen over padding? Oke. Cool. Zoals ik al zei, de bitmaps zijn slechts een sequentie van bytes. En dus wat we hebben is in plaats van om het bijhouden van precies welke aantal byte komt overeen met een specifiek element, we eigenlijk hebben een struct die vertegenwoordigen. Dus wat we hebben is een RGBTRIPLE struct. Wanneer u een exemplaar van een RGB-triple hebben, want dit is een type te definiëren struct, dan kunt u toegang krijgen tot de rgbtBlue variabele, eveneens de groene en rode variabelen, die aangeeft hoeveel blauw, groen, en rood, respectievelijk je hebt. Dus als we de blauwe variabele ingesteld op 0, de groene set om ff, Dit is de maximale waarde die u kan hebben, en daarna de rode variabele ingesteld op 0, dan welke kleur zou deze bijzondere RGB drievoudige vertegenwoordigen? >> [Student] Green. Green. Precies. Het zal nuttig zijn om te weten dat wanneer u een exemplaar van een RGB-triple hebben, kun je eigenlijk toegang tot de hoeveelheid kleur - blauw, groen en rood - afzonderlijk. Nu we hebben gesproken over de structuur van dat, laten we een kijkje nemen op het BMP-bestand. Dit zijn structs voor u gemaakt. Hier hebben we een BITMAPFILEHEADER struct. Van belang is de grootte. Later hebben we de info-header, die een paar dingen die interessant zijn heeft voor ons, namelijk de grootte, de breedte en de hoogte. Als we gaan naar later, als je leest in het bestand, het leest automatisch in omdat we de volgorde hetzelfde te zijn. Dus de biSize bevat de juiste bytes die overeenkomen met de werkelijke grootte van de afbeelding. En dan hier, ten slotte, zoals we hebben het gehad over, wij hebben de RGBTRIPLE typedef struct. We hebben een rgbtBlue, Groen en Rood ermee verbonden zijn. Geweldig. Oke. Nu we begrijpen bitmaps een beetje begrijpen dat we een bestand header hebben en een info-header die ermee verbonden zijn en dan na dat, hebben we de interessante dingen van de kleuren en deze kleuren worden vertegenwoordigd door RGBTRIPLE structs, en die op hun beurt zijn drie waarden geassocieerd met de blauwe, groene en rode. Dus nu kunnen we soort van denken over het herstellen van een beetje. Sorry. Denk na over Whodunit. Wanneer we onze idee-bestand hebben, dan wat we willen doen, is te lezen in het pixel voor pixel en dan een of andere manier te veranderen die pixels, zodat we het kunnen uitvoeren in een leesbaar formaat. En dus om het uit te voeren, gaan we pixel schrijven voor pixel in de verdict.bmp bestand. Dat is een soort van een veel te doen. We realiseren ons dat. Dus wat we hebben gedaan is dat we je eigenlijk voorzien copy.c. Wat copy.c doet is gewoon een exacte kopie van een bepaalde bitmap-bestand dan en voert deze uit. Dus dit opent al het bestand voor u, leest in pixel voor pixel, en schrijft het vervolgens in in een output-bestand. Laten we eens een kijkje nemen op die. Dit is ervoor te zorgen correct gebruik, het verkrijgen van de bestandsnamen hier. Wat dit doet is het zet de input-file om te zijn wat we hebben doorgegeven in hier in de infile, dat is onze tweede command-line argument. Controles om ervoor te zorgen dat we het bestand te openen. Controles om ervoor te zorgen dat we een nieuwe outfile hier te maken. Maar wat dit hier doet, het alleen maar in principe begint te lezen in het bitmap-bestand vanaf het begin. Het begin, zoals we weten, bevat de BITMAPFILEHEADER, en dus die sequenties van bits direct invullen van de BITMAPFILEHEADER. Dus wat we hier hebben is te zeggen dat BITMAPFILEHEADER bf - dat is onze nieuwe variabele van het type BITMAPFILEHEADER - we gaan zetten binnen bf wat we lezen in pointer, dat is onze infile. Hoeveel hebben we gelezen? We lezen in hoeveel bytes moeten we de hele BITMAPFILEHEADER bevatten. Ook dat is wat we doen voor de info header. Dus we verder langs ons dossier in de infile, en we zijn het lezen van deze bits en bytes, en we sluiten ze direct in in deze gevallen van de variabelen die we maken. Hier zijn we gewoon ervoor te zorgen dat de bitmap is een bitmap. Nu hebben we een outfile, toch? Dus zoals het nu is als we creëren, het is in wezen leeg. Dus moeten we eigenlijk een nieuwe bitmap vanaf nul. Wat wij doen is moeten we ervoor zorgen dat we kopiëren in de header en de info header net als de infile heeft. Wat wij doen is schrijven we - en vergeet niet dat bf is de variabele van het type BITMAPFILEHEADER, dus wat we doen is dat we gewoon gebruik maken van die inhoud te schrijven in de outfile. Hier herinneren we gesproken over padding, hoe belangrijk het is ervoor te zorgen dat het aantal pixels dat we een veelvoud van 4. Dit is een vrij nuttige formule om te berekenen hoeveel vulling je hebt gelet op de breedte van uw dossier. Ik wil dat jullie te onthouden dat in copy.c we een formule voor het berekenen van padding hebben. Oke? Dus iedereen onthouden. Geweldig. Dus wat doet copy.c volgende is het doorloopt alle scanlines. Het gaat door de rijen en vervolgens opgeslagen om triple die ze leest en schrijft het in de outfile. Dus dan hier zijn we aan het lezen bent slechts een RGB-triple in een tijd en dan zetten diezelfde triple in de outfile. Het lastige deel is dat de vulling niet een RGB triple, en dus kunnen we niet gewoon lezen dat padding hoeveelheid RGB triples. Wat we moeten doen is eigenlijk alleen maar bewegen ons positie-indicator, bewegen onze cursor, van de soort over te slaan alle padding, zodat we op de volgende rij. En wat dit doet is copy laat je zien hoe je zou willen om de vulling toe te voegen. Dus hebben we berekend hoeveel padding we nodig hebben, dus dat betekent dat we padding aantal 0s nodig hebben. Wat dit doet is een lus die padding aantal 0s zet in onze outfile. En dan tot slot, sluit u beide bestanden. U sluit de infile evenals de outfile. Dus dat is hoe copy.c werkt, en dat gaat behoorlijk nuttig. In plaats van alleen eigenlijk direct kopiëren en plakken of gewoon naar te kijken en te typen in wat je wilt, je kan gewoon wilt dit commando uit te voeren in de terminal, cp copy.c whodunit.c, die een nieuw bestand te maken, whodunit.c, dat bevat exact dezelfde inhoud als kopie doet. Dus dan wat we kunnen doen is gebruik dat als een raamwerk waarop te bouwen en te bewerken voor onze whodunit-bestand. Dit zijn onze to-do's te doen voor Whodunit, maar wat copy.c doet daadwerkelijk verzorgt meeste voor ons. Dus alles wat we moeten gaan doen is verandering de pixels als dat nodig is om daadwerkelijk het bestand leesbaar. Bedenk dat voor een gegeven pixel triple, zodat voor een gegeven variabele van het type RGBTRIPLE, hebt u toegang tot de blauwe, groene en rode waarden. Dat zal van pas komen, want als je er toegang toe, dat betekent dat u ook controleren ze, en dat betekent dat u ook wijzigen. Dus toen we gingen terug naar onze rode vergrootglas bijvoorbeeld, in feite, werd dat als een soort filter voor ons. Dus wat we willen doen is dat we willen alle triples die komende inch filteren Er zijn verschillende manieren om dit te doen. In principe kunt u ongeacht het type filter dat u wilt. Misschien wilt u alle rode pixels wijzigen of misschien wilt u een andere kleur pixel te wijzigen in een andere kleur. Dat is aan jou. Vergeet niet dat u kunt controleren welke kleur de pixel en dan kun je ook veranderen als je doormaakt. Oke. Dus dat is Whodunit. Zodra u Whodunit loopt, zul je weten wie de dader van de misdaad was. Nu gaan we naar Formaat wijzigen. We gaan nog steeds te maken hebben met bitmaps. Wat we gaan doen is gaan we een ingang bitmap hebben en dan gaan we pas in een getal en vervolgens een outfile bitmap te krijgen waar dat is eigenlijk onze infile geschaald door n. Zeg mijn dossier was slechts een pixel groot. Dan, als mijn n was 3, schalen met 3, dan zou ik herhalen dat pixel n aantal keren, dus 3 keer, en dan ook schalen naar beneden 3 keer ook. Zo zie je maar dat ik het opschalen zowel verticaal als horizontaal. En dan is hier een voorbeeld. Als je n = 2, zie je dat de eerste blauwe pixel er twee keer herhaald zowel horizontaal als twee keer verticaal. En dan is dat verder op, en dus heb je een directe schaalvergroting van de oorspronkelijke afbeelding door twee. Dus dan als we voor het detail van de pseudocode voor deze willen we het bestand te openen. En dan te weten dat als we terug te gaan hier, zien we dat de breedte voor de outfile gaat om anders te zijn dan de breedte van de infile. Wat betekent dat? Dat betekent dat onze header informatie gaat veranderen. En dus wat we willen doen is het actualiseren van de header info, wetende dat wanneer we lezen in de bestanden als je die op de copy.c kader, hebben we al een variabele die aangeeft wat de omvang is en dat soort dingen. Dus zodra je dat hebt, wat je zou willen doen is die bepaalde variabelen. Vergeet niet, als je een struct, hoe je de variabelen binnen die te openen. U gebruikt de puntoperator, toch? Dus dan met behulp van dat, je weet dat je nodig hebt om de header info te veranderen. Dus hier is gewoon een lijst van de feitelijke elementen die zullen worden veranderen in uw bestand. Het bestand zal worden veranderen, het beeld, en de breedte en hoogte. Dus dan terug te gaan naar de kaart van de bitmaps, kijken of het nu de bestandsheader of de info header die deze informatie bevat en dan veranderen als dat nodig is. Nogmaals, laten we zeggen cp copy.c resize.c. Dat betekent dat resize.c nu alles wat er die binnen kopie bevat omdat kopie geeft ons een manier van het lezen in elk scanline pixel per pixel. Behalve nu, in plaats van alleen het veranderen van de waarden zoals wij deden in Whodunit, wat we willen doen is dat we willen om te schrijven in meerdere pixels zolang de n groter is dan 1. Dan wat we willen doen is dat we willen horizontaal uitrekken door n, als verticaal rekken door n. Hoe kunnen we dat doen? Zeg uw n 2 is en je dit gegeven infile. Uw cursor zal om te beginnen op de eerste, en wat je wilt doen als n 2, die u wilt afdrukken in 2 van die. Dus u afdrukt in 2 van die. Vervolgens de cursor gaat naar het volgende pixel, die de rode, en het gaat om uit te printen 2 van die rode, gehecht worden op wat het eerder gedaan. Dan is de cursor gaat naar de volgende pixel en trekken in 2 van die. Als je kijkt naar de copy.c kader, wat dit doet hier wordt het creëert een nieuwe instantie van een RGB-triple, een nieuwe variabele genaamd triple. En hier als het leest in het, het leest van de infile 1 RGBTRIPLE en slaat deze binnenkant van die triple variabele. Dus dan moet je eigenlijk een variabele die die bepaalde pixel. Dan wanneer je schrijft, wat je zou willen doen is omsluiten de fwrite verklaring in een lus dat schrijft deze in je outfile zo vaak als nodig. Dat is eenvoudig genoeg. Alleen maar in principe herhaal het schrijfproces n aantal keren om horizontaal te schalen. Maar dan moeten we niet vergeten dat onze padding gaat veranderen. Voorheen zeggen dat we hadden iets van lengte 3. Dan zouden we gewoon toevoegen in hoeveel padding? Nog een om er een veelvoud van 4. Maar zeggen dat we dit bijzondere beeld schaalvergroting door n = 2. Dus dan hoeveel blauwe pixels zouden we aan het eind? We zouden 6. 1, 2, 3, 4, 5, 6. Oke. 6 is geen veelvoud van 4. Wat is het dichtstbijzijnde veelvoud van 4? Dat komt wel 8. Dus we zijn eigenlijk gaat om daar te hebben 2 karakters van padding. Heeft iemand herinner me als we een formule om te berekenen padding en waar dat zal zijn? [Onverstaanbaar student reactie] >> Ja, copy.c. Juist. Er is een formule in copy.c om te berekenen hoeveel vulling je hebt gegeven een bepaalde breedte van de bitmapafbeelding. Dus dan dat gaat handig zijn als je nodig hebt om toe te voegen in een zekere mate van vulling om daadwerkelijk uit te vinden hoeveel padding je nodig hebt om toe te voegen. Maar een noot is echter dat u wilt ervoor zorgen dat u de juiste maat gebruikt. Wees voorzichtig, want je bent in principe zal worden te maken met twee bitmapafbeeldingen. U wilt er zeker van zijn dat je de juiste gebruikt. Wanneer u de opvulling berekenen voor de outfile, wil je de breedte van de outfile gebruiken en niet de breedte van de vorige. Geweldig. Dat soort zorgt voor het oprekken van een hele bitmapafbeelding horizontaal. Maar wat we willen doen is eigenlijk uitrekken verticaal als goed. Dit gaat een beetje lastiger, want als we klaar zijn het kopiëren van een rij en het schrijven van die rij, is onze cursor gaat worden aan het eind. Dus als we lezen weer, dan is het gewoon om in te lezen naar de volgende regel. Dus wat we willen doen is een soort van een manier vinden van het kopiëren van die rijen weer of gewoon een soort van het nemen van die rij en dan herschrijven het weer. Zoals ik soort van gezinspeeld, zijn er verschillende manieren om dit te doen. Wat je zou kunnen doen is als je gaat door en het lezen van de bijzondere scanline en veranderen indien nodig, dan soort winkel al die pixels in een array. Later op weet je dat je nodig hebt om uit te printen die array weer, en dus kun je gewoon gebruik maken van die array om dat te doen. Een andere manier om het te doen is dat je zou kunnen kopiëren naar beneden een rij, begrijpen dat je nodig hebt om dat opnieuw te kopiëren, dus eigenlijk beweeg je cursor, en dat gaat worden met behulp van de methode fseek. Je kon je cursor weer helemaal en herhaal het kopieerproces. Dus als onze schaalvergroting getal n, dan hoe vaak zouden we om terug te gaan en herschrijven van een lijn? >> [Student] n - 1. >> Ja, perfect. n - 1. We hebben het gedaan al een keer, dus dan zullen we willen het terug te gaan herhalen n - 1 aantal keer. Oke. Dus daar heb je je resize functie. Nu we kunnen krijgen om een ​​echt leuke gedeelte, mijn favoriete PSET, dat is terug. In plaats van bitmaps, deze keer hebben we mee te maken hebben JPEG's. We zijn eigenlijk niet gegeven een bestand alleen van JPEG's, we krijgen in principe een raw formaat geheugenkaart. En dus dit bevat een beetje info en vuilnis waarden in het begin, en dan begint het en het heeft een bos van JPEG-bestanden. Echter, we overhandigde een kaartje waar we verwijderd van de foto's; wezen, hebben we vergeten waar de foto's bevinden zich in de kaart. Dus dan is onze taak in Recover is om te gaan door middel van deze kaart formaat en terug te vinden die foto's. Gelukkig, de structuur van de JPEG-bestanden en de kaart-bestand is een beetje nuttig. Het is zeker had kunnen zijn een beetje lastiger als het niet in dit specifieke formaat. Elke JPEG-bestand begint eigenlijk met twee mogelijke sequenties, hierboven vermeld. Kortom, wanneer je een nieuwe JPEG-bestand, het begint met ofwel de volgorde ffd8 ffe0 of de andere, ffd8 ffe1. Een ander nuttig ding om te weten is dat JPEG's aansluitend worden opgeslagen. Dus wanneer een JPEG bestand eindigt, de andere begint. Er is geen enkele vorm van in-tussen waarden zijn. Zodra je de start van een JPEG, als je al het lezen van een JPEG-, je weet dat je het einde van de vorige en het begin van de volgende hit. Om vorm van visualiseren dit, heb ik een schema. Een ander ding over JPEG-bestanden is dat we ze kunnen lezen in sequenties van 512 bytes per keer, Hetzelfde geldt voor de begin van de kaart. We hoeven niet te worden te controleren elke byte want dat zou zuigen. Dus in plaats daarvan wat we kunnen doen is eigenlijk alleen maar in 512 bytes te lezen op een moment en dan, in plaats van de controle tussen die in die piepkleine schijfjes, we kunnen gewoon check het begin van de 512 bytes. In wezen, op deze foto, wat je ziet is in het begin van de kaart, u heeft een waarde die niet echt relevant zijn voor de werkelijke JPEG's zelf. Maar wat ik een ster om een ​​van de twee uitgangsstoffen sequenties voor een JPEG geven. Dus wanneer je een ster ziet, weet u dat u een JPEG-bestand te hebben. En vervolgens om de JPEG-bestand gaat om een ​​aantal veelvoud van 512 bytes worden maar niet noodzakelijkerwijs hetzelfde meerdere. De manier waarop je weet dat je een andere JPEG geraakt is als je op een andere ster, een andere startvolgorde van bytes. Dan wat je hebt hier heb je de rode JPEG-bestand verder tot je een ster, die wordt aangegeven door een nieuwe kleur. U blijft en dan je hit een andere ster, je raakt een andere JPEG, u doorgaat helemaal tot het einde. Je bent op de laatste foto hier, de roze. Je gaat naar het einde tot je het einde van het bestand karakter. Dit gaat echt nuttig. Een paar belangrijke afhaalrestaurants hier: De kaart-bestand begint niet met een JPEG-, maar eenmaal JPEG begint, worden alle JPEG opgeslagen naast elkaar. Sommige pseudocode voor de Recover. Ten eerste, we gaan naar onze kaart bestand te openen, en dat gaat worden met behulp van onze file I / O-functies. We gaan het volgende proces herhalen totdat we aan het einde van het bestand. We gaan 512 bytes per keer lezen. En wat ik zei hier gaan we het op te slaan in een buffer, dus in principe vast te houden aan die 512 bytes tot we precies weten wat te doen met hen. Dan wat we willen doen is dat we willen nagaan of we hebben een ster of niet geraakt. Als we raakte een ster, als we geraakt een van de uitgangspunten sequenties, dan weten we dat we een nieuw JPEG-bestand te raken. Wat we willen doen is gaan we willen een nieuw bestand in onze pset4 map aan te maken te blijven maken dat bestand. Maar ook als we hebben al een JPEG-voor, dan willen we dat bestand te beëindigen en te duwen om de pset4 map, waar we hebben dat bestand opgeslagen, want als we niet aangeven dat we dat JPEG-bestand eindigde, dan zullen we in principe een onbepaalde hoeveelheid. De JPEG's zal nooit eindigen. Dus we willen er zeker van dat als we het lezen in een JPEG-bestand is en dat het schrijven, we willen eens sluiten dat om de volgende te openen. We willen verschillende dingen te controleren. We willen nagaan of we aan het begin van een nieuw JPEG met onze buffer en ook als we al hebben gevonden een JPEG voordat want dat zal je proces een beetje. Dan, nadat je door de hele weg en je raakt het einde van het bestand, dan wat je wilt doen is je wilt alle bestanden die momenteel zijn geopend sluiten. Dat is waarschijnlijk de laatste zal zijn JPEG-bestand dat je hebt, alsook de kaart bestand dat u hebt te maken met. De laatste hindernis die we moeten aanpakken is hoe om daadwerkelijk een JPEG-bestand en hoe je nu eigenlijk te duwen naar de map. De PSET vereist dat elke JPEG die je kunt vinden in het volgende formaat, waar u het nummer. jpg. Het aantal, ook al is het 0, noemen we het 000.jpg. Wanneer u een JPEG in uw programma, je gaat te willen om het te noemen in de volgorde waarin het is gevonden. Wat betekent dit? We moeten dergelijke bijhouden hoeveel we hebben gevonden en wat het nummer van elke JPEG moet. Hier gaan we om te profiteren van de sprintf functie. Net als bij printf, die gewoon een soort van prenten een waarde uit in de terminal, sprintf drukt het bestand uit in de map. En dit dus wat zou doen als ik had sprintf, titel, en dan de string daar, het zou uitprinten 2.jpg. Ervan uitgaande dat ik mijn bestanden correct afgesloten, dat zou bevatten het bestand dat ik had geschreven uit. Maar een ding is dat de code die ik hier heb niet helemaal voldoet aan wat de PSET vereist. De PSET vereist dat de tweede JPEG bestand moet de naam 002 in plaats van slechts 2. Dus wanneer u afdrukt uit de naam, dan misschien wilt u misschien de plaatsaanduiding iets te veranderen. Weet iemand nog hoe we zorgen voor extra spaties als we iets af te drukken? Ja. >> [Student] Je zet een 3 tussen het procentteken en de 2. >> Ja, perfect. Je zet een 3 in dit geval, want we willen ruimte voor 3. % 3d zou waarschijnlijk geven u 002.jpg in plaats van 2. Het eerste argument in de sprintf functie is eigenlijk een char array, die we eerder kenden als strings. Die wil, soort van meer als een tijdelijke opslag, maar slaan de resulterende tekenreeks. U zult niet echt te maken hebben met dit, maar je moet het op te nemen. Wetende dat elk bestand de naam van het nummer, dat in beslag neemt drie tekens heeft, en dan. jpg, moet deze array hoe lang zijn? Gooi een nummer. Hoeveel tekens in de titel, in de naam? Dus er is 3 hashtags, periode, jpg. >> [Student] 7. >> 7. Niet helemaal. We gaan tot 8 wilt, want we willen zorgen voor de null-terminator ook. Tot slot, om gewoon trekken uit het proces dat u zult moeten doen voor Recover, je een aantal begin informatie. U blijft totdat u het begin van een JPEG-bestand, en die ofwel een van de twee sequenties beginnen. Je blijft bij het lezen. Elke slash hier vertegenwoordigt 512 bytes. Je blijft op lezen, blijven lezen totdat je tegenkomt een andere startvolgorde. Zodra je dat hebt, je de huidige JPEG eindigen - in dit geval, het is de rode, dus je wilt dat een einde. U wilt sprintf de naam van die in uw pset4 map, dan wil je een nieuwe JPEG te openen en vervolgens op het lezen te houden totdat kom je de volgende. Blijf lezen, blijf lezen, en dan eindelijk, uiteindelijk, je gaat naar het einde van het bestand bereikt, en dus je wilt de laatste JPEG dichtbij dat u werkte, sprintf die in uw pset4 map en kijk dan naar alle van de foto's die je hebt gekregen. Die foto's zijn eigenlijk foto's van CS50 personeel, en dus dit is waar de bonus leuke gedeelte van de PSET komt in is dat je met elkaar concurreren in uw secties om de TFS in de foto's te vinden en foto's nemen met hen om te bewijzen dat u de PSET gedaan en zodat u kunt zien welke medewerkers zijn op de foto's. Dus dan moet je foto's maken met het personeel. Soms moet je ze achterna te zitten. Waarschijnlijk een van hen zal proberen weg te rennen van je. Je neemt foto's met hen. Dit is aan de gang. Het is niet verschuldigd wanneer de PSET is te wijten. De deadline zal worden aangekondigd in de spec. Dan samen met uw afdeling, afhankelijk van welke paragraaf neemt de meeste foto's met de meeste medewerkers wint een pretty awesome prijs. Dat is een soort van stimulans om uw pset4 eindigde zo snel mogelijk want dan kun je aan de slag gaan jacht op alle verschillende CS50 medewerkers. Dat is niet verplicht is, al, dus als je eenmaal de foto's, dan bent u klaar met pset4. En ik ben klaar met Walkthrough 4, dus alle dank u voor uw komst. Veel succes met Forensics. [Applaus] [CS50.TV]