[Παίζει μουσική] ZAMYLA CHAN: Ήταν Δεσποινίς Scarlett με το κηροπήγιο. Whodunit; Λοιπόν, θα πάμε να το μάθουμε. Στο Clue επιτραπέζιο παιχνίδι, ίσως να δοθεί μια φυσική κόκκινη εικόνα. Και αυτή η εικόνα είναι πολύ κόκκινο και ανώμαλος, και η δουλειά σας είναι να αποκαλύψει το κρυμμένο μήνυμα. Και συνήθως είστε παρέχεται με ένα κόκκινο μεγεθυντικό φακό, ή μια κόκκινη οθόνη για να αποκαλύπτουν ότι η κρυμμένο μήνυμα. Λοιπόν, θα πάμε να μιμούνται αυτό. Στο αστυνομικό θεατρικό έργο, σας δίνεται μια εικόνα bitmap που μοιάζει πολύ ανώμαλος και κόκκινο, και στη συνέχεια εκτελέστε το πρόγραμμα whodunit για να αποκαλύψει ένα κρυφό μήνυμα. Έτσι, ας σπάσει αυτό σε βήματα. Κατ 'αρχάς, θέλετε να ανοίξετε το αρχείο - η ιδέα που έχετε δώσει. Και στη συνέχεια να δημιουργήσετε επίσης ένα αρχείο bitmap ετυμηγορία. Στη συνέχεια, θέλετε να ενημερώσετε το bitmap header πληροφορίες για την outfile ετυμηγορία. Περισσότερα για αυτό αργότερα. Και τότε θα πάμε να διαβάσετε σε το ιδέα, scanline, pixel προς pixel, αλλάζοντας τα χρώματα pixel ως αναγκαίο, και τη γραφή εκείνες στην ετυμηγορία - pixel προς pixel σε η scanline ετυμηγορία. Πώς μπορούμε να αρχίσει πηγαίνει γι 'αυτό; Καλά, ευτυχώς, έχουμε copy.c στον κώδικα διανομής. Και αυτό πρόκειται να αποδείξει πολύ χρήσιμο για μας. Copy.c ανοίγει ένα αρχείο, διαβάζει ότι header infile του, και στη συνέχεια, ενημερώνει το header outfile του. Και στη συνέχεια να διαβάζει κάθε εικονοστοιχείο στην scanline, pixel προς pixel, και κατόπιν γράφει ότι η pixel στην outfile. Έτσι, το πρώτο σας βήμα θα μπορούσε είναι να εκτελέσετε την ακόλουθη εντολή στο τερματικό - cp copy.c whodunit.c. Αυτό θα δημιουργήσει ένα αντίγραφο του copy.c ονομάζεται whodunit.c. Έτσι, το πρώτο μας βήμα για να ανοίξει το αρχείο, καλά, υπάρχει μια ακριβής αντίγραφο του ότι copy.c. Γι 'αυτό θα σας αφήσει να το εξετάσουμε αυτό. Αυτό που έχουμε να κάνουμε στην παρούσα PSET είναι file I / O, ουσιαστικά λαμβάνοντας αρχεία, την ανάγνωση, τη γραφή, την επεξεργασία τους. Πώς μπορείτε πρώτα να ανοίξετε ένα αρχείο; Λοιπόν, θα πάμε για να δηλώσει ένα αρχείο δείκτη, και στη συνέχεια να καλέσετε το συνάρτηση fopen. Περάστε στη διαδρομή ή το όνομα του εν λόγω αρχείο, και στη συνέχεια η λειτουργία που θέλετε να ανοίξετε το αρχείο μέσα Περνώντας σε ένα r θα ανοίξει foo.bmp για την ανάγνωση. Λαμβάνοντας υπόψη ότι η fopen με το πέρασμα σε μια w θα ανοιχτή bar.bmp, για τη σύνταξη του φακέλου και στην πραγματικότητα επεξεργασία. Έτσι, τώρα που έχουμε ανοίξει το αρχείο, μας το επόμενο βήμα είναι να ενημερώσετε τις πληροφορίες κεφαλίδας για την outfile. Τι είναι μια κεφαλίδα πληροφορίες; Λοιπόν, πρώτα πρέπει να γνωρίζουμε τι είναι bitmap. Ένα bitmap είναι μόνο μια απλή διάταξη των bytes. Και από όπου και αν δηλώνονται σε αυτό το αρχείο εδώ, bmp.h, με μια δέσμη των πληροφορίες για το τι ένα bitmap είναι στην πραγματικότητα κατασκευασμένα από. Αλλά αυτό που πραγματικά νοιάζονται για το κεφαλίδα του αρχείου bitmap, ακριβώς εδώ, και οι πληροφορίες bitmap header, εδώ. Η επικεφαλίδα αποτελείται από ένα ζευγάρι των μεταβλητές που θα αποδειχθεί πολύ χρήσιμη. Υπάρχει biSizeImage, η οποία είναι η συνολικό μέγεθος της εικόνας σε bytes. Και αυτό περιλαμβάνει pixels και padding. Padding είναι πολύ σημαντική, αλλά θα φτάσουμε σε αυτό αργότερα. BiWidth αντιπροσωπεύει το πλάτος της εικόνας σε pixels μείον το παραγέμισμα. BiHeight είναι τότε επίσης το ύψος της εικόνας σε pixels. Και στη συνέχεια το BITMAPFILEHEADER και το BITMAPINFOHEADER, όπως ανέφερα Νωρίτερα, εκείνοι εκπροσωπούνται ως structs. Έτσι, δεν μπορείτε να αποκτήσετε πρόσβαση στο αρχείο κεφαλίδα μόνη της, αλλά θα θελήσετε να πάρετε για να αυτές οι μεταβλητές μέσα. OK. Επομένως, πώς θα ενημερώσετε τις πληροφορίες κεφαλίδας; Λοιπόν, πρώτα θα πρέπει να δούμε αν μπορούμε πρέπει να αλλάξετε οποιαδήποτε πληροφορία από η infile, η ένδειξη, με την outfile, η ετυμηγορία. Είναι κάτι αλλάζει σε αυτή την περίπτωση; Λοιπόν, δεν είναι πραγματικά, γιατί θα πάμε να αλλάζει μόνο τα χρώματα. Εμείς δεν πρόκειται να αλλάξει το αρχείο το μέγεθος, το μέγεθος της εικόνας, το πλάτος, ή το ύψος. Έτσι, είστε εντάξει για τώρα απλά την αντιγραφή κάθε pixel. OK. Έτσι τώρα ας δούμε πώς μπορούμε πραγματικά μπορεί να διαβάσει κάθε pixel από το αρχείο. Ένα άλλο αρχείο I / O λειτουργία θα μπαίνουν στο παιχνίδι - fread. Παίρνει σε ένα δείκτη στο struct η οποία θα περιέχει τα bytes που διαβάζετε. Έτσι διαβάζετε σε αυτό. Και τότε θα περάσει σε ένα μέγεθος, το οποίο είναι το μέγεθος του κάθε στοιχείου που θα θέλετε να διαβάσετε. Εδώ, η sizeof λειτουργία θα έρθει σε πρακτικό. Στη συνέχεια θα περάσει σε αριθμό, τα οποία αντιπροσωπεύει τον αριθμό των στοιχείων του μέγεθος για να το διαβάσετε. Και τελικά, inptr, η οποία είναι ο δείκτης αρχείου που είστε πρόκειται να διαβάσει από. Έτσι, όλα αυτά τα στοιχεία είναι μέσα inptr και θα πάμε στα δεδομένα. Ας δούμε ένα μικρό παράδειγμα. Αν θέλω να διαβάσω σε δεδομένα δύο σκυλιά, καλά, μπορώ να το κάνω με δύο τρόπους. Μπορώ να διαβάσετε είτε σε δύο αντικείμενα μεγέθους σκυλί από inptr μου, ή μπορώ να διαβάσω σε ένα αντικείμενο στο μέγεθος των δύο σκυλιά. Έτσι, θα δείτε ότι ανάλογα με τον τρόπο ότι έχετε κανονίσει το μέγεθος και αριθμό, μπορεί να διαβάσει τον ίδιο αριθμό των bytes. Έτσι τώρα, ας αλλάξουμε το pixel χρώμα, όπως έχουμε ανάγκη. Αν κοιτάξετε bmp.h και πάλι, στη συνέχεια, θα δείτε ότι στο κάτω μέρος RGBTRIPLEs είναι μια άλλη struct, όπου αυτά αποτελούνται από τρία bytes. Ένα, rgbtBlue, rgbtGreen και rgbtRed. Έτσι ώστε κάθε ένα από αυτά αντιπροσωπεύει το ποσό μπλε, η ποσότητα του πράσινου, και το ποσότητα του κόκκινου χρώματος μέσα σε αυτό το pixel, όπου κάθε ποσό που αντιπροσωπεύεται από ένα δεκαεξαδικό αριθμό. Έτσι ff0000 θα είναι ένα μπλε χρώμα, επειδή πηγαίνει από το μπλε, σε πράσινο, κόκκινο. Και τότε όλα f θα είναι λευκό. Ας ρίξουμε μια ματιά σε smiley.bmp, η οποία έχετε στον κώδικα της διανομής σας. Εάν το ανοίξετε σε μόλις μια εικόνα θεατή, τότε θα απλά δείτε ένα κόκκινο smiley. Όμως, λαμβάνοντας μια βαθύτερη κατάδυση σε, θα δείτε ότι η δομή του είναι ακριβώς pixels. Έχουμε λευκά εικονοστοιχεία, και, στη συνέχεια, κόκκινα εικονοστοιχεία. Το λευκό, FFFFFF, και στη συνέχεια όλα τα κόκκινα εικονοστοιχεία έχω χρωματισμένο για σας εδώ, και θα δείτε ότι είναι 0000FF. Μηδέν μπλε, πράσινο μηδέν, και την πλήρη κόκκινο. Και δεδομένου ότι smiley είναι οκτώ pixels πλάτος, δεν έχουμε καμία padding. Εντάξει. Έτσι, εάν επρόκειτο να ορίσετε διαφορετικές τιμές σε RGBTRIPLE και ήθελα να να το κάνει πράσινο, τότε αυτό που θα κάνουμε είναι να Θα ήθελα να δηλώσω RGBTRIPLE, που ονομάζεται τρίκλινα, και στη συνέχεια να έχουν πρόσβαση σε κάθε byte μέσα σε αυτό το struct I Θα χρησιμοποιήσετε τον τελεστή τελεία. Έτσι triple.rgbtBlue, μπορώ εκχωρήσετε ότι στο 0. Πράσινο μπορώ να το αναθέσει σε πλήρη - κάθε αριθμό, πραγματικά, μεταξύ 0 και επόμενα. Και στη συνέχεια, κόκκινο, Είμαι, επίσης, πρόκειται να πω 0. Οπότε αυτό μου δίνει ένα πράσινο pixel. Στη συνέχεια, τι κι αν θέλετε να ελέγξετε η αξία του κάτι; Θα μπορούσα να έχω κάτι που ελέγχει αν η αξία του τριπλού του rgbtBlue είναι ff και στη συνέχεια να εκτυπώσετε, «αισθάνομαι μπλε! ", ως αποτέλεσμα. Τώρα, αυτό δεν σημαίνει κατ 'ανάγκην ότι η pixel είναι μπλε, σωστά; Επειδή πράσινο και κόκκινο αξίες του pixel θα μπορούσαν επίσης να έχουν μη-0 τιμές. Ό, τι αυτό σημαίνει, και όλα αυτά αυτό είναι ο έλεγχος για για μια πλήρη μπλε χρώμα. Αλλά όλα τα εικονοστοιχεία θα μπορούσαν επίσης να έχουν μερική τιμές χρώματος, όπως αυτό επόμενο παράδειγμα εδώ. Είναι λίγο πιο δύσκολο να δείτε τι αυτή η εικόνα είναι τώρα. Αυτό φαίνεται λίγο περισσότερο σαν το clue.bmp ότι θα πρέπει να δοθεί. Τώρα, φυσικά, θα μπορούσε να λύσει αυτό, επειδή υπάρχει μια πολύ κόκκινο, με κρατώντας μια κόκκινη οθόνη για την εικόνα έτσι ότι μπορεί να εμφανιστούν τα άλλα χρώματα. Επομένως, πώς θα μιμούνται αυτό με c; Λοιπόν, θα μπορούσαμε να αφαιρέσετε όλα τα κόκκινα από την εικόνα. Και έτσι να το κάνουμε αυτό θα καθορίζεται κάθε κόκκινο τιμή pixel προς μηδέν. Και έτσι η εικόνα θα δούμε λίγο Κάτι σαν αυτό, όπου δεν έχουμε καμία κόκκινο απολύτως. Μπορούμε να δούμε το κρυφό μήνυμα α λίγο πιο καθαρά τώρα. Είναι άλλο ένα χαμογελαστό πρόσωπο. Ή ίσως θα μπορούσαμε να χρησιμοποιήσουμε μια άλλη μέθοδο. Ίσως, θα μπορούσαμε να διακρίνουμε όλα τα κόκκινα εικονοστοιχεία - δηλαδή, όλα τα εικονοστοιχεία με 0 μπλε, πράσινο 0 και 0 κόκκινο - και να αλλάξετε εκείνα για τα λευκά. Και την εικόνα μας μπορεί να μοιάζει κάτι σαν αυτό. Μια λίγο πιο εύκολο να δούμε. Υπάρχουν πολλοί άλλοι τρόποι για να αποκαλύψει το μυστικό μήνυμα, καθώς, που ασχολούνται με το χειρισμό του χρώματος. Ίσως μπορείτε να χρησιμοποιήσετε μία από τις μεθόδους που ανέφερα παραπάνω. Και επιπλέον, μπορεί να θέλετε να ενισχύσει ορισμένα χρώματα και να φέρει τα έξω. Έτσι, τώρα που έχουμε αλλάξει το pixel το χρώμα, την επόμενη εμείς απλά πρέπει να τα γράψω μέσα στο scanline, pixel προς pixel. Και για άλλη μια φορά, θα θελήσετε να κοιτάξουμε πίσω να copy.c, αν δεν το έχετε αντιγράψει ήδη, και να εξετάσουμε την fwrite λειτουργία, η οποία λαμβάνει τα δεδομένα, ένας δείκτης στο struct που περιέχει το ψηφιολέξεις ότι διαβάζετε από, το μέγεθος της τα στοιχεία, ο αριθμός των τεμαχίων, και στη συνέχεια το outptr - ο προορισμός αυτών των αρχείων. Αφού γράψετε στα pixels, θα είστε πρέπει επίσης να γράψετε στην padding. Τι είναι το υπόστρωμα; Λοιπόν, κάθε pixel rgbt είναι τρία bytes. Όμως, η scanline για μια εικόνα bitmap πρέπει να είναι ένα πολλαπλάσιο των τεσσάρων byte. Και εάν ο αριθμός των pixels που δεν είναι πολλαπλάσιο του τέσσερα, τότε θα πρέπει να προσθέσετε αυτά τα μαξιλαράκια. Padding είναι μόνο εκπροσωπείται από 0s. Έτσι, πώς γράφουμε, ή να διαβάσετε αυτό; Λοιπόν, αποδεικνύεται ότι δεν μπορείτε πραγματικά fread padding, αλλά μπορείτε να υπολογισμό αυτό. Σε αυτή την περίπτωση, η ιδέα και η ετυμηγορία έχουν το ίδιο πλάτος, έτσι ώστε η παραγεμίσματος είναι η ίδια. Και το padding, όπως θα δείτε σε copy.c, υπολογίζεται με τον παρακάτω τύπο - bi.biWidth φορές sizeof (RGBTRIPLE) θα να μας δώσει πόσα bytes το bmp έχει σε κάθε γραμμή. Από εκεί, οι modulos και αφαιρέσεις με 4 μπορεί να υπολογίσει πόσο πρέπει να προστεθεί ο αριθμός των bytes, έτσι ώστε το πολλαπλάσιο των bytes για κάθε σειρά είναι τέσσερις. Τώρα που έχουμε τον τύπο για πόση πλήρωση χρειαζόμαστε, τώρα μπορούμε να το γράψω. Τώρα, ανέφερα και πριν, padding είναι μόνο 0s. Έτσι, στην περίπτωση αυτή, είμαστε απλά βάζοντας μια χαρα, σε αυτή την περίπτωση ένα 0, σε μας outptr - outfile μας. Έτσι ώστε να μπορεί να είναι μόνο fputc 0, κόμμα outptr. Έτσι, ενώ έχουμε διαβάσει σε μας αρχείων, file I / O έχει παρακολουθημένη μας θέση σε αυτά τα αρχεία με κάτι καλείται ο δείκτης θέσης αρχείου. Σκεφτείτε το σαν ένα δρομέα. Βασικά, προχωρεί κάθε φορά ότι Fread, αλλά έχουμε ελέγχουν πάνω από αυτό, πάρα πολύ. Για να μετακινήσετε το δείκτη θέσης αρχείου, μπορείτε να χρησιμοποιήσετε τη λειτουργία fseek. Όταν η inptr αντιπροσωπεύει το αρχείο δείκτη που αναζητάτε μέσα, το ποσότητα είναι ο αριθμός των bytes που θα θέλετε να μετακινήσετε το δρομέα, και στη συνέχεια από σχετίζεται με το σημείο αναφοράς από όπου βρίσκεται ο δρομέας. Αν περάσει SEEK_CUR, ότι αντιπροσωπεύει την τρέχουσα θέση στο αρχείο. Ή μπορείτε να χρησιμοποιήσετε κάποιες άλλες παραμέτρους. Έτσι, θα μπορούσαμε να θέλετε να χρησιμοποιήσετε fseek να παρακάμψετε πάνω από την επενδυτική πλήρωση του αρχείο σε μορφή. Και πάλι, αν είστε κολλημένοι, υπάρχει ένα παράδειγμα ότι στην copy.c. Έτσι τώρα έχουμε ανοίξει το αρχείο, η ιδέα, και η ετυμηγορία. Έχουμε ενημερωθεί τις πληροφορίες κεφαλίδας για ετυμηγορία μας, γιατί κάθε bitmap χρειάζεται μια κεφαλίδα. Έχουμε στη συνέχεια, διαβάστε στην ιδέα του scanline, pixel προς pixel, αλλάζοντας κάθε χρώμα ανάλογα με τις ανάγκες, και γραπτώς σε εκείνα τα ετυμηγορία, pixel προς pixel. Μόλις ανοίξετε την ετυμηγορία, μπορείτε να δείτε ποιος ο ένοχος, ή ποιο είναι το μυστικό μήνυμα. Το όνομά μου είναι Zamyla, και αυτό ήταν whodunit.