[Powered by Google Translate] [Walkthrough - Problem Set 4] [Zamyla Chan - Harvard University] [Dette er CS50. - CS50.TV] OK. Hei, alle sammen, og velkommen til Walkthrough 4. I dag vårt pset er Forensics. Forensics er en veldig morsom pset som innebærer håndtering av bitmap-filer å oppdage hvem begått en forbrytelse. Så vi kommer til å endre størrelsen noen bitmap-filer, så vi kommer også til å håndtere en veldig morsom del kalt gjenvinning, der vi i utgangspunktet ga et minnekort der noen har et uhell slettet alle sine filer, og vi blir bedt om å gjenopprette filene. Men først, før vi kommer inn i pset, jeg egentlig bare ønsker å gratulere alle. Vi er i ferd med på midtpunktet av dette kurset. Quiz 0 er bak oss, og vi er på pset4, så egentlig er vi halvveis. Vi har kommet en lang vei hvis du ser tilbake til psets, pset0 og pset1, så gratulere deg om det, og vi kommer til å få inn noen virkelig morsomme ting. Så vår verktøykasse for denne pset, igjen, i stedet for å kjøre sudo yum-y-oppdatering, vi er i stand til å bare kjøre update50 hvis du er på versjon 17.3 og nyere av apparatet. Så sørg for å kjøre update50 - det er mye enklere, noen mindre tegn - å sørge for at du er på den nyeste versjonen av apparatet. Spesielt er det viktig å update50 når vi begynner å bruke CS50 Check. Så sørg for at du gjør det. For alle delene for denne pset, vi kommer til å være håndtere fil innganger og utganger, fil I / O. Vi kommer til å gå over en rekke programmer som omhandler matriser peker til filer og sånt, så vi ønsker å være sikker på at vi er veldig kjent og komfortabel arbeider med hvordan inngang og utgang til filer. I fordelingen koden for denne pset er en fil som heter copy.c, og det er det vi kommer til å finne kommer til å være veldig nyttig for oss fordi vi kommer til å ende opp med faktisk å kopiere copy.c filen og bare endre det litt å kunne oppnå de første 2 deler av oppgaven. Og så da, som jeg nevnte tidligere, har vi å gjøre med punktgrafikk samt JPEG. Så egentlig å forstå strukturen av hvordan disse filene er organisert, hvordan vi virkelig kan oversette den 0'er og 1'ere i structs og ting som vi faktisk kan forstå og tolke og redigere, som vil være veldig viktig, så gå inn JPEG og bitmap-filer og forstå strukturen av disse. Pset4, som vanlig, begynner med en del spørsmål. De vil håndtere fil I / O og få deg vant til det. Da del 1 er whodunit, der du får en bitmap fil som ser typen som røde prikker over hele kroppen. Og deretter i utgangspunktet hva vi skal gjøre er å ta denne filen og bare redigere det litt inn i en versjon som vi kan lese. I hovedsak, når vi er ferdige, vil vi ha den samme filen, bortsett fra vi vil være i stand til å se det skjulte budskapet skjult av alle de røde prikkene. Deretter Resize er et program som, gitt en fil og deretter gitt navnet på filen som det utganger og deretter gitt et tall som godt, faktisk vil endre størrelsen at bitmap ved at heltallsverdi. Så til slutt, har vi Recover pset. Vi får et minnekort og deretter har å gjenopprette alle bildene som har blitt slettet ved et uhell, men, som vi skal lære, ikke egentlig slettet og fjernet fra filen; vi bare slags mistet hvor de var i filen, men vi kommer til å gjenopprette det. Flott. Så gå inn fil I / O spesielt, disse er en hel liste over funksjoner som du skal bruke. Du har allerede sett litt grunnleggende fopen, fread og fwrite, men vi kommer til å se nærmere på noen fil I / O-funksjoner som fputc, der du bare skrive ett tegn om gangen, til fseek, der du slags flytte filen posisjonsindikator forover og bakover, og deretter noen andre. Men vi vil gå inn på det litt senere i løpet av pset. Så først, bare for å komme inn fil I / O før vi går inn i pset, å åpne en fil, for eksempel, er hva du har å gjøre faktisk sette en peker til den filen. Så vi har en fil * peker. I dette tilfellet, jeg kaller det en i peker fordi det kommer til å være min infile. Og så jeg kommer til å bruke funksjonen fopen og så navnet på filen og deretter hvilken modus jeg kommer til å være håndtere filen. Så det er "r" i dette tilfellet for å lese, "w" for skriving, og deretter "a" for å føye til. For eksempel, når du arbeider med en infile og alt du ønsker å gjøre er å lese bits og bytes lagret der, så er du sannsynligvis kommer til å ønske å bruke "r" som modusen. Når du ønsker å faktisk skrive, type lage en ny fil, så hva vi skal gjøre er at vi kommer til å åpne den nye filen og bruke "w"-modus for å skrive. Så når du faktisk leser inn filene, er strukturen som følger. Først inkluderer pekeren til struct som skal inneholde de bytes som du leser. Så det kommer til å være slutten plasseringen av bytes som du leser. Du deretter kommer til å indikere størrelsen, liker i utgangspunktet hvor mange byte programmet har å lese i til filen, størrelsen utgangspunktet en del er, og du kommer til å spesifisere hvor mange elementer du ønsker å lese. Og så til slutt, må du vite hvor du leser fra, så det kommer til å bli din i pekeren. Jeg fargekodet disse fordi fread er også svært lik fwrite, bortsett fra at du vil være sikker på at du bruker riktig rekkefølge, sørg for at du faktisk skriver til eller leser fra høyre fil. Så da som før, hvis vi har størrelsen av elementet samt antall elementer, så kan vi spille rundt her litt. Si jeg har en hund struct og så da vil jeg lese to hunder om gangen. Hva jeg kunne gjøre er å si størrelsen på ett element kommer til å være på størrelse med en hund og jeg kommer til å faktisk lese to av dem. Alternativt er å si hva jeg kunne gjøre jeg bare kommer til å lese ett element og at ett element kommer til å være på størrelse med to hunder. Så det er analogt hvordan du kan slags lek rundt med størrelse og antall avhengig av hva som er mer intuitive for deg. OK. Så nå får vi til å skrive filer. Når du ønsker å skrive en fil, er det første argumentet faktisk der du leser fra. Så det er i utgangspunktet dataene du skal skrive inn filen, som er den ute pekeren på slutten. Så når du arbeider med pset, sørg for at du ikke blir forvirret. Kanskje har definisjonene side ved side. Du kan trekke definisjonene opp i manualen ved å skrive mannen og så fwrite, for eksempel, i terminalen, eller du kan se tilbake på dette lysbildet og sørg for at du bruker den rette. Så igjen, for fwrite, når du har en fil som du ønsker å skrive inn, som kommer til å bli det siste argumentet, og det kommer til å være en peker til den filen. Så da det er hvordan vi håndterer skrive kanskje flere byte om gangen, men si at du ønsker å bare skrive i bare ett enkelt tegn. Som vi skal se senere i dette eksempelet, i punktgrafikk må vi bruke det. Det er da vi kan bruke fputc, egentlig bare å sette en karakter på en gang, chr, inn i filen pekeren, og det er vår ute pekeren der. Så da når vi søker eller skrive i en fil, filen er å holde styr på hvor vi er. Så det er en slags markør, filen posisjonsindikator. Og så når vi skriver eller leser igjen i en fil, filen husker faktisk hvor det er, og så det fortsetter fra der markøren er. Dette kan være nyttig når du vil, sier lese i en viss å gjøre noe og deretter lese i følgende beløp, men noen ganger vi kanskje vil gå tilbake eller faktisk starte fra en bestemt referanseverdi. Så da fseek funksjon, hva den gjør er tillater oss å flytte markøren i en bestemt fil et visst antall av bytes. Og hva vi må gjøre er å angi hvor referanseverdien er. Så enten den beveger seg fremover eller bakover fra der markøren i øyeblikket er, eller vi kan angi at det skal bare bevege seg i fra begynnelsen av filen eller fra slutten av filen. Og så kan du passere i negative eller positive verdier til beløp, og som vil slags flytte markøren enten forover eller bakover. Før vi kommer inn i de andre psets, noen spørsmål på fil I / O? Okay. Som vi får inn flere eksempler, gjerne stoppe meg for spørsmål. Så i whodunit, du levert en bitmap fil som ligner på denne røde på lysbildet, og det ser ut som dette - en haug med røde prikker - og du vet ikke egentlig hva som er skrevet. Hvis du myse, kan du være i stand til å se en liten blåaktig farge på innsiden midten. I hovedsak er det der teksten er lagret. Det var et mord som skjedde, og vi trenger å finne ut hvem som gjorde det. For å gjøre det, må vi slags konvertere dette bildet til et lesbart format. Hvis dere noen gang støtt på dette, noen ganger ville det være lite kits der du vil ha et forstørrelsesglass med en rød film. Anyone? Ja. Så du ville være handed noe som dette, ville du ha et forstørrelsesglass med den røde film over det, ville du sette den over bildet, og du ville være i stand til å se meldingen skjult der. Vi har ikke et forstørrelsesglass med rød film, så i stedet vi skal til slags lage vår egen i denne pset. Og slik at brukeren skal inn whodunit, så ledetråd,. Bmp, så det er infile, det er den røde prikken meldingen, og deretter de sier verdict.bmp kommer til å være vår utfil. Så det kommer til å opprette en ny punktgrafikkbilde lik ledetråd en bortsett fra i et lesbart format der vi kan se det skjulte budskapet. Siden vi kommer til å håndtere redigering og manipulering punktgrafikk av noe slag, vi kommer til å slags dykk i inn i strukturen av disse bitmap-filer. Vi gikk over disse litt i foredrag, men la oss se nærmere på dem litt mer. Punktgrafikk er egentlig bare et arrangement av bytes hvor vi har angitt som bytes mener det. Så her er typen som et kart over punktgrafikkbildet sier at det starter med noen header filer, starter med litt informasjon der. Du ser at på ca byte nummer 14 størrelsen er angitt av punktgrafikkbildet, og det fortsetter. Men så hva vi virkelig er interessert i her er i ferd rundt byte nummer 54. Vi har disse RGB tremannsrom. Hva som kommer til å gjøre er å inneholde de faktiske piksler, fargeverdiene. Alt over det i overskriften er litt informasjon tilsvarende bildestørrelsen, bredden av bildet, og høyden. Når vi går inn i polstring senere, vil vi se hvorfor størrelsen på bildet kan være annerledes enn bredden eller høyden. Så da å representere disse - disse punktgrafikkbilder er sekvenser av bytes - hva vi kunne gjøre er å si greit, jeg kommer til å huske at på 14-indeksen, det er der størrelsen er, for eksempel, men i stedet hva vi skal gjøre for å gjøre dette enklere er kapsle den i en struct. Og så har vi to structs gjort for oss, en BITMAPFILEHEADER og en BITMAPINFOHEADER, og så når vi leser i til denne filen, som standard det kommer til å gå i orden, og så for det er også kommer til å fylle inn variabler som biWidth og biSize. Og så til slutt, hver piksel representert med tre byte. Den første er mengden av blått i pixel, den andre er mengden av grønt, og til slutt, mengden av rødt, hvor 0 er egentlig ingen blå eller ingen grønne eller ingen rød og deretter ff er den maksimale verdien. Dette er heksadesimale verdier. Så hvis vi har FF0000, så det tilsvarer den maksimale mengden av blått og deretter ingen grønn og ingen røde, så da det ville gi oss en blå pixel. Så hvis vi har ff oss alle over hele linja, så det betyr at vi har en hvit piksel. Dette er slags motsatt typisk når vi sier RGB. Det som faktisk skjer BGR. Så hvis vi faktisk se på et eksempel på et punktgrafikkbilde - la meg trekke en opp her. Det er litt for liten. Jeg zoomet inn, og vi kan se det er kornete. Det ser ut som blokker av farge. Du har hvite blokker og deretter rødt blokker. Hvis du spiller i Microsoft Paint, for eksempel, kan du gjøre noe sånt ved utgangspunktet bare male noen kvadrater i en bestemt rekkefølge. Så hva dette betyr i bitmap er som følger. Her har vi første hvite piksler, at alle 6 er f-tallet, og da har vi røde piksler, angitt med 0000FF. Og så sekvensen av byte som vi har indikerer hvordan punktgrafikkbildet kommer til å se. Så det jeg har gjort her er bare skrevet ut alle disse byte og deretter farget i rødt slik at du kan slags se, hvis du myse litt, hvordan den slags indikerer en smiley ansikt. Den måten som bitmap bilder arbeid er jeg ser det i utgangspunktet som et rutenett. Og så ved standard har hver rad i rutenettet for å være et multiplum av 4 byte. Hvis vi ser på et punktgrafikkbilde, du fyller hver verdi. For eksempel kan du ha en rød her, en grønn her, en blå her, men du må sørge for at bildet er fylt med et multiplum av fire byte. Så hvis jeg vil at min bilde for å være tre blokker bred, så jeg måtte sette en tom verdi i den siste til å gjøre det til en multippel på fire. Så da ville jeg legge inn noe som vi kaller polstring. Jeg skal bare indikere at det med en x. Nå sier vi ønsker et bilde som er 7 piksler lang, for eksempel. Vi har 1, 2, 3, 4, 5, 6, 7, og alt dette er fylt i med farge. Den måten som punktgrafikkbilder fungere er at vi trenger en åttende. Akkurat nå har vi 1, 2, 3, 4, 5, 6, 7. Vi trenger 8 plasser for punktgrafikkbildet å lese riktig. Så hva vi har å gjøre er å legge inn bare en bit av padding å sørge for at alle de bredder er ensartet og at alle de bredder er et multiplum av 4. Og så jeg tidligere indikert, utfylling som en x eller en snirklete linje, men i selve punktgrafikkbilder padding er angitt med en heksadesimal 0. Så det ville være et enkelt tegn, 0. Hva som kan komme til nytte er xxd kommandoen. Hva den gjør er faktisk viser deg, liker ligner på hva jeg gjorde før med smiley når jeg faktisk skrevet ut hva hver farge ville være for piksel og deretter fargekodet det, når du kjører xxd med følgende kommandoer, så vil det faktisk skrive ut hva fargene er for de piksler. Hva du trenger å gjøre er over her jeg viser, i likhet med-s 54 sier at jeg kommer til å starte på den 54. byte fordi før det, husk hvis vi ser tilbake til kart over punktgrafikk, det er alt topp informasjon og sånt. Men hva vi virkelig bryr seg om er de faktiske piksler som indikerer fargen. Så ved å legge i det flagget,-s 54, så vi er i stand til å se fargeverdiene. Og ikke bekymre deg om de kompliserte flagg og sånt. I oppgavesettet spec, vil du ha instruksjoner om hvordan du bruker xxd å vise piksler. Så hvis du ser her, den slags ser ut som en grønn boks, denne lille tingen. Jeg har fargekodet den 00FF00 som i utgangspunktet si ingen blå, mye grønt, og ingen røde. Slik som tilsvarer til grønt. Som du ser her, ser vi en grønn firkant. Denne grønne rektangelet er bare 3 piksler bred, så da hva vi har å gjøre å sørge for at bildet er et multiplum av fire brede er å legge inn ekstra polstring. Og så da det er hvordan du ser disse 0s her. Dette vil faktisk være et resultat av din Resize pset, hovedsak tar den lille bitmap og deretter forstørrer det med 4. Og så det vi ser er at faktisk dette bildet er 12 piksler bred, men 12 er et multiplum av 4, og slik at vi faktisk ikke se noen 0s på slutten fordi vi ikke trenger å legge til fordi det er fullt polstret. Det har ikke noe mer plass. Okay. Eventuelle spørsmål om utfylling? Okay. Cool. Som jeg nevnte tidligere, de punktgrafikk er bare en sekvens av bytes. Og så det vi har er stedet for å måtte holde styr på nøyaktig hvilke antall byte svarer til en bestemt element, vi faktisk har skapt en struct å representere det. Så det vi har er en RGBTRIPLE struct. Når du har en forekomst av et RGB-trippel, fordi dette er en type definere struct, så kan du få tilgang til rgbtBlue variabel, likeledes de grønne og røde variabler, som vil indikere hvor mye blått, grønt og rødt, henholdsvis, har du. Så hvis vi har den blå variabel satt til 0, den grønne settet til ff, som er den maksimale verdien du kan ha, og deretter det røde variabelen satt til 0, så hvilken farge ville denne spesielle RGB triple representere? >> [Student] Green. Green. Akkurat. Det kommer til å være nyttig å vite at når du har en forekomst av et RGB-trippel, du kan faktisk få tilgang mengden farge - blå, grønn og rød - separat. Nå som vi har snakket om strukturen av det, la oss ta en titt på BMP-filen. Dette er structs gjort for deg. Her har vi en BITMAPFILEHEADER struct. Av interesse er størrelsen. Senere har vi info header, som har noen flere ting som er interessant for oss, nemlig størrelsen, bredden og høyden. Som vi vil gå inn senere, når du leser i til filen, det står automatisk i fordi vi har satt for å være den samme. Så biSize vil inneholde de riktige bytes som tilsvarer den faktiske størrelsen på bildet. Og så her, til slutt, som vi har snakket om, har vi RGBTRIPLE typedef struct. Vi har en rgbtBlue, Grønn og Rød knyttet til den. Flott. Okay. Nå som vi forstår punktgrafikk litt, forstår at vi har en filhodet og en info header forbundet med det, og så etter det, har vi interessante ting av fargene, og disse fargene er representert ved RGBTRIPLE structs, og de i sin tur har tre verdier som er knyttet til den blå, grønne og røde. Så nå kan vi på en måte tenker på Gjenopprett litt. Unnskyld. Tenk på whodunit. Når vi har vår ledetråd fil, så hva vi ønsker å gjøre er å lese på den piksel for piksel og deretter noe endre disse piksler, slik at vi kan sende det til et lesbart format. Og så å sende det, kommer vi til å skrive piksel for piksel i verdict.bmp filen. Det er litt for mye å gjøre. Vi skjønner det. Så det vi har gjort er at vi faktisk har gitt deg med copy.c. Hva copy.c gjør er bare lager en nøyaktig kopi av et gitt bitmap fil og deretter utganger det. Så dette åpner allerede filen for deg, leser i piksel for piksel, og skriver deretter det til en utdatafil. La oss ta en titt på det. Dette er å sikre riktig bruk, får filnavnene her. Hva dette er det setter inndatafilen å være hva vi har gått på i det infile her, som er vår andre kommandolinje-argument. Sjekker å sørge for at vi kan åpne filen. Sjekker å sikre at vi kan lage en ny utfil her. Så hva dette gjør her, det bare starter utgangspunktet leser inn til bitmap fil fra begynnelsen. Begynnelsen, som vi vet, inneholder BITMAPFILEHEADER, og så de sekvenser av bits vil direkte fylle ut BITMAPFILEHEADER. Så det vi har her sier at BITMAPFILEHEADER bf - det er vår nye variabel av typen BITMAPFILEHEADER - vi kommer til å sette inne bf hva vi leser fra i pekeren, som er vår infile. Hvor mye leser vi? Vi leser i hvor mange byte vi trenger å inneholde hele BITMAPFILEHEADER. Tilsvarende, det er hva vi gjør for info header. Så vi fortsetter langs fil vår i innfil, og vi leser disse bits og bytes, og vi koble dem direkte i i disse tilfeller av de variablene som vi gjør. Her er vi bare å sørge for at bitmap er punktgrafikk. Nå har vi en utfil, ikke sant? Slik som det står når vi skaper det, er det egentlig tom. Så vi må i utgangspunktet lage en ny bitmap fra bunnen av. Hva vi gjør er at vi må sørge for at vi kopierer i filhodet og info header akkurat som infile har. Hva vi gjør er vi skriver - og husk at bf er variabelen av typen BITMAPFILEHEADER, så det vi gjør er vi bare bruke dette innholdet å skrive inn i utfil. Her husker vi snakket om padding, hvordan det er viktig å sørge for at mengden av piksler som vi har er et multiplum av fire. Dette er en ganske nyttig formel for å beregne hvor mye polstring du har gitt bredden av filen. Jeg ønsker dere å huske at i copy.c har vi en formel for beregning padding. Ok? Så alle husker det. Flott. Så hva copy.c gjør neste er det gjentar over alle de scanlines. Det går gjennom radene først og deretter lagrer hver trippel at den leser og skriver den med til den utfil. Så da her vi leser bare én RGB trippel gangen og deretter sette det samme trippel i utfil. Den vanskelige delen er at padding er ikke en RGB trippel, og så vi kan ikke bare lese det padding mengde RGB tremannsrom. Hva vi trenger å gjøre er faktisk bare flytte vår fil indikator, flytte vår markøren, å slags hoppe over all utfylling slik at vi er på neste rad. Og så hva dette gjør er å kopiere viser deg hvordan du kanskje vil legge til padding. Så vi har beregnet hvor mye polstring vi trenger, så det betyr at vi trenger padding antall 0s. Hva dette er en for løkke som setter polstring antall 0s inn utfil vår. Og så til slutt, lukker du begge filene. Du lukker infile samt utfil. Så det er slik copy.c fungerer, og det kommer til å være ganske nyttig. I stedet for bare faktisk direkte kopiere og lime det eller bare se på det og skrive inn hva du vil, kanskje du bare ønsker å utføre denne kommandoen i terminalen, cp copy.c whodunit.c, noe som vil skape en ny fil, whodunit.c, som inneholder nøyaktig samme innhold som kopi gjør. Så hva vi kan gjøre er å bruke den som et rammeverk ved å bygge og redigere for vår whodunit fil. Dette er vår to-dos å gjøre for whodunit, men hva copy.c gjør er tar faktisk vare på de fleste av dem for oss. Så alt vi trenger å gjøre neste er å endre bildepunktene som nødvendig å faktisk gjøre filen lesbar. Husk at for en gitt piksel trippel, så for en gitt variabel av typen RGBTRIPLE, du kan få tilgang til blå, grønn og rød verdier. Det kommer til å komme godt fordi hvis du kan få tilgang til dem, det betyr at du også kan kontrollere dem, og det betyr at du også kan endre dem. Så når vi gikk tilbake til vår rød forstørrelsesglass eksempel I utgangspunktet var det fungerte som en slags filter for oss. Så det vi ønsker å gjøre er vi ønsker å filtrere alle tripler som kommer i. Det finnes flere forskjellige måter å gjøre dette. I utgangspunktet kan du ha uansett hva slags filter du ønsker. Kanskje du ønsker å endre alle røde piksler eller kanskje du ønsker å endre en annen farge pixel til en annen farge. Det er opp til deg. Husk at du kan sjekke hvilken farge piksel er og deretter kan du også endre det som du går gjennom. Okay. Så det er whodunit. Når du kjører whodunit, vet du hvem som den skyldige av kriminalitet var. Nå skal vi gå til Resize. Vi kommer til å fortsatt være å håndtere punktgrafikk. Hva vi kommer til å gjøre er at vi kommer til å ha en inngang bitmap og vi kommer til å passere i en rekke, og deretter få en utfil bitmap hvor det er utgangspunktet vårt infile skalert med n. Si min filen var bare én piksel store. Så hvis min n var 3, skalering med 3, så ville jeg gjenta at pixel n antall ganger, så 3 ganger, og deretter også skalere det ned 3 ganger også. Så du ser jeg skalere den vertikalt og horisontalt. Og så er her et eksempel. Hvis du har n = 2, ser du at den første blå pixel det gjentas to ganger horisontalt samt to ganger vertikalt. Og da fortsetter, og så har du en direkte skalering av det opprinnelige bildet av to. Så hvis vi skulle detalj pseudokode for dette, ønsker vi å åpne filen. Og så vet at hvis vi går tilbake hit, ser vi at bredden for utfil kommer til å være annerledes enn bredden for infile. Hva betyr det? Det betyr at vår hodeinformasjon kommer til å endre. Og så hva vi ønsker å gjøre er å oppdatere header info, vel vitende om at når vi leser i filene hvis du opererer på copy.c rammeverk, vi allerede har en variabel som indikerer hva størrelsen er og ting som det. Så når du har det, hva du kanskje ønsker å gjøre er å endre de aktuelle variabler. Husk, hvis du har en struct, hvordan du får tilgang til variabler innenfor det. Du bruker dot operatør, ikke sant? Så da bruker det, vet du at du må endre overskriften info. Så her er bare en liste over de faktiske elementer som kommer til å være i endring i filen. Filstørrelsen skal være i endring, bildet, samt bredden og høyden. Så da går tilbake til kart over punktgrafikk, se på om det er filhodet eller info header som inneholder denne informasjonen og deretter endre etter behov. Igjen, sier cp copy.c resize.c. Det betyr at resize.c nå inneholder alt som er inneholdt i kopi fordi kopien gir oss en måte å lese på hver enkelt scanline piksel for piksel. Bortsett fra nå, i stedet for bare å endre verdiene som vi gjorde i whodunit, hva vi ønsker å gjøre er vi ønsker å skrive i flere piksler så lenge vår n er større enn 1. Så hva vi ønsker å gjøre er vi ønsker å strekke det horisontalt n, samt strekke det vertikalt av n. Hvordan kan vi gjøre dette? Si din n er 2 og du har dette gitt infile. Markøren kommer til å starte på den første, og hva du vil gjøre hvis n er 2, vil du skrive ut i 2 av disse. Så du skrive ut i to av disse. Deretter markøren kommer til å gå til neste piksel, som er den røde, og det kommer til å skrive ut to av de røde, tilføye det på hva det har gjort før. Deretter markøren vil flytte til neste piksel og trekke i 2 av disse. Hvis du ser tilbake til copy.c rammeverk, hva dette betyr her er det skaper en ny forekomst av et RGB-trippel, en ny variabel kalt trippel. Og her når den leser inn i det, leser det fra infile en RGBTRIPLE og lagrer den på innsiden av det trippel variabel. Så da du faktisk har en variabel som representerer den aktuelle piksel. Så når du skriver, hva du kanskje ønsker å gjøre er encase fwrite setningen i en for loop som skriver det inn utfil din så mange ganger som nødvendig. Det er enkelt nok. Bare utgangspunktet gjenta skriveprosessen n antall ganger for å skalere den horisontalt. Men da må vi huske at vår padding kommer til å endre seg. Tidligere si at vi hadde noe av lengde 3. Da ville vi bare legge i hvor mye polstring? Bare en mer for å gjøre det til en multippel av 4. Men sier at vi skalere dette bestemt bilde av n = 2. Så da hvor mange blå piksler ville vi ha til slutt? Vi ville ha seks. 1, 2, 3, 4, 5, 6. OK. 6 er ikke et multiplum av 4. Hva er det nærmeste multiplum av 4? Det kommer til å være 8. Så vi faktisk kommer til å ha to tegn av padding der. Husker noen hvis vi har en formel for å beregne padding og hvor det kan være? [Uhørlig student respons] >> Ja, copy.c. Høyre. Det er en formel i copy.c å beregne hvor mye polstring du har gitt en bestemt bredde av det punktgrafikkbilde. Så da det kommer til å være nyttig når du trenger å legge i en viss padding å faktisk finne ut hvor mye polstring du trenger å legge til. Men ett notat, skjønt, er at du vil være sikker på at du bruker riktig størrelse. Bare vær forsiktig fordi du i utgangspunktet skal gjøre med to punktgrafikkbilder. Du ønsker å være sikker på at du bruker den rette. Når du beregner padding for utfil, du vil bruke bredden på utfil og ikke bredden av den forrige. Flott. Den slags tar seg av strekke en hel punktgrafikkbilde horisontalt. Men hva vi ønsker å gjøre er å strekke det faktisk vertikalt også. Dette kommer til å være litt mer komplisert fordi når vi er ferdig med å kopiere en rad og skriver at rad, vår markøren kommer til å være på slutten. Så hvis vi leser igjen, så det er bare kommer til å lese på neste linje. Så det vi ønsker å gjøre er slags finne en måte å kopiere disse radene igjen eller bare slags ta raden og deretter skrive det igjen. Som jeg slags antydet, er det flere forskjellige måter å gjøre dette. Hva du kan gjøre er som du går gjennom og lese gjennom den aktuelle scanline og endre det som er nødvendig, deretter type butikk alle disse pikslene i en matrise. Senere på deg vet at du må skrive ut denne matrisen igjen, og så kan du bare bruke denne matrisen til å gjøre det. En annen måte å gjøre det er at du kan kopiere én rad ned, forstår at du trenger å kopiere det igjen, så faktisk flytte markøren, og det kommer til å bruke den metoden fseek. Du kan flytte markøren helt tilbake og gjenta kopieringen på nytt. Så hvis vår skalering nummer er n, så hvor mange ganger må vi gå tilbake og skrive en linje? >> [Student] n - 1. >> Ja, perfekt. n - 1. Vi har gjort det en gang allerede, så da vi ønsker å gjenta kommer tilbake prosessen n - 1 antall ganger. Okay. Så der har du din resize funksjon. Nå kan vi få til en veldig morsom del, min favoritt pset, som er friske. I stedet for punktgrafikk, denne gangen vi har å gjøre med JPEG. Vi faktisk ikke får en fil bare av JPEG, vi får i utgangspunktet en rå minnekort format. Og så dette inneholder litt av info og søppel verdier i begynnelsen, og det begynner og den har en haug med JPEG-filer. Men vi ga et kort hvor vi har slettet bildene; hovedsak har vi glemt hvor bildene ligger innenfor kort. Så da er vår oppgave i Recover er å gå gjennom dette kortet format og finne de bildene igjen. Heldigvis, er strukturen i JPEG-filer og kortet filen litt nyttig. Det kunne definitivt ha vært litt mer komplisert hvis det ikke var i dette formatet. Hver JPEG-fil starter faktisk med to mulige sekvenser, som er nevnt ovenfor. I utgangspunktet, når du har en ny JPEG-fil, den starter med enten sekvensen ffd8 ffe0 eller den andre, ffd8 ffe1. En annen nyttig ting å vite er at JPEG lagres contiguously. Så når en JPEG-fil slutter, den andre starter. Så det er ikke noen form for i-mellom verdiene der. Når du treffer starten på en JPEG, hvis du allerede har lest en JPEG, du vet at du har truffet på slutten av forrige og begynnelsen av neste. Å slags visualisere dette, gjorde jeg en skjematisk. En annen ting om JPEG er at vi kan lese dem i sekvenser på 512 bytes om gangen, tilsvarende med begynnelsen av kortet. Vi trenger ikke å være sjekker hver eneste byte fordi det ville suge. Så i stedet, hva vi kan gjøre er faktisk bare lese i 512 bytes om gangen og da, i stedet for å sjekke inn mellom de i de bitte små skiver, Vi kan bare sjekke begynnelsen av 512 byte. Hovedsak, i dette bildet, det du ser er i begynnelsen av kortet, du har verdier som ikke er virkelig relevant for de faktiske JPEG selv. Men hva jeg har er en stjerne for å indikere en av de to start sekvenser for en JPEG. Så når du ser en stjerne, vet du at du har en JPEG-fil. Og deretter hver JPEG-fil skal være noen flere på 512 bytes men ikke nødvendigvis det samme flere. Måten du vet at du har truffet en annen JPEG er hvis du treffer en annen stjerne, en annen startrekkefølge bytes. Så hva du har her er at du har den røde JPEG-fil fortsetter til du treffer en stjerne, som er angitt med en ny farge. Du fortsetter og du treffer en annen stjerne, du treffer en annen JPEG, du fortsetter helt til slutten. Du er på det siste bildet her, den rosa. Du gå til slutten før du treffer slutten av filen karakter. Dette kommer til å være veldig nyttig. Noen viktigste takeaways her: Kortet filen starter ikke med en JPEG, men når en JPEG starter, blir alle JPEG lagret side om side med hverandre. Noen pseudokode for Recover. Først, vi kommer til å åpne våre kort fil, og det kommer til å bruke vår fil I / O-funksjoner. Vi kommer til å gjenta følgende prosess før vi har nådd slutten av filen. Vi kommer til å lese 512 bytes om gangen. Og det jeg sa her er vi kommer til å lagre den i en buffer, så i utgangspunktet holde på de 512 bytes før vi vet nøyaktig hva de skal gjøre med dem. Så hva vi ønsker å gjøre er vi ønsker å sjekke om vi har truffet en stjerne eller ikke. Hvis vi har truffet en stjerne, hvis vi har truffet et av utgangspunktene sekvenser, da vet vi at vi har truffet en ny JPEG-fil. Hva vi ønsker å gjøre er vi kommer til å ønske å opprette en ny fil i vår pset4 katalog å fortsette å gjøre denne filen. Men også, hvis vi har allerede gjort en JPEG før, så vi ønsker å avslutte denne filen og skyv den mot pset4 mappe, der vi vil ha den filen lagret fordi hvis vi ikke angir at vi har endte som JPEG-fil, så får vi i utgangspunktet har en ubestemt beløp. De JPEG vil aldri ta slutt. Så vi vil være sikker på at når vi leser i en JPEG-fil og skrive det, vi ønsker å spesifikt nær at for å åpne neste. Vi ønsker å sjekke flere ting. Vi ønsker å sjekke om vi er i starten av en ny JPEG med buffer vår og også hvis vi allerede har funnet en JPEG før fordi det vil endre prosessen litt. Så når du går gjennom hele veien og du treffer slutten av filen, så hva du ønsker å gjøre er at du ønsker å lukke alle filene som er åpne. Det vil trolig være den siste JPEG-fil som du har, samt kort fil som du har hatt befatning med. Den siste hindringen som vi må takle er hvordan du faktisk lage en JPEG-fil og hvordan du faktisk skyve den til mappen. Den pset krever at hver JPEG som du finner være i følgende format, hvor du har nummeret. jpg. Nummeret, selv om det er 0, kaller vi det 000.jpg. Når du finner en JPEG i programmet, du kommer til å gi den navnet i den rekkefølgen det er funnet. Hva betyr dette? Vi trenger å slags holde styr på hvor mange vi har funnet og hva antallet av hver JPEG bør være. Her skal vi dra nytte av sprintf funksjon. I likhet med printf, som bare slags utskrifter en verdi ut i terminalen, sprintf skriver filen ut i mappen. Og så hva dette ville gjøre hvis jeg hadde sprintf, tittel og deretter strengen der, det ville skrive ut 2.jpg. Forutsatt at jeg har lukket filene mine riktig, som vil inneholde filen som jeg hadde skrevet ut. Men en ting er at koden som jeg har her ikke helt tilfredsstiller hva pset krever. Den pset krever at andre JPEG filen skal hete 002 i stedet for bare to. Så når du skriver ut navnet, så kanskje kan det være lurt å endre plassholderen litt. Husker noen hvordan vi tillater for ekstra mellomrom når vi ut noe? Ja. >> [Student] Du setter en 3 mellom prosenttegn og to. >> Ja, perfekt. Du vil sette en 3 i dette tilfellet fordi vi vil ha plass til tre. % 3d ville trolig gi deg 002.jpg istedenfor 2. Det første argumentet i sprintf funksjonen er faktisk en char array, som vi tidligere kjente som strenger. De vilje, type mer som en midlertidig lagring, bare lagre den resulterende strengen. Du vil egentlig ikke håndtere dette, men du må ta det. Vel vitende om at hver filnavnet har nummer, som tar opp tre tegn, og da. jpg, bør hvor lenge denne tabellen være? Kaste ut et tall. Hvor mange tegn i tittelen, i navnet? Så det er 3 hashtags, punktum, jpg. >> [Student] 7. >> 7. Ikke helt. Vi kommer til å ønske 8 fordi vi ønsker å tillate for null terminator også. Til slutt, bare trekke ut prosessen som du skal gjøre for gjenvinning, du har noen begynnelse informasjon. Du fortsetter til du finner starten på en JPEG-fil, og som kan være enten en av to utgangspunkter sekvenser. Du holder på å lese. Hver skråstrek her representerer 512 bytes. Du holder på å lese, holder på å lese før du får en annen startsekvens. Når du har det, du vil avslutte den aktuelle JPEG - i dette tilfellet er det den røde, så du ønsker å avslutte det. Du ønsker å sprintf navnet på det inn i din pset4 mappe, så du ønsker å åpne en ny JPEG og deretter holde på lesing til du støter på den neste. Holder på å lese, holder på å lese, og så til slutt, til slutt, du kommer til å nå slutten av filen, og så vil du ønsker å lukke den siste JPEG som du arbeidet med, sprintf at inn pset4 mappe, og deretter se på alle bildene som du har fått. Disse bildene er faktisk bilder av CS50 ansatte, og så dette er hvor bonus morsom del av pset kommer i er at du konkurrerer i seksjonene dine for å finne de TFS i bildene og ta bilder med dem for å bevise at du har gjort det pset og så kan du se hvilke ansatte er på bildene. Så da kan du ta bilder med personalet. Noen ganger må du jage dem ned. Sannsynligvis noen av dem vil prøve å løpe vekk fra deg. Du ta bilder med dem. Dette er pågående. Det er ikke på grunn av når pset skyldes. Fristen vil bli annonsert i spec. Deretter sammen med inndelingen, tar hvilken seksjon de fleste bildene med de fleste ansatte vil vinne en ganske imponerende premie. Det er slags insentiv til å få pset4 ferdig så raskt som mulig fordi da kan du komme ned til virksomheten jakte ned alle de forskjellige CS50 ansatte. Det er ikke obligatorisk, skjønt, så når du får bildene, så er du ferdig med pset4. Og jeg er ferdig med Walkthrough 4, så takk skal du ha for å komme. Lykke til med Forensics. [Applaus] [CS50.TV]