Bersedia untuk bekerja
Seperti biasa, mula-mula buka tetingkap terminal dan jalankan arahan.update50
untuk memastikan permohonan anda sudah dikemas kini. Sebelum anda memulakan, ikuti ini cd ~ / workspace
wget http://cdn.cs50.net/2015/fall/psets/4/pset4/pset4.zip
untuk memuat turun arkib ZIP tugas ini. Sekarang jika anda menjalankan ls anda akan melihat bahawa anda mempunyai fail yang dipanggil pset4.zip dalam direktori ~/workspace anda . Ekstraknya menggunakan arahan: Jika anda menjalankan unzip pset4.zip
perintah ls sekali lagi , anda akan melihat bahawa direktori lain telah muncul. Kini anda boleh memadam fail zip seperti yang ditunjukkan di bawah: rm -f pset4.zip
Mari buka direktori pset4 cd pset4
, jalankan ls , dan pastikan direktori tersebut mengandungi bmp / jpg / questions.txt
whodunit atau "Siapa yang melakukan ini?"
Jika anda pernah melihat desktop Windows XP lalai (https://en.wikipedia.org/wiki/Bliss_(image)) (bukit dan langit biru), maka anda telah melihat BMP. Pada halaman web, kemungkinan besar anda telah melihat GIF. Pernahkah anda melihat foto digital? Jadi, kami gembira melihat JPEG. Jika anda pernah mengambil tangkapan skrin pada Mac, kemungkinan besar anda telah melihat PNG. Baca di Internet tentang format BMP, GIF, JPEG, PNG dan jawab soalan ini:-
Berapa banyak warna yang setiap format menyokong?
-
Format mana yang menyokong animasi?
-
Apakah perbezaan antara pemampatan lossy dan lossless?
-
Manakah antara format ini menggunakan pemampatan lossy?
-
Apakah yang berlaku dari sudut teknikal apabila fail dipadamkan dalam sistem fail FAT?
-
Apakah yang boleh dilakukan untuk memastikan (dengan kebarangkalian yang tinggi) bahawa fail yang dipadam tidak dapat dipulihkan?
xxd -c 24 -g 3 -s 54 smiley.bmp
Anda harus melihat apa yang ditunjukkan di bawah; Kami telah menyerlahkan lagi dengan warna merah semua contoh 0000ff. Dalam imej dalam lajur paling kiri anda boleh melihat alamat dalam fail, yang bersamaan dengan offset daripada bait pertama fail. Kesemuanya diberikan dalam sistem nombor heksadesimal. Jika kita menukar perenambelasan 00000036 kepada perpuluhan, kita mendapat 54. Jadi anda sedang melihat bait ke-54 daripada smiley.bmp . Ingat bahawa dalam fail BMP 24-bit, 14 + 40 = 54 bait pertama diisi dengan metadata. Jadi, jika anda ingin melihat metadata, jalankan arahan berikut: xxd -c 24 -g 3 smiley.bmp
Jika smiley.bmp mengandungi aksara ASCII , kami akan melihatnya di lajur paling kanan dalam xxd dan bukannya semua titik tersebut. Jadi, smiley ialah BMP 24-bit (setiap piksel diwakili oleh 24 ÷ 8 = 3 bait) dengan saiz (resolusi) 8x8 piksel. Oleh itu, setiap baris (atau "Scanline" dipanggil) mengambil (8 piksel) x (3 bait setiap piksel) = 24 bait. Nombor ini ialah gandaan empat, dan ini penting kerana fail BMP disimpan sedikit berbeza jika bilangan bait dalam baris bukan gandaan empat. Jadi, dalam small.bmp, satu lagi fail BMP 24-bit dalam folder kami, anda boleh melihat kotak hijau 3x3 piksel. Jika anda membukanya dalam pemapar imej, anda akan melihat bahawa ia menyerupai imej yang ditunjukkan di bawah, hanya bersaiz lebih kecil. Oleh itu, setiap baris dalam small.bmp menduduki (3 piksel) × (3 bait setiap piksel) = 9 bait, yang bukan gandaan 4. Untuk mendapatkan panjang baris yang gandaan 4, ia berlapik dengan sifar tambahan: antara 0 dan 3 bait kami mengisi setiap baris dalam format BMP 24-bit (bolehkah anda meneka mengapa demikian?). Untuk small.bmp , 3 bait sifar diperlukan, memandangkan (3 piksel) x (3 bait setiap piksel) + (3 bait padding) = 12 bait, yang sebenarnya merupakan gandaan 4. Untuk "melihat" padding ini, lakukan perkara berikut. xxd -c 12 -g 3 -s 54 small.bmp
Ambil perhatian bahawa kami menggunakan nilai yang berbeza untuk -c berbanding dengan smiley.bmp , jadi xxd hanya mengeluarkan 4 lajur kali ini (3 untuk petak hijau dan 1 untuk padding). Untuk kejelasan, kami telah menyerlahkan semua kejadian 00ff00 dalam warna hijau. Sebagai kontras, mari gunakan xxd untuk fail large.bmp . Ia kelihatan sama persis dengan small.bmp, hanya resolusinya ialah 12x12 piksel, iaitu empat kali lebih besar. Jalankan arahan di bawah. Anda mungkin perlu mengembangkan tetingkap untuk mengelakkan pemindahan. xxd -c 36 -g 3 -s 54 large.bmp
Anda akan melihat sesuatu seperti ini: Sila ambil perhatian, tiada penyelewengan dalam BMP ini! Lagipun, (12 piksel) × (3 bait setiap piksel) = 36 bait, dan ini adalah gandaan 4. Editor hex xxd menunjukkan kepada kami bait dalam fail BMP kami. Bagaimanakah kita boleh mendapatkannya secara pemrograman? Dalam copy.c terdapat satu program yang tujuan utamanya dalam hidup adalah untuk mencipta salinan BMP, sekeping demi sekeping. Ya, anda boleh menggunakan cp untuk ini . Walau bagaimanapun, cp tidak akan dapat membantu En Boddy. Harap copy.c melakukan ini, jadi begini: ./copy smiley.bmp copy.bmp
Jika anda sekarang menjalankan ls (dengan bendera yang sesuai), anda akan melihat smiley.bmp dan copy.bmp sememangnya mempunyai saiz yang sama. Mari kita semak semula sama ada ini benar? diff smiley.bmp copy.bmp
Jika arahan ini tidak memaparkan apa-apa pada skrin, ini bermakna fail itu sememangnya sama (penting: sesetengah program, seperti Photoshop, menyertakan sifar tertinggal di hujung beberapa VMP. Versi salinan kami membuangnya, jadi jangan bimbang jika sekiranya anda menyalin BMP lain yang telah anda muat turun atau cipta untuk ujian, salinan itu akan menjadi beberapa bait lebih kecil daripada yang asal). Anda boleh membuka kedua-dua fail dalam pemapar imej Ristretto (klik dua kali) untuk mengesahkan ini secara visual. Tetapi diff melakukan perbandingan bait demi bait ini, jadi penglihatannya lebih tajam daripada anda! Bagaimanakah salinan ini dicipta? Ternyata copy.c berkaitan dengan bmp.h . Mari pastikan: buka bmp.h. Di sana anda akan melihat takrifan sebenar pengepala yang telah kami nyatakan, disesuaikan daripada pelaksanaan Microsoft sendiri. Selain itu, fail ini mentakrifkan jenis data BYTE, DWORD, LONG dan WORD, yang merupakan jenis data yang biasanya ditemui dalam dunia pengaturcaraan Win32 (iaitu, Windows). Ambil perhatian bahawa ini pada dasarnya adalah alias untuk primitif yang anda (semoga) sudah biasa dengannya. Ternyata BITMAPFILEHEADER dan BITMAPINFOHEADER telah menggunakan jenis ini. Fail ini juga mentakrifkan struct yang dipanggil RGBTRIPLE. Ia "merangkum" tiga bait: satu biru, satu hijau dan satu merah (ini adalah susunan di mana kita akan mencari kembar tiga RGB pada cakera). Bagaimanakah struct ini berguna? Untuk meringkaskan, fail hanyalah jujukan bait (atau akhirnya bit) pada cakera. Walau bagaimanapun, bait ini biasanya dipesan supaya beberapa yang pertama mewakili sesuatu, kemudian yang berikutnya mewakili sesuatu yang lain, dan seterusnya. "Format" fail wujud kerana kami mempunyai piawaian, atau peraturan, yang mentakrifkan maksud bait. Sekarang, kita hanya boleh membaca fail dari cakera ke dalam RAM sebagai satu tatasusunan bait besar. Dan kita ingat bahawa bait pada kedudukan [i] mewakili satu perkara, manakala bait pada kedudukan [j] adalah sesuatu yang lain. Tetapi mengapa tidak berikan beberapa nama bait ini supaya kita boleh mendapatkannya dengan lebih mudah daripada ingatan? Ini adalah apa yang struktur dalam bmp.h membantu kami. Daripada memikirkan fail sebagai satu jujukan bait yang panjang, kami melihatnya dipecahkan kepada blok yang lebih mudah difahami - jujukan struktur. Ingat bahawa smiley.bmp mempunyai resolusi 8x8 piksel, jadi ia memerlukan 14 + 40 + (8 × 8) × 3 = 246 bait pada cakera (anda boleh menyemak ini menggunakan arahan ls). Begini rupanya pada cakera menurut Microsoft: Kami dapat melihat bahawa pesanan itu penting apabila ia melibatkan ahli struct. Byte 57 ialah rgbtBlue (bukan, katakan, rgbtRed) kerana rgbtBlue ditakrifkan dalam RGBTRIPLE dahulu. Ngomong-ngomong, penggunaan atribut padak kami memastikan bahawa dentang tidak cuba "menjajarkan perkataan" ahli (dengan alamat bait pertama setiap ahli ialah gandaan 4), supaya kami tidak berakhir dengan lubang dalam struktur kami yang tidak wujud pada cakera sama sekali. Jom teruskan. Cari URL yang sepadan dengan BITMAPFILEHEADER dan BITMAPINFOHEADER, mengikut ulasan dalam bmp.h. Perhatian, saat yang hebat: anda mula menggunakan MSDN (Rangkaian Pembangun Microsoft)! Daripada menatal lebih jauh melalui copy.c , jawab beberapa soalan untuk memahami cara kod tersebut berfungsi. Seperti biasa, arahan lelaki adalah kawan sejati anda, dan kini juga MSDN. Jika anda tidak tahu jawapannya, Google dan fikirkan. Anda juga boleh merujuk kepada fail stdio.h di https://reference.cs50.net/.
-
Tetapkan titik putus dalam utama (dengan mengklik di sebelah kiri pembaris dengan nombor baris utama).
-
Dalam tab terminal , pergi ke ~/workspace/pset4/bmp , dan susun copy.c ke dalam atur cara salin menggunakan make.
-
Jalankan debug50 copy smiley.bmp copy.bmp , ini akan membuka panel debugger di sebelah kanan.
-
Berjalan melalui program langkah demi langkah menggunakan panel di sebelah kanan. Nota bf dan bi . Dalam ~/workspace/pset4/questions.txt , jawab soalan:
-
Apakah stdint.h ?
-
Apakah gunanya menggunakan uint8_t , uint32_t , int32_t dan uint16_t dalam program?
-
Berapakah bilangan bait yang masing-masing mengandungi BYTE , DWORD , LONG dan WORD (Dengan mengandaikan seni bina 32-bit)?
- Apakah (ASCII, perpuluhan atau perenambelasan) sepatutnya dua bait pertama fail BMP? (bait utama, yang digunakan untuk mengenal pasti format fail (dengan kebarangkalian tinggi) sering dipanggil "nombor ajaib").
-
Apakah perbezaan antara bfSize dan biSize?
-
Apakah maksud biHeight negatif?
-
Medan manakah dalam BITMAPINFOHEADER mentakrifkan kedalaman warna dalam BMP (iaitu bit setiap piksel)?
-
Mengapa fungsi fopen boleh mengembalikan NULL dalam copy.c 37?
-
Mengapa hujah ketiga untuk fread dalam kod kami sama dengan 1?
-
Apakah nilai dalam copy.c 70 mentakrifkan padding jika bi.biWidth ialah 3?
-
Apa yang fseek lakukan?
-
Apakah SEEK_CUR?
Kembali kepada Encik Boddy. Senaman:
Tulis program yang dipanggil whodunit dalam fail yang dipanggil whodunit.c yang menunjukkan lukisan Encik Boddy. Hmmmm, apa? Seperti salinan, program mesti mengambil tepat dua argumen baris arahan, dan jika anda menjalankan program anda seperti yang ditunjukkan di bawah, hasilnya akan disimpan dalam verdict.bmp, di mana lukisan En. Boddy tidak akan bising../whodunit clue.bmp verdict.b
Biar kami cadangkan anda akan mula menyelesaikan misteri ini dengan menjalankan arahan di bawah. cp copy.c whodunit.c
Anda mungkin kagum dengan berapa banyak baris kod yang anda perlu tulis untuk membantu En. Boddy. Tiada apa-apa yang tidak perlu disembunyikan dalam smiley.bmp , jadi jangan ragu untuk menguji atur cara pada fail ini. Ia kecil, dan anda boleh membandingkan output program anda dan output xxd semasa pembangunan (atau mungkin ada sesuatu yang tersembunyi dalam smiley.bmp ? Sebenarnya, tidak). Dengan cara ini, masalah ini boleh diselesaikan dengan cara yang berbeza. Sebaik sahaja anda mengenal pasti lukisan Encik Boddy, dia akan berehat dengan tenang. Memandangkan whodunit boleh dilaksanakan dalam pelbagai cara, anda tidak akan dapat menyemak ketepatan pelaksanaan dengan check50 . Dan biarkan ia merosakkan keseronokan anda, tetapi penyelesaian pembantu juga tidak tersedia untuk masalah whodunit . Akhir sekali, dalam fail Dalam ~/workspace/pset4/questions.txt , jawab soalan berikut: Whodunit? //ктоэтосделал?
ubah saiz
Nah, sekarang - ujian seterusnya! Mari kita tulis atur cara yang dipanggil resize in resize.c . Ia akan mengubah saiz imej BMP 24-bit yang tidak dimampatkan dalam langkah n. Aplikasi anda mesti menerima tepat tiga argumen baris arahan, dengan yang pertama (n) ialah integer tidak lebih daripada 100, yang kedua ialah nama fail yang akan diubah suai dan yang ketiga ialah nama versi yang disimpan bagi yang diubah suai fail.Usage: ./resize n infile outfile
Dengan program sedemikian, kita boleh mencipta large.bmp daripada small.bmp dengan mengubah saiz yang terakhir dengan 4 (iaitu, mendarab kedua-dua lebar dan tinggi dengan 4), seperti yang ditunjukkan di bawah. Untuk memudahkan, anda boleh memulakan tugas dengan menyalin copy.c./resize 4 small.bmp large.bmp
sekali lagi dan menamakan salinan resize.c . Tetapi pertama-tama, tanya diri anda dan jawab soalan-soalan ini: apakah maksud menukar saiz BMP (anda boleh mengandaikan bahawa n kali saiz fail tidak akan melebihi 232 - 1) . Tentukan medan dalam BITMAPFILEHEADER dan BITMAPINFOHEADER yang perlu anda ubah. Pertimbangkan sama ada anda perlu menambah atau mengalih keluar medan garis imbasan . Dan, ya, bersyukur kerana kami tidak meminta anda untuk mempertimbangkan semua kemungkinan nilai n dari 0 hingga 1! (walaupun, jika anda berminat, ini adalah masalah dari buku penggodam ;)). Walau bagaimanapun, kami menganggap bahawa untuk n = 1 atur cara akan berfungsi dengan betul dan fail keluar fail keluaran akan sama saiz dengan fail dalam asal. Adakah anda ingin menyemak program menggunakan check50? Taip arahan berikut: ~cs50/pset4/resize
Nah, jika anda ingin melihat, sebagai contoh, pengepala
large.bmp (dalam bentuk yang lebih mesra pengguna daripada yang dibenarkan xxd), anda perlu menjalankan arahan berikut:
~cs50/pset4/peek large.bmp
Lebih baik lagi, jika anda ingin membandingkan anda pengepala dengan pengepala fail pembantu CS50. Anda boleh menjalankan arahan di dalam direktori
~/workspace/pset4/bmp anda (fikirkan tentang apa yang dilakukan oleh setiap arahan). Jika anda menggunakan
malloc , pastikan anda menggunakan
percuma untuk mengelakkan kebocoran memori. Cuba gunakan
valgrind untuk memeriksa kebocoran.
./resize 4 small.bmp student.bmp
~cs50/pset4/resize 4 small.bmp staff.bmp
~cs50/pset4/peek student.bmp staff.bmp
Bagaimana untuk membuat keputusan?
-
Buka fail yang perlu kita besarkan, dan juga buat dan buka fail baharu di mana imej yang diperbesarkan akan direkodkan;
-
kemas kini maklumat pengepala untuk fail output. Memandangkan imej kami dalam format BMP dan kami menukar saiznya, kami perlu menulis pengepala fail baharu dengan dimensi baharu. Apa yang akan berubah? Saiz fail, serta saiz imej - lebar dan ketinggiannya.
-
Kami membaca fail keluar, baris demi baris, piksel demi piksel. Untuk melakukan ini, kami sekali lagi beralih ke perpustakaan I/O fail kami dan fungsi fread. Ia memerlukan penuding kepada struktur yang akan mengandungi bait yang dibaca, saiz elemen tunggal yang akan kita baca, bilangan elemen tersebut dan penunjuk kepada fail yang akan kita baca.
-
Kami meningkatkan setiap baris secara mendatar mengikut skala yang ditentukan, dan menulis hasilnya ke fail output.
Bagaimana kita menulis fail? Kami mempunyai fungsi fwrite, yang mana kami menghantar penunjuk kepada struktur di mana data yang akan ditulis ke fail terletak, saiz elemen, nombor mereka dan penunjuk ke fail output. Untuk mengatur gelung, kita boleh menggunakan gelung for yang kita sudah biasa dengan .
-
Mengisi ruang! Jika bilangan piksel dalam baris bukan gandaan empat, kita mesti menambah "penjajaran" - bait sifar. Kami memerlukan formula untuk mengira saiz penjajaran. Untuk menulis bait nol ke fail output, anda boleh menggunakan fungsi fputc, menghantarnya aksara yang anda mahu tulis dan penunjuk ke fail output.
Sekarang kita telah meregangkan rentetan secara mendatar dan menambah penjajaran pada fail output, kita perlu mengalihkan kedudukan semasa dalam fail output kerana kita perlu melompat ke atas penjajaran.
-
Meningkatkan saiz menegak. Ia lebih rumit, tetapi kita boleh menggunakan kod sampel daripada copy.c (copy.c membuka fail output, menulis tajuk pada fail output, membaca imej daripada fail sumber baris demi baris, piksel demi piksel dan menulisnya ke fail output). Berdasarkan ini, perkara pertama yang boleh anda lakukan ialah menjalankan arahan berikut: cp copy.c resize.c
Untuk meregangkan imej secara menegak bermakna menyalin setiap baris beberapa kali. Terdapat beberapa cara yang berbeza untuk melakukan ini. Sebagai contoh, menggunakan penulisan semula, apabila kita menyimpan semua piksel satu baris dalam ingatan dan menulis baris ini ke fail output dalam gelung seberapa banyak kali yang diperlukan. Kaedah lain ialah menyalin semula: selepas membaca baris dari fail keluar, tuliskannya ke fail output dan selaraskannya, kembalikan fungsi fseek kembali ke permulaan baris dalam fail keluar dan ulangi semuanya sekali lagi beberapa kali.
-
Buka fail dengan kandungan kad memori.
-
Cari permulaan fail JPEG. Semua fail pada kad ini adalah imej dalam format JPEG.
pulih
Dalam menjangkakan kertas masalah Minggu 4, saya telah menghabiskan beberapa hari terakhir melihat foto yang disimpan dalam format JPEG oleh kamera digital saya pada kad memori CompactFlash (CF) 1 GB. Tolong jangan beritahu saya bahawa saya sebenarnya telah menghabiskan beberapa hari terakhir di Facebook. Malangnya, kemahiran komputer saya meninggalkan banyak yang diingini, dan tanpa disedari, saya secara tidak sengaja memadamkan semua foto! Nasib baik, dalam dunia komputer, "dipadam" biasanya tidak sama dengan "dibunuh." Komputer saya menegaskan bahawa kad memori kini kosong, tetapi saya tahu ia berbohong. Tugasan: Tulis program dalam ~/workspace/pset4/jpg/recover.c yang akan memulihkan foto ini. Hmmm. Okay, ini satu lagi penjelasan. Walaupun format JPEG lebih kompleks daripada BMP, JPEG mempunyai "tandatangan", corak bait yang membantu membezakannya daripada format fail lain. Kebanyakan fail JPEG bermula dengan tiga bait berikut:0xff 0xd8 0xff
Dari bait pertama hingga yang ketiga, dari kiri ke kanan. Bait keempat kemungkinan besar akan menjadi salah satu daripada gabungan berikut: 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,0xe8, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xef. Dalam erti kata lain, empat bit pertama bait keempat fail JPEG ialah 1110. Kemungkinannya, jika anda menemui salah satu corak ini pada pemacu tempat foto disimpan (seperti kad memori saya), ini akan menjadi permulaan fail JPEG. Sudah tentu, anda mungkin menemui ini pada cakera yang mana secara kebetulan; pemulihan data tidak boleh dipanggil sains tepat.
GO TO FULL VERSION