[Powered by Google Translate] [Soluzione - Problema Set 4] [Zamyla Chan - Harvard University] [Questo è CS50. - CS50.TV] Bene. Ciao a tutti, e benvenuti a Walkthrough 4. Oggi la nostra pset è Forensics. Forensics è un pset davvero divertente che coinvolge fare con file bitmap per scoprire chi ha commesso un reato. Poi andremo a ridimensionare alcuni file bitmap, allora stiamo anche andando a che fare con una parte davvero divertente chiamato Recover, in cui stiamo praticamente consegnato una scheda di memoria in cui qualcuno ha accidentalmente cancellato tutti i loro file, e abbiamo chiesto di recuperare i file. Ma prima, prima di entrare in pset, ho davvero voglia di congratularmi con tutti. Siamo circa a metà di questo corso. Quiz 0 è dietro di noi, e siamo a pset4, quindi in sostanza, siamo a metà strada. Abbiamo percorso una lunga strada, se si guarda indietro alle vostre pset, pset0 e pset1, quindi congratularmi con te su questo, e stiamo per entrare in alcune cose davvero divertenti. Così la nostra cassetta degli attrezzi per questo pset, ancora una volta, invece di eseguire sudo yum-y update, siamo in grado di eseguire solo update50 se siete alla versione 17.3 e superiore dell'apparecchio. Quindi, essere sicuri di eseguire update50 - è molto più facile, alcuni caratteri meno - per assicurarsi che siete al l'ultima versione dell'apparecchio. Soprattutto è importante update50 quando iniziare ad usare CS50 Check. Quindi assicuratevi che l'hai fatto. Per tutte le sezioni di questo pset, stiamo andando a che fare con file di input e output, file I / O. Stiamo per andare in un sacco di programmi che si occupano di array puntano ai file e cose del genere, quindi vogliamo fare in modo che siamo molto familiare e confortevole che fare con il modo di input e output in file. Nel codice di distribuzione per questo pset è un file chiamato impossibile fare, ed è quello che stiamo andando a trovare sta per essere veramente utile per noi perché stiamo andando a finire copiando il file di impossibile fare e semplicemente modificando leggermente per poter raggiungere i primi due parti del problema proposto. E così poi come ho detto prima, abbiamo a che fare con le immagini bitmap, nonché JPEG. Quindi, in realtà la comprensione della struttura di come questi file sono organizzati, come si può davvero tradurre il 0 e 1 in strutture e le cose che si possono realmente capire e interpretare e modificare, che sarà molto importante, in modo da andare in JPEG e file bitmap e comprendere la struttura di quelli. Pset4, come al solito, inizia con una sezione di domande. Chi si occuperà di file di I / O e farti abituato a questo. Poi parte 1 è Whodunit, in cui si è dato un file bitmap che sembra un po 'come puntini rossi in tutto. E poi in fondo quello che stiamo andando a fare è prendere questo file e solo modificarlo un po ' in una versione che possiamo leggere. In sostanza, una volta finito, avremo lo stesso file, tranne saremo in grado di vedere il messaggio nascosto nascosto da tutti quei puntini rossi. Poi Resize è un programma che, dato un file e poi dato il nome del file che emette e poi dato un numero come pure, effettivamente ridimensionare che bitmap da tale valore intero. Poi, infine, abbiamo la pset Recover. Ci viene data una scheda di memoria e quindi sono tenuti a recuperare tutte le foto che sono stati accidentalmente cancellati, ma, come vedremo, imparino, non effettivamente eliminati e rimosso dal file; abbiamo perso solo tipo di dove si trovavano nel file, ma abbiamo intenzione di recuperare tale. Grande. Quindi, andando nel file di I / O in particolare, si tratta di tutta una serie di funzioni che verranno utilizzati. Hai già visto un po 'le basi di fopen, fread, fwrite, e ma abbiamo intenzione di approfondire un po 'di file di I / O, quali funzioni fputc, in cui è sufficiente scrivere un carattere alla volta, a fseek, dove tipo di spostare l'indicatore di posizione del file in avanti e indietro, e poi alcuni altri. Ma andiamo in quello un po 'più tardi nel corso della pset. Quindi, prima, giusto per entrare in file di I / O prima di andare in pset, per aprire un file, per esempio, quello che dovete fare è in realtà impostare un puntatore al file. Così abbiamo un puntatore FILE *. In questo caso, sto definendolo un puntatore perché sarà la mia infile. E così ho intenzione di utilizzare la funzione fopen e quindi il nome del file e poi il modo in cui ho intenzione di avere a che fare con il file. Quindi c'è "r", in questo caso per la lettura, "w" per la scrittura, e quindi "a" per aggiungere. Per esempio, quando hai a che fare con un infile e tutto quello che voglio fare è leggere i bit e byte memorizzati, allora probabilmente stai andando a voler usare "r" come modalità. Quando si desidera scrivere in realtà, una sorta di creare un nuovo file, allora quello che andremo a fare è che andremo ad aprire il nuovo file e utilizzare la modalità "w" per la scrittura. Allora quando si è in realtà la lettura nei file, la struttura è la seguente. Prima di includere il puntatore alla struttura che conterrà i byte che si sta leggendo. In modo che sarà la posizione finale dei byte che si sta leggendo. Stai andando poi per indicare la dimensione, come in pratica il numero di byte il vostro programma deve leggere il file, il formato in genere da un elemento, e poi si sta andando a specificare il numero di elementi che si desidera leggere. E poi, infine, è necessario sapere dove stai leggendo, in modo che sarà il puntatore in. I colori diversi, perché questi fread è anche molto simile a fwrite, se non si vuole fare in modo di utilizzare il giusto ordine, fare in modo che si sta effettivamente scrittura o la lettura dal file di destra. Quindi come prima, se abbiamo la dimensione dell'elemento e il numero di elementi, allora possiamo giocare qui un po '. Dire che ho una struttura DOG e così poi voglio leggere due cani alla volta. Quello che ho potuto fare è dire le dimensioni di un elemento sarà la dimensione di un cane e ho intenzione di leggere in realtà due di loro. In alternativa, quello che ho potuto fare è dire che sto solo andando a leggere un elemento e che un elemento sta per essere la dimensione di due cani. Ecco, questo è analogo come è possibile tipo di gioco in giro con dimensioni e numero a seconda di cosa è più intuitivo per voi. Bene. Così ora si arriva a file di scrittura. Quando si desidera scrivere un file, il primo argomento è in realtà dove si sta leggendo da. Ecco, questo è fondamentalmente i dati che si sta per scrivere nel file, che è il puntatore alla fine. Così, quando hai a che fare con il pset, fare attenzione a non confondersi. Forse avere il lato definizioni a fianco. È possibile tirare le definizioni nel manuale digitando man e poi fwrite, per esempio, nel terminale, oppure è possibile fare riferimento a questa diapositiva e assicurarsi che si sta utilizzando quella giusta. Quindi, di nuovo, per la fwrite, quando si dispone di un file che si desidera scrivere in, che sta per essere l'ultimo argomento e che sta per essere un puntatore a tale file. Allora è così che abbiamo a che fare con la scrittura, forse diversi byte alla volta, ma che tu voglia scrivere solo in un singolo carattere. Come vedremo più avanti in questo esempio, nelle bitmap dovremo usare quello. In quel momento possiamo usare fputc, essenzialmente solo mettendo un carattere alla volta, chr, nel puntatore a file, e questo è il nostro puntatore fuori. Allora ogni volta che cerchiamo o scrivere in un file, il file è tenere traccia di dove ci troviamo. Quindi è una sorta di cursore, l'indicatore di posizione del file. E così ogni volta che scrivere o leggere di nuovo in un file, il file in realtà si ricorda dove si trova, e così continua da dove si trova il cursore. Questo può essere utile quando si desidera, ad esempio, letto in una certa quantità di fare qualcosa e quindi leggere nelle seguenti quantità, ma a volte si potrebbe desiderare di tornare indietro o di fatto, a partire da un valore di riferimento certo. Allora la funzione fseek, ciò che fa è permette di spostare il cursore in un determinato file un certo numero di byte. E poi quello che dobbiamo fare è specificare dove il valore di riferimento è. Quindi, o si muove in avanti o indietro da dove si trova il cursore al momento, oppure si può specificare che deve solo muovere in dall'inizio del file o dalla fine del file. E così è possibile passare a valori negativi o positivi alla quantità, e che tipo di spostare il cursore in avanti o indietro. Prima di entrare nei pset altri, tutte le questioni sui file I / O? Va bene. Man mano che in altri esempi, non esitate a fermarmi per le domande. Quindi, in Whodunit, si sta consegnato un file bitmap simile a questo rosso sulla diapositiva, e sembra che questo - un mucchio di punti rossi - e non so davvero cosa c'è scritto. Se si strabismo, si può essere in grado di vedere una leggera colorazione bluastra all'interno del mezzo. In sostanza, è lì che il testo è memorizzato. C'è stato un omicidio che è successo, e abbiamo bisogno di scoprire chi lo ha fatto. Per fare questo, abbiamo bisogno di convertire questo tipo di immagine in un formato leggibile. Se voi ragazzi mai incontrato questo, a volte non ci sarebbe kit piccoli dove si avrebbe una lente di ingrandimento con una pellicola rosso. Nessuno? Gia '. Così si sarebbe qualcosa di mano in questo modo, si avrebbe una lente d'ingrandimento con la pellicola rossa su di esso, si sarebbe messo sopra l'immagine, e si sarebbe in grado di vedere il messaggio nascosto in essa. Noi non abbiamo una lente di ingrandimento con la pellicola rossa, così invece che andremo a creare il nostro tipo di propria in questo pset. E così che l'utente sta per giallo, allora l'indizio,. Bmp, quindi questo è il infile, questo è il messaggio di punto rosso, e poi dicono verdict.bmp sarà il nostro file di emissione. Così sta andando a creare una nuova immagine bitmap simile a uno indizio se non in un formato leggibile in cui possiamo vedere il messaggio nascosto. Dal momento che stiamo andando a che fare con la modifica e la manipolazione di immagini bitmap di qualche tipo, stiamo andando a tipo di immersione in nella struttura di questi file bitmap. Siamo andati oltre questi un po 'in conferenza, ma guardiamo in loro un po' di più. Bitmap sono essenzialmente solo un accordo di byte dove abbiamo specificato che byte dire quello. Così qui è un po 'come una mappa dell'immagine bitmap dicendo che inizia con alcuni file di intestazione, inizia con alcune informazioni in là. Si vede che a circa 14 il numero di byte di dimensione è indicata l'immagine bitmap, e continua su. Ma allora che cosa stiamo realmente interessa qui sta iniziando intorno numero di byte 54. Abbiamo questi triple RGB. Cosa che sta per fare è contenere i pixel effettivi, i valori di colore. Tutto ciò al di sopra che nell'intestazione sono alcune informazioni corrispondente alla dimensione dell'immagine, la larghezza dell'immagine, e l'altezza. Quando andiamo in imbottitura in seguito, vedremo perché la dimensione dell'immagine potrebbero essere diverse o della larghezza. Allora per rappresentare questi - queste immagini bitmap sono sequenze di byte - quello che abbiamo potuto fare è dire che va bene, ho intenzione di ricordare che al punto 14, è lì che la dimensione è, per esempio, ma invece quello che andremo a fare per rendere questo più facile sta incapsulare in una struttura. E così abbiamo due strutture fatte per noi, un BITMAPFILEHEADER e un BITMAPINFOHEADER, e così ogni volta che si legge per quel file, per impostazione predefinita, sta per andare in ordine, e così in ordine è anche andando a riempire in variabili quali biWidth e biSize. E infine, ogni pixel è rappresentato da tre byte. La prima è la quantità di blu nel pixel, il secondo è la quantità di verde, e, infine, la quantità di rosso, dove 0 è essenzialmente blu o verde o non è rosso e poi ff è il valore massimo. Si tratta di valori esadecimali. Allora se abbiamo ff0000, poi che corrisponde all'importo massimo di blu e poi non verde e non rosso, e allora che ci avrebbe dato un pixel blu. Poi se abbiamo FF tutto su tutta la linea, allora ciò significa che abbiamo un pixel bianco. Questa è una specie di fronte al solito quando si dice RGB. In realtà andando BGR. Quindi, se abbiamo effettivamente guardare in un esempio di un'immagine bitmap - fammi un tiro qui. E 'un po' piccola. Sono lo zoom, e possiamo vedere che è sgranata. Sembra blocchi di colore. Non ci sono blocchi bianchi e poi blocchi rossi. Se si gioca in Microsoft Paint, per esempio, si potrebbe fare una cosa del genere fondamentalmente solo da dipingere alcuni quadratini in un ordine specifico. E allora che cosa questo si traduce nella bitmap è la seguente. Qui abbiamo prima pixel bianchi, che tutti e 6 sono f, e poi abbiamo pixel rossi, indicato da 0000FF. E così la sequenza di byte che abbiamo indica come l'immagine bitmap è andare a guardare. Quindi quello che ho fatto qui è solo scritto tutti quei byte e poi colorate in rosso modo che sia possibile tipo di vedere, se si strabismo un po ', come questo tipo di indica una faccina sorridente. Il modo in cui le immagini bitmap lavoro io lo immagino in pratica come una griglia. E così di default, ogni riga della griglia deve essere un multiplo di 4 byte. Se guardiamo un'immagine bitmap, si sta riempiendo in ogni valore. Per esempio, si potrebbe avere un rosso qui, un verde qui, un blu qui, ma bisogna fare in modo che l'immagine viene riempita con un multiplo di quattro byte. Quindi, se voglio che la mia immagine da tre blocchi di larghezza, quindi vorrei mettere un valore vuoto in ultimo a un multiplo di quattro. Allora vorrei aggiungere in qualcosa che stiamo chiamando imbottitura. Sto solo andando a indicare che lì con una x. Ora, dire che vogliamo un'immagine che è lunga 7 pixel, per esempio. Abbiamo 1, 2, 3, 4, 5, 6, 7, e tutto questo è riempita di colore. Il modo in cui le immagini bitmap lavoro è che abbiamo bisogno di un 8. In questo momento ci sono 1, 2, 3, 4, 5, 6, 7. Abbiamo bisogno di 8 spazi per l'immagine bitmap di leggere correttamente. Quindi quello che dobbiamo fare è aggiungere in un po 'di imbottitura fare in modo che tutte le larghezze sono uniformi e che tutte le larghezze sono un multiplo di 4. E così ho indicato in precedenza, imbottitura come x o una linea ondulata, ma nelle immagini reali bitmap l'imbottitura è indicata da uno 0 esadecimale. In modo che sarebbe un singolo carattere, 0. Ciò che potrebbe tornare utile è il comando xxd. Ciò che fa è in realtà mostra, come simile a quello che ho fatto prima con lo smiley quando ho stampato quello che ogni colore sarebbe per il pixel e poi colori diversi, quando si esegue xxd con i seguenti comandi, allora verrà la stampa cosa i colori sono per quei pixel. Quello che devi fare è qui indico, come il-s 54 dice che ho intenzione di iniziare al byte 54 perché prima che, ricordo se torniamo ad osservare la mappa delle bitmap, è tutto quello che le informazioni di intestazione e cose del genere. Ma quello che ci interessa davvero è il pixel effettivi che indicano il colore. Quindi, con l'aggiunta di quella bandiera,-s 54, quindi siamo in grado di vedere i valori di colore. E non preoccuparti per le bandiere complicate e cose del genere. Nel set di specifiche problema, avrete indicazioni su come utilizzare xxd per visualizzare i pixel. Quindi, se vedete qui, che tipo di aspetto di una scatola verde, questa piccola cosa. Ho un codice colore la 00FF00 fondamentalmente come dire di no blu, un sacco di verde e non rosso. In modo che corrisponda a verde. Come potete vedere qui, si vede un rettangolo verde. Questo rettangolo verde è a soli 3 pixel di larghezza, e allora che cosa dobbiamo fare fare in modo che l'immagine sia un multiplo di 4 larga è aggiungere nella imbottitura extra. E così allora è così che si vede 0s questi qui. Questo sarà effettivamente il risultato del tuo pset Ridimensiona, essenzialmente prendendo la piccola bitmap e poi ingrandendola per 4. E così ciò che vediamo è che in realtà questa immagine è di 12 pixel di larghezza, ma 12 è un multiplo di 4, e quindi in realtà non si vede alcun 0s alla fine perché non abbiamo bisogno di aggiungere qualsiasi perché è completamente imbottito. Essa non ha spazio più. Va bene. Avete domande su imbottitura? Va bene. Cool. Come ho detto prima, le bitmap sono solo una sequenza di byte. E così ciò che abbiamo è invece di aver bisogno di tenere traccia di esattamente quale numero di byte corrisponde ad un elemento specifico, in realtà abbiamo creato una struttura per rappresentare questo. Quindi ciò che abbiamo è una struct RGBTRIPLE. Ogni volta che si dispone di un'istanza di una tripla RGB, perché questo è un tipo di definire struct, allora si può accedere alla variabile rgbtBlue, allo stesso modo le variabili di verde e rosso, che indicano la quantità di blu,, verde e rosso rispettivamente, si ha. Quindi, se abbiamo il set blu variabile a 0, la serie verde per ff, che è il valore massimo che si può avere, e quindi la variabile rosso impostato su 0, allora di che colore sarebbe questo particolare RGB triplice rappresenta? >> [Studente] Verde. Verde. Esattamente. E 'intenzione di essere utile sapere che ogni volta che si dispone di un'istanza di una tripla RGB, si può effettivamente accedere alla quantità di colore - blu, verde e rosso - separatamente. Ora che abbiamo parlato della struttura di questo, diamo uno sguardo al file BMP. Si tratta di strutture realizzate per voi. Qui abbiamo una struttura BITMAPFILEHEADER. Di notevole interesse è la dimensione. In seguito, abbiamo le informazioni nell'intestazione, che ha ancora alcune cose che sono interessanti per noi, cioè la dimensione, la larghezza e l'altezza. Come ci occuperemo in seguito, quando si legge nel file di, si legge automaticamente, perché abbiamo impostato l'ordine di essere la stessa. Così il biSize conterrà i byte giusti che corrispondono alla dimensione effettiva dell'immagine. E poi qui, infine, come abbiamo parlato, abbiamo la struttura RGBTRIPLE typedef. Abbiamo un rgbtBlue, verde e rosso ad esso associati. Grande. Va bene. Ora che abbiamo capito bitmap un po ', capire che abbiamo un file di intestazione e un'intestazione informazioni ad esso associato e poi, dopo che, abbiamo la roba interessante dei colori, ed i colori sono rappresentati da strutture RGBTRIPLE, e quelli, a loro volta, hanno tre valori associati al blu, al verde e al rosso. Così ora, possiamo tipo di pensare di recuperare un po '. Scusi. Pensate Whodunit. Quando abbiamo il nostro file indizio, allora quello che vogliamo fare è leggere ad esso pixel per pixel e quindi in qualche modo cambiare i pixel in modo che siamo in grado di produrre in un formato leggibile. E così per l'output, abbiamo intenzione di scrivere pixel per pixel nel file verdict.bmp. Questo è il tipo di un sacco da fare. Ci rendiamo conto che. Quindi quello che abbiamo fatto è che abbiamo in realtà è dotato di copy.c. Che cosa fa è impossibile fare fa solo una copia esatta di un file bitmap dato e poi lo trasmette. Così si apre già il file per te, legge in pixel per pixel, e poi scrive in in un file di output. Diamo uno sguardo a questo. Questo è garantire un uso corretto, ottenere i nomi dei file qui. Quello che fa è che imposta il file di input di essere quello che abbiamo passato in infile qui, che è il nostro secondo argomento della riga di comando. Controlli per fare in modo che siamo in grado di aprire il file. Verifica che si può fare un nuovo file di output qui. Allora cosa fa qui, solo che inizia soprattutto la lettura per il file bitmap dall'inizio. L'inizio, come si sa, contiene il BITMAPFILEHEADER, e così quelle sequenze di bit sarà direttamente compilare il BITMAPFILEHEADER. Quindi ciò che abbiamo qui sta dicendo che bf BITMAPFILEHEADER - questa è la nostra nuova variabile di tipo BITMAPFILEHEADER - stiamo andando a mettere dentro bf quanto si legge da in puntatore, che è la nostra infile. Quanto leggiamo? Leggiamo in quanti byte abbiamo bisogno di contenere l'intera BITMAPFILEHEADER. Allo stesso modo, questo è quello che facciamo per le informazioni nell'intestazione. Quindi stiamo proseguendo il nostro file in infile, e stiamo leggendo quei bit e byte, e li stiamo collegando direttamente in in questi casi, le variabili che stiamo facendo. Qui stiamo solo facendo in modo che l'immagine bitmap è una bitmap. Ora abbiamo un file di output, giusto? Quindi, così com'è quando si crea, è essenzialmente vuota. Quindi dobbiamo creare fondamentalmente una nuova bitmap da zero. Quello che facciamo è che dobbiamo fare in modo di copiare nel file di intestazione e le informazioni nell'intestazione proprio come il infile ha. Quello che facciamo è che scriviamo - e ricordare che bf è la variabile BITMAPFILEHEADER di tipo, quindi quello che facciamo è che basta utilizzare tale contenuto da scrivere nel file di output. Qui, ricordo che abbiamo parlato di imbottitura, come è importante assicurarsi che la quantità di pixel che abbiamo è un multiplo di 4. Si tratta di una formula molto utile per calcolare la quantità di imbottitura si ha data la larghezza del file. Voglio che voi ragazzi a ricordare che in copy.c abbiamo una formula per il calcolo imbottitura. Va bene? Così tutti ricordo. Grande. E allora cosa fa impossibile fare il prossimo è che itera su tutte le linee di scansione. Si passa attraverso le righe e poi memorizza ogni tripla che si legge scrive e poi nel file di output. Allora qui stiamo leggendo un solo RGB tripla alla volta e poi mettere che tripla stessi nel file di output. La parte difficile è che l'imbottitura non è una tripla RGB, e quindi non può semplicemente leggere tale importo imbottitura di terne RGB. Quello che dobbiamo fare è in realtà solo spostare il nostro indicatore di posizione del file, spostare il nostro cursore, al tipo di saltare tutto l'imbottitura in modo che siamo alla riga successiva. E poi che questo non è copia vi mostra come si potrebbe desiderare di aggiungere l'imbottitura. Proprio per questo abbiamo calcolato quanto imbottitura cui abbiamo bisogno, in modo che significa che abbiamo bisogno di imbottitura numero di 0. Quello che fa è un ciclo for che mette numero imbottitura di 0 nel nostro file di output. E poi, infine, si chiude entrambi i file. Si chiude la infile così come il file di emissione. Ecco, questo è impossibile fare come funziona, e che sta per essere molto utile. Invece di limitarsi a realtà direttamente copiarlo e incollarlo o solo a guardarla e digitando quello che vuoi, si potrebbe semplicemente voler eseguire questo comando nel terminale, cp impossibile fare whodunit.c, che creerà un nuovo file, whodunit.c, che contiene il contenuto esattamente come fa copia. E allora cosa si può fare è utilizzare che come un quadro su cui costruire e modificare per il nostro file di giallo. Queste sono le nostre cose da fare da fare per Whodunit, ma quello che fa impossibile fare è in realtà prende cura della maggior parte di loro per noi. Quindi tutto quello che dobbiamo fare adesso è cambiare i pixel in base alle esigenze per rendere effettivamente il file leggibile. Ricordate che per un dato pixel tripla, quindi per una data variabile di tipo RGBTRIPLE, è possibile accedere ai valori di blu, verde e rosso. Che sta per tornare utile, perché se è possibile accedere, questo significa che si può anche verificare, e questo significa che si può anche cambiare. Così, quando siamo tornati al nostro esempio rosso lente di ingrandimento, in fondo, che agiva come una sorta di filtro per noi. Quindi, quello che vogliamo fare è che vogliamo filtrare tutte le triple che sono provenienti pollici Ci sono diversi modi per farlo. In sostanza, si può avere qualsiasi tipo di filtro che si desidera. Forse si desidera modificare tutti i pixel rossi o forse si desidera modificare un pixel di colore diverso di un colore diverso. Dipende da voi. Ricordate che è possibile verificare il colore del pixel è e poi si può anche cambiare, come si sta passando. Va bene. Ecco, questo è Whodunit. Una volta che si esegue Whodunit, saprete chi è il colpevole del delitto era. Ora stiamo per andare a ridimensionare. Stiamo andando ancora a che fare con le bitmap. Quello che andremo a fare è che stiamo andando ad avere una bitmap di input e poi andremo a passare in un numero e quindi ottenere una bitmap file di output dove questo è fondamentalmente il nostro infile scalato per n. Dire il mio file era solo un pixel di grandi dimensioni. Poi se il mio n è stato di 3, scala da 3, quindi vorrei ripetere che pixel n volte, così 3 volte, e poi anche scala verso il basso 3 volte pure. Così si vede che sto scalando in verticale che in orizzontale. E poi ecco un esempio. Se si dispone di n = 2, si vede che il primo pixel blu si ripete due volte orizzontalmente che verticalmente due volte. E poi, che continua, e così si ha una scala diretta dell'immagine originale per due. Allora se dovessimo dettaglio lo pseudocodice per questo, vogliamo aprire il file. E poi sapere che se torniamo qui, si vede che la larghezza per il file di output sarà diverso rispetto alla larghezza del infile. Che cosa vuol dire? Questo significa che le nostre informazioni di intestazione sta per cambiare. E allora cosa dobbiamo provare a fare è aggiornare le informazioni di intestazione, sapendo che quando si legge nei file se si opera sul quadro impossibile fare, abbiamo già una variabile che indica la dimensione è e cose del genere. Quindi, una volta che hai, quello che si potrebbe desiderare di fare è cambiare le variabili particolari. Ricordate, se si dispone di una struttura, come accedere alle variabili all'interno di quella. Si utilizza l'operatore punto, giusto? Allora con questo, sai che hai bisogno di cambiare le informazioni di intestazione. Così qui è solo un elenco degli elementi reali che stanno per essere la modifica nel file. La dimensione del file sta per cambiare, l'immagine, così come la larghezza e l'altezza. Allora tornando alla mappa delle bitmap, guarda se è l'intestazione del file o l'intestazione info che contiene tali informazioni e quindi modificare come necessario. Anche in questo caso, ad esempio cp impossibile fare resize.c. Ciò significa che resize.c ora contiene tutto quello che è contenuto all'interno di copia copia perché ci fornisce un modo di lettura per ciascun pixel per pixel scanline. Eccetto che ora, invece di cambiare i valori come abbiamo fatto in Whodunit, quello che vogliamo fare è che vogliamo scrivere in più pixel purché il nostro n è maggiore di 1. Poi quello che vogliamo fare è che vogliamo allungare orizzontalmente da n, così come si estendono verticalmente dal n. Come possiamo fare questo? Dite il vostro n è 2 e si ha questa data infile. Il cursore sta per iniziare al primo, e che cosa si vuole fare, se n è 2, si desidera stampare in 2 di questi. Così si stampa in 2 di questi. Poi il cursore sta per passare al pixel successivo, che è quello rosso, e sta andando a stampare 2 di quelle rosse, aggiungendo che su ciò che è fatto prima. Quindi il cursore si sposterà al pixel successivo e disegnare in 2 di questi. Se si guarda indietro al impossibile fare il quadro, cosa fa qui si crea una nuova istanza di un triplo RGB, una nuova variabile chiamata triple. E qui quando si legge in esso, si legge dal 1 infile RGBTRIPLE e lo memorizza all'interno della variabile tripla. Quindi in realtà hanno una variabile che rappresenta quel pixel particolare. Poi, quando si scrive, quello che si potrebbe desiderare di fare è racchiudere l'istruzione fwrite in un ciclo for che scrive nel file di output il numero di volte necessario. Questo è abbastanza semplice. Proprio in fondo ripetere il processo di scrittura n volte di scalare orizzontalmente. Ma dobbiamo ricordare che la nostra imbottitura sta per cambiare. In precedenza, dire che abbiamo avuto qualcosa di lunghezza 3. Poi ci sarebbe solo aggiungere in quanto imbottitura? Solo uno di più per renderlo un multiplo di 4. Ma dire che stiamo scalando questa immagine particolare n = 2. Allora il numero di pixel blu avremmo alla fine? Avremmo 6. 1, 2, 3, 4, 5, 6. Bene. 6 non è un multiplo di 4. Qual è il più vicino multiplo di 4? Che sta per essere 8. Quindi stiamo effettivamente andando ad avere 2 caratteri di padding lì. Qualcuno ricorda se abbiamo una formula per calcolare imbottitura e dove potrebbe essere? [Risposta degli studenti incomprensibile] >> Sì, copy.c. Giusto. C'è una formula impossibile fare a calcolare la quantità di imbottitura si ha data una particolare larghezza dell'immagine bitmap. E allora che sta per essere utile quando è necessario aggiungere una certa quantità di imbottitura per capire effettivamente quanta imbottitura è necessario aggiungere. Ma una nota, però, è che si vuole fare in modo che si sta utilizzando la giusta dimensione. Basta stare attenti perché si sta in fondo andando a che fare con due immagini bitmap. Si vuole fare in modo che si sta utilizzando quella giusta. Quando si sta calcolando l'imbottitura per il file di output, che si desidera utilizzare la larghezza del file di output e non la larghezza della precedente. Grande. Questo tipo di cura si estende una intera immagine bitmap in senso orizzontale. Ma quello che vogliamo fare è in realtà tratto verticale pure. Ciò sta andando essere un po 'più complicato, perché quando abbiamo terminato di copiare una riga e la scrittura di tale riga, il nostro cursore sarà alla fine. Quindi, se si legge di nuovo, allora è solo andando a leggere alla riga successiva. Quindi, quello che vogliamo fare è una specie di trovare il modo di copiare tali righe di nuovo o solo tipo di prendere quella riga e poi riscrivere di nuovo. Come tipo di accennato, ci sono diversi modi per farlo. Che cosa si potrebbe fare è come si sta attraversando e la lettura attraverso la linea di scansione particolare e la modifica, se necessario, quindi tipo di negozio tutti quei pixel in una matrice. Poi, in seguito a sapere che hai bisogno di stampare che ancora l'array, e così si può semplicemente utilizzare tale matrice per farlo. Un altro modo per farlo è che si può copiare in basso di una riga, capire che è necessario copiare di nuovo, quindi in realtà spostare il cursore, e che ha intenzione di utilizzare il metodo di fseek. Si potrebbe spostare il cursore per tutto il tragitto e poi ripetere il processo di copia di nuovo. Quindi, se il nostro numero di scala è n, allora quante volte dobbiamo tornare indietro e riscrivere una linea? >> [Studente] n - 1. >> Si ', perfetto. n - 1. Ce l'abbiamo fatta già una volta, e allora dobbiamo provare a ripetere il processo di tornare indietro n - 1 quantità di volte. Va bene. Così ci avete la funzione di ridimensionamento. Ora siamo in grado di arrivare a una parte davvero divertente, il mio preferito pset, che è Recover. Invece di bitmap, questa volta abbiamo a che fare con file JPEG. Non siamo in realtà in un file solo di JPEG, ci è dato fondamentalmente un formato di scheda di memoria prima. E così questo contiene un po 'di informazioni e valori spazzatura in principio, e poi inizia e ha un sacco di file JPEG. Tuttavia, stiamo consegnata una tessera in cui abbiamo cancellato le foto; in sostanza, abbiamo dimenticato dove le foto si trovano all'interno della carta. Allora il nostro compito in Recuperare è di passare attraverso questo formato carta e trovare quelle immagini di nuovo. Per fortuna, la struttura dei file JPEG e il file di carta è un po 'utile. E 'sicuramente avrebbe potuto essere un po' più complicato se non fosse in questo particolare formato. Ogni file JPEG inizia in realtà con due possibili sequenze, di cui sopra. In pratica, ogni volta che si dispone di un nuovo file JPEG, inizia con la sequenza di FFD8 FFE0 o l'altra, FFD8 ffe1. Un'altra cosa utile da sapere è che i file JPEG sono memorizzati in modo contiguo. Così ogni volta che un file JPEG termina, gli altri si parte. Quindi non vi è alcun tipo di in-tra i valori lì. Una volta raggiunto l'inizio di una JPEG, se hai già letto un JPEG, sai che hai raggiunto la fine della precedente e l'inizio di quello successivo. Per visualizzare questo tipo di, ho fatto uno schema. Un'altra cosa JPEG è che possiamo leggere in sequenze di 512 byte alla volta, analogamente con l'inizio della carta. Non abbiamo bisogno di essere controllando ogni singolo byte perché avrebbe fatto schifo. Così, invece, quello che possiamo fare è in realtà appena letto in 512 byte alla volta e poi, invece di controllare tra quelle in quelle fette piccolo piccolo, possiamo solo controllare l'inizio dei 512 byte. In sostanza, in questo quadro, quello che vedi è all'inizio della carta, si dispone di valori che non sono realmente rilevanti per i file JPEG veri e propri. Ma poi quello che ho è una stella per indicare una delle due sequenze di partenza per un file JPEG. Così ogni volta che vedi una stella, lo sai che hai un file JPEG. E poi ogni file JPEG sta per essere un multiplo di 512 byte ma non necessariamente la stessa multiple. Il modo in cui si sa che hai colpito un altro JPEG è se si colpisce un'altra stella, un'altra sequenza iniziale di byte. Allora quello che abbiamo qui è di avere il file JPEG rosso continuando fino a colpire una stella, che è indicato da un nuovo colore. Si prosegue e poi si preme un'altra stella, che ha colpito un altro JPEG, si continua tutta la strada fino alla fine. Sei in l'ultima immagine qui, quello rosa. Si va fino alla fine fino a colpire il carattere di fine file. Questo sta per essere veramente utile. A pochi takeaway principali qui: Il file di scheda non si avvia con un JPEG, ma una volta JPEG inizia, tutte le immagini JPEG sono memorizzati affiancati l'uno all'altro. Alcuni pseudocodice per il Recupero. In primo luogo, stiamo per aprire il nostro file di carta, e che ha intenzione di utilizzare il nostro file funzioni I / O. Abbiamo intenzione di ripetere il seguente processo finché non avremo raggiunto la fine del file. Stiamo andando a leggere 512 byte alla volta. E quello che ho detto qui è che stiamo andando a memorizzare in un buffer, Quindi, in pratica conservare queste 512 byte finché non sappiamo esattamente cosa fare con loro. Poi quello che vogliamo fare è che vogliamo verificare se abbiamo colpito una stella o meno. Se abbiamo colpito una stella, se abbiamo colpito una delle sequenze di partenza, allora sappiamo che abbiamo raggiunto un nuovo file JPEG. Che cosa dobbiamo provare a fare è che stiamo andando a voler creare un nuovo file nella directory pset4 di continuare a fare quel file. Ma anche, se abbiamo già fatto una prima JPEG, poi vogliamo porre fine a tale file e spingerlo nella cartella pset4, dove avremo il file memorizzato perché se non si specifica che abbiamo finito il file JPEG, poi ci sono fondamentalmente un importo indeterminato. I file JPEG non avrà mai fine. Così vuole fare in modo che, quando stiamo leggendo in un file JPEG e per iscritto che, vogliamo chiudere specificamente che per aprire quella successiva. Noi ti consigliamo di controllare diverse cose. Vogliamo verificare se siamo all'inizio di un nuovo file JPEG con il nostro tampone e anche se abbiamo già trovato una prima JPEG perché che cambierà il processo un po '. Allora dopo si passa attraverso tutto il percorso e si colpisce la fine del file, allora che cosa si vorrà fare è ti consigliamo di chiudere tutti i file che sono attualmente aperti. Questo sarà probabilmente l'ultimo file JPEG che avete, nonché il file della scheda che hai avuto a che fare con. L'ultimo ostacolo che dobbiamo affrontare è come fare in realtà un file JPEG e come in realtà spingere alla cartella. Il pset richiede che ogni JPEG che si trova essere nel formato seguente, dove si ha il numero. jpg. Il numero, anche se è 0, lo chiamiamo 000.jpg. Ogni volta che si trova un JPEG nel programma, si sta andando a voler dare un nome nel modo che ha trovato. Che cosa significa? Abbiamo bisogno di sorta di tenere traccia di quante abbiamo trovato e che il numero di ciascun JPEG dovrebbe essere. Qui stiamo andando a sfruttare la funzione sprintf. Simile a printf, che solo tipo di stampa su un valore nel terminale, sprintf stampa il file nella cartella fuori. E così ciò che questo avrebbe fatto se avessi sprintf, titolo, e quindi la stringa lì, sarebbe stampare 2.jpg. Supponendo che ho chiuso i miei file in modo corretto, che dovrebbe contenere il file che avevo scritto fuori. Ma una cosa è che il codice che ho qui non tutto ciò che soddisfa il pset richiede. Il pset richiede che il secondo file JPEG deve essere denominato 002 invece di 2. Così, quando si stampa il nome, allora forse si potrebbe desiderare di modificare il segnaposto leggermente. Qualcuno ricorda come ci permettono di spazi aggiuntivi quando stampare qualcosa? Gia '. >> [Studente] Hai messo un 3 tra il segno di percentuale e il 2. >> Si ', perfetto. Potrai inserire un 3 in questo caso perché ci vuole spazio per 3. 3d% probabilmente vi darà 002.jpg invece di 2. Il primo argomento nella funzione sprintf è in realtà un array di caratteri, che abbiamo precedentemente conosciuto come stringhe. Quelli volontà, un po 'più simile a un deposito temporaneo, basta memorizzare la stringa risultante. Non sarà davvero a che fare con questo, ma è necessario includerlo. Sapendo che ogni nome di file ha il numero, che occupa tre caratteri, e poi. jpg, per quanto tempo dovrebbe essere questa matrice? Buttate via un numero. Quanti caratteri per il titolo, nel nome? Quindi ci sono tre hashtags, periodo, jpg. >> [Studente] 7. >> 7. Non proprio. Stiamo andando a voler 8 perché vogliamo consentire il terminatore null pure. Infine, solo per tirare fuori il processo che vi ritroverete a fare per recuperare, avete alcune informazioni inizio. Si prosegue fino a trovare l'inizio di un file JPEG, e che può essere una delle due sequenze di partenza. Continui a leggere. Ogni barra qui rappresenta 512 byte. Continui a leggere, continua a leggere fino a quando si incontra un'altra sequenza di partenza. Una volta che avete, si termina l'attuale JPEG - in questo caso, è quello rosso, così si vuole porre fine a tale. Si desidera sprintf il nome di tale nella cartella pset4, poi si vuole aprire un nuovo formato JPEG e poi continuare a leggere fino a quando si verifica il successivo. Continuate a leggere, continuate a leggere, e poi finalmente, alla fine, si sta andando a raggiungere la fine del file, e così si vorrà chiudere l'ultima JPEG che si stava lavorando, sprintf che nella cartella pset4, e poi guardare tutte le immagini che hai ottenuto. Quelle immagini sono in realtà immagini di CS50 personale, e quindi questo è dove la parte divertente bonus del pset è disponibile in è che sono in competizione per le sezioni per trovare i TF nelle immagini e scattare foto con loro per dimostrare che hai fatto il pset e in modo da poter vedere quali sono i membri del personale nelle immagini. Allora si scattano foto con il personale. A volte dovrete inseguire giù. Probabilmente alcuni di loro cercheranno di scappare da te. È scattare foto con loro. Questo è in corso. Non è dovuto quando il pset è dovuto. Il termine sarà annunciato nelle specifiche. Poi, insieme con la sezione, qualunque sia il capitolo prende il maggior numero di immagini con i membri dello staff più vincerà un premio piuttosto impressionante. Questo è il tipo di incentivo per ottenere la vostra pset4 finito il più rapidamente possibile perché allora si può ottenere al lavoro caccia a tutti i diversi membri dello staff CS50. Non è obbligatorio, però, quindi una volta che le immagini, allora avete finito con pset4. E ho finito con Walkthrough 4, quindi grazie a tutti per essere venuti. Buona fortuna con Forensics. [Applausi] [CS50.TV]