[MUSIC CHƠI] ZAMYLA CHAN: Đó là Hoa hậu Scarlett với nến. Whodunit? Vâng, chúng ta sẽ tìm hiểu. Trong các trò chơi hội đồng quản trị Clue, bạn có thể được cung cấp một hình ảnh màu đỏ vật lý. Và hình ảnh đó là rất đỏ và chắp vá, và việc của bạn là tiết lộ thông điệp ẩn. Và thường là bạn đang cung cấp với một màu đỏ kính lúp, hoặc một màn hình màu đỏ để tiết lộ rằng thông điệp ẩn. Vâng, chúng ta sẽ bắt chước đó. Trong whodunit, bạn sẽ được một hình ảnh bitmap trông rất chắp vá và đỏ, và sau đó chạy chương trình whodunit để lộ ra một thông điệp ẩn. Vì vậy, chúng ta hãy phá vỡ này thành các bước. Trước tiên, bạn muốn mở tập tin - đầu mối mà bạn đã được đưa ra. Và sau đó cũng tạo ra một tập tin bitmap phán quyết. Sau đó, bạn muốn cập nhật các bitmap tiêu đề thông tin cho các outfile phán quyết. Thêm về điều này sau. Và sau đó bạn sẽ đọc vào đầu mối, scanline, từng pixel, thay đổi màu sắc điểm ảnh như cần thiết, và viết những thành phán quyết - pixel vào phán quyết scanline. Làm thế nào để chúng tôi bắt đầu đi về điều này? Vâng, may mắn, chúng tôi có copy.c trong mã phân phối. Và điều này sẽ chứng minh khá hữu ích cho chúng tôi. Copy.c mở một tập tin, đọc trong đó tiêu đề infile, và sau đó cập nhật tiêu đề của outfile. Và sau đó nó đọc từng điểm ảnh trong scanline, từng pixel, và sau đó viết pixel vào outfile. Vì vậy, bước đầu tiên của bạn có thể để chạy sau lệnh trong thiết bị đầu cuối - cp copy.c whodunit.c. Điều này sẽ tạo ra một bản sao của copy.c tên whodunit.c. Vì vậy, bước đầu tiên của chúng tôi để mở tập tin, tốt, có một chính xác bản sao về điều đó trong copy.c. Vì vậy tôi sẽ để lại cho bạn để nhìn vào đó. Những gì chúng tôi đang làm việc với trong PSET này tập tin I / O, về cơ bản dùng các tập tin, đọc, viết, chỉnh sửa chúng. Làm thế nào để lần đầu tiên bạn mở một tập tin? Vâng, bạn sẽ khai báo một tập tin con trỏ, và sau đó bạn gọi chức năng fopen. Vượt qua trong đường dẫn, hoặc tên của tập tin, và sau đó là chế độ mà bạn muốn để mở tập tin đó in Đi qua trong một r sẽ mở foo.bmp để đọc. Trong khi fopen với đi qua trong một w sẽ mở bar.bmp, để viết các tập tin và thực sự chỉnh sửa nó. Vì vậy, bây giờ mà chúng tôi đã mở các tập tin, chúng tôi Bước tiếp theo là để cập nhật các thông tin tiêu đề cho outfile. Một thông tin tiêu đề là gì? Vâng, đầu tiên chúng ta cần biết những gì một bitmap là. Một ảnh bitmap chỉ là một đơn giản sắp xếp các byte. Và chúng được khai báo trong tập tin này ở đây, bmp.h, với một loạt các thông tin về những gì một bitmap thực sự làm ra. Nhưng những gì chúng ta thực sự quan tâm là phần đầu tập tin bitmap, ngay tại đây, và các thông tin tiêu đề bitmap, trên đây. Tiêu đề bao gồm một vài biến mà sẽ chứng minh rất hữu ích. Có biSizeImage, đó là tổng kích thước của hình ảnh trong byte. Và điều này bao gồm các điểm ảnh và padding. Đệm là rất quan trọng, nhưng chúng tôi sẽ nhận được điều này sau. BiWidth đại diện cho chiều rộng của hình ảnh theo pixel trừ đi padding. BiHeight là sau đó cũng là chiều cao của hình ảnh theo pixel. Và sau đó là BITMAPFILEHEADER và BITMAPINFOHEADER, như tôi đã đề cập trước đó, những người được đại diện như cấu trúc. Vì vậy, bạn không thể truy cập các tập tin tiêu đề chính nó, nhưng bạn sẽ muốn có được để các biến bên trong. OK. Vì vậy, làm thế nào để chúng tôi cập nhật các thông tin tiêu đề? Vâng, đầu tiên chúng ta phải xem liệu chúng tôi cần phải thay đổi bất kỳ thông tin từ các infile, các đầu mối, đến outfile, phán quyết. Được bất cứ điều gì thay đổi trong trường hợp này? Vâng, không thực sự, bởi vì chúng ta sẽ được chỉ cần thay đổi màu sắc. Chúng tôi sẽ không được thay đổi các tập tin kích thước, kích thước hình ảnh, chiều rộng, hoặc chiều cao. Vì vậy, bạn không sao bây giờ bằng chỉ cần sao chép mỗi điểm ảnh. OK. Vì vậy, bây giờ chúng ta hãy xem làm thế nào chúng ta thực sự có thể đọc tất cả các điểm ảnh từ tập tin. Một tập tin tôi O chức năng / sẽ đi vào chơi - fread. Nó có trong một con trỏ đến cấu trúc sẽ chứa các byte bạn đang đọc. Vì vậy, bạn đang đọc vào đó. Và sau đó bạn vượt qua trong một kích thước, đó là kích thước của từng yếu tố mà bạn muốn đọc. Ở đây, hàm sizeof sẽ có ích. Sau đó, bạn vượt qua về số lượng, mà đại diện cho số phần tử của kích thước để đọc. Và cuối cùng, inptr, đó là con trỏ tập tin mà bạn sẽ đọc từ. Vì vậy, tất cả những yếu tố này là bên trong inptr và họ sẽ dữ liệu. Hãy xem xét một ví dụ nhỏ. Nếu tôi muốn đọc dữ liệu vào hai con chó, tốt, tôi có thể làm điều đó một trong hai cách. Tôi hoặc là có thể đọc trong hai đối tượng có kích thước con chó từ inptr của tôi, hoặc tôi có thể đọc trong một đối tượng kích thước của hai con chó. Vì vậy, bạn thấy rằng tùy thuộc vào cách mà bạn sắp xếp kích thước và số, bạn có thể đọc trong cùng số byte. Vì vậy, bây giờ, chúng ta hãy thay đổi màu của điểm ảnh như chúng ta cần. Nếu bạn nhìn vào bmp.h một lần nữa, sau đó bạn sẽ thấy rằng ở phía dưới RGBTRIPLEs là cấu trúc khác, nơi họ bao gồm ba byte. Một, rgbtBlue, rgbtGreen, và rgbtRed. Vì vậy, mỗi đại diện cho số tiền màu xanh, số lượng màu xanh lá cây, và số lượng điểm ảnh màu đỏ bên trong này, nơi mỗi số được đại diện bởi một số thập lục phân. Vì vậy, ff0000 sẽ là một màu xanh, vì nó đi từ màu xanh, màu xanh lá cây, màu đỏ. Và sau đó tất cả các e sẽ có màu trắng. Chúng ta hãy nhìn vào smiley.bmp, mà bạn có trong mã phân phối của bạn. Nếu bạn mở nó chỉ trong một hình ảnh người xem, sau đó bạn sẽ chỉ nhìn thấy một mặt cười màu đỏ. Nhưng việc lặn sâu hơn trong, chúng tôi sẽ thấy rằng cấu trúc của nó chỉ là pixel. Chúng tôi có điểm ảnh màu trắng, và sau đó các điểm ảnh màu đỏ. Màu trắng, ffffff, và sau đó tất cả các pixel màu đỏ tôi đã có màu cho bạn ở đây, bạn sẽ thấy rằng họ đang 0000FF. Không xanh, không xanh, và đầy đủ màu đỏ. Và kể từ khi cười là tám điểm ảnh, chúng tôi không có bất kỳ padding. Được rồi. Vì vậy, nếu tôi được là để gán các giá trị khác nhau một RGBTRIPLE và tôi muốn làm cho nó màu xanh lá cây, sau đó những gì tôi sẽ làm là Tôi sẽ khai báo một RGBTRIPLE, được đặt tên ba, và sau đó truy cập vào tất cả các byte trong đó cấu trúc tôi sẽ sử dụng các dấu chấm. Vì vậy, triple.rgbtBlue, tôi có thể gán là 0. Màu xanh lá cây tôi có thể gán nó cho đầy đủ - bất kỳ số lượng, thực sự, giữa 0 và ff. Và sau đó màu đỏ, tôi cũng sẽ nói 0. Vì vậy, sau đó cung cấp cho tôi một điểm ảnh màu xanh lá cây. Tiếp theo, những gì nếu tôi muốn kiểm tra giá trị của một cái gì đó? Tôi có thể có một cái gì đó để kiểm tra dù rgbtBlue giá trị của ba là ff và sau đó in, "Tôi cảm thấy màu xanh! ", như một kết quả. Bây giờ, điều đó không nhất thiết có nghĩa rằng các điểm ảnh màu xanh, phải không? Bởi vì giá trị màu xanh lá cây và màu đỏ của điểm ảnh cũng có thể có giá trị không 0. Tất cả những điều này có nghĩa, và tất cả những gì điều này được kiểm tra là cho một màu xanh đầy đủ. Nhưng tất cả các điểm ảnh cũng có thể có một phần giá trị màu, như thế này Ví dụ tiếp theo đây. Đó là một chút khó khăn hơn để xem những gì hình ảnh này bây giờ. Điều này có vẻ hơn một chút như clue.bmp rằng bạn sẽ được đưa ra. Bây giờ, về thể chất, bạn có thể giải quyết điều này, bởi vì có rất nhiều màu đỏ, bởi nắm giữ lên một màn hình màu đỏ to hình ảnh rằng các màu sắc khác có thể xuất hiện. Vì vậy, làm thế nào để chúng ta bắt chước này với c? Vâng, chúng ta có thể loại bỏ tất cả màu đỏ từ hình ảnh hoàn toàn. Và do đó, để làm được điều đó, chúng tôi muốn thiết lập mỗi giá trị điểm ảnh màu đỏ là 0. Và do đó hình ảnh sẽ xem xét một chút bit như thế này, nơi mà chúng tôi không có màu đỏ nào. Chúng ta có thể nhìn thấy thông báo ẩn một chút rõ ràng hơn bây giờ. Đó là một khuôn mặt cười. Hoặc có lẽ chúng ta có thể sử dụng phương pháp khác. Có lẽ, chúng ta có thể xác định tất cả các điểm ảnh màu đỏ - có nghĩa là, tất cả các điểm ảnh với 0 màu xanh, màu xanh lá cây 0, 0 và đỏ - và thay đổi những thành màu trắng. Và hình ảnh của chúng tôi có thể trông một cái gì đó như thế này. Một chút dễ dàng hơn để xem. Có rất nhiều cách khác để khám phá các thông điệp bí mật là tốt, đối phó với các thao tác màu sắc. Có lẽ bạn có thể sử dụng một trong những phương pháp mà tôi đã đề cập ở trên. Và ngoài ra, bạn có thể muốn để nâng cao một số màu sắc và mang lại cho những người ra. Vì vậy, bây giờ mà chúng tôi đã thay đổi các điểm ảnh màu sắc, tiếp theo chúng ta chỉ cần viết chúng vào các scanline, từng pixel. Và một lần nữa, bạn sẽ muốn nhìn lại để copy.c, nếu bạn không sao chép nó đã có, và nhìn vào fwrite chức năng, trong đó có dữ liệu, một con trỏ để các cấu trúc có chứa các byte mà bạn đang đọc từ, kích thước của các mặt hàng, số lượng mặt hàng, và sau đó là outptr - điểm đến của các tập tin. Sau khi bạn viết trong các điểm ảnh, bạn sẽ cũng phải viết trong đệm. Đệm là gì? Vâng, mỗi điểm ảnh rgbt dài ba byte. Tuy nhiên, scanline cho một hình ảnh bitmap có phải là một bội số của bốn byte. Và nếu số lượng điểm ảnh không phải là một bội số của bốn, sau đó chúng ta cần thêm bổ sung này. Đệm chỉ được đại diện bởi số 0. Vì vậy, làm thế nào để chúng tôi viết, hoặc đọc này? Vâng, nó chỉ ra rằng bạn có thể không đệm thực sự fread, nhưng bạn có thể tính toán nó. Trong trường hợp này, các đầu mối và bản án có cùng một chiều rộng, do đó, đệm là như nhau. Và đệm, như bạn sẽ thấy trong copy.c, được tính với công thức dưới đây - bi.biWidth lần sizeof (RGBTRIPLE) sẽ cho chúng ta bao nhiêu byte bmp có trong mỗi hàng. Từ đó, modulos và bớt với 4 có thể tính toán như thế nào nhiều byte phải được bổ sung để bội số của byte trên mỗi hàng là bốn. Bây giờ chúng ta có công thức bao nhiêu đệm chúng ta cần, bây giờ chúng ta có thể viết nó. Bây giờ, tôi đã đề cập trước đây, đệm chỉ là số 0. Vì vậy, trong trường hợp đó, chúng ta chỉ cần đặt một char, trong trường hợp này là 0, chúng tôi outptr - outfile của chúng tôi. Vì vậy, đó chỉ có thể được fputc 0, dấu phẩy outptr. Vì vậy, trong khi chúng tôi đã được đọc vào chúng tôi tập tin, tập tin I / O đã lưu giữ theo dõi của chúng tôi vị trí trong các tập tin với một cái gì đó được gọi là chỉ báo vị trí tập tin. Nghĩ về nó như một con trỏ. Về cơ bản, nó tiến bộ mỗi khi mà chúng ta fread, nhưng chúng tôi có kiểm soát nó, quá. Để di chuyển các tập tin chỉ báo vị trí, bạn có thể sử dụng chức năng fseek. Nơi inptr đại diện cho các tập tin con trỏ mà bạn đang tìm kiếm trong, các số tiền là số byte mà bạn muốn di chuyển con trỏ, và sau đó từ liên quan đến các điểm tham chiếu từ nơi con trỏ chuột của bạn. Nếu bạn vượt qua trong SEEK_CUR, mà đại diện cho hiện tại vị trí trong tập tin. Hoặc bạn có thể sử dụng một số thông số khác. Vì vậy, chúng ta có thể muốn sử dụng fseek để bỏ qua trên miếng đệm của các tập tin trong. Và một lần nữa, nếu bạn đang bị mắc kẹt, có một ví dụ về điều đó trong copy.c. Vì vậy, bây giờ chúng tôi đã mở các tập tin, đầu mối, và phán quyết. Chúng tôi đã cập nhật các thông tin tiêu đề cho bản án của chúng tôi, bởi vì mỗi bitmap cần một tiêu đề. Sau đó chúng tôi đã đọc vào đầu mối của scanline, từng pixel, thay đổi mỗi màu khi cần thiết, và viết những vào bản án, từng pixel. Một khi bạn mở bản án, bạn có thể xem ai thủ phạm, hoặc những gì bí mật thông điệp. Tên tôi là Zamyla, và này là whodunit.