JavaRush /Java Blog /Random-ID /Harvard CS50: Tugas Minggu 4 (Kuliah 9 dan 10)
Masha
Level 41

Harvard CS50: Tugas Minggu 4 (Kuliah 9 dan 10)

Dipublikasikan di grup Random-ID
Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 1

Mempersiapkan pekerjaan

Seperti biasa, pertama buka jendela terminal dan jalankan perintah. update50 untuk memastikan aplikasi Anda sudah diperbarui. Sebelum memulai, ikuti ini cd ~ / workspace wget http://cdn.cs50.net/2015/fall/psets/4/pset4/pset4.zip untuk mengunduh arsip ZIP dari tugas ini. Sekarang jika Anda menjalankan ls Anda akan melihat bahwa Anda memiliki file bernama pset4.zip di direktori ~/workspace Anda . Ekstrak menggunakan perintah: Jika Anda menjalankan perintah lsunzip pset4.zip lagi , Anda akan melihat bahwa direktori lain telah muncul. Sekarang Anda dapat menghapus file zip seperti yang ditunjukkan di bawah ini: Mari buka direktori pset4 , jalankan ls , dan pastikan direktori tersebut berisi rm -f pset4.zip cd pset4bmp / jpg / questions.txt

cerita detektif atau "Siapa yang melakukan ini?"

Jika Anda pernah melihat desktop default Windows XP (https://en.wikipedia.org/wiki/Bliss_(image)) (bukit dan langit biru), maka Anda pernah melihat BMP. Di halaman web, kemungkinan besar Anda pernah melihat GIF. Pernahkah Anda melihat foto digital? Jadi, kami senang melihat JPEG. Jika Anda pernah mengambil tangkapan layar di Mac, kemungkinan besar Anda melihat PNG. Baca di Internet tentang format BMP, GIF, JPEG, PNG dan jawab pertanyaan berikut:
  1. Berapa banyak warna yang didukung setiap format?

  2. Format mana yang mendukung animasi?

  3. Apa perbedaan antara kompresi lossy dan lossless?

  4. Manakah dari format berikut yang menggunakan kompresi lossy?

Mereka yang berbahasa Inggris disarankan untuk merujuk pada artikel dari MIT . Jika Anda mempelajarinya (atau menemukan sumber lain di Internet tentang menyimpan file pada disk dan sistem file), Anda dapat menjawab pertanyaan berikut:
  1. Apa yang terjadi dari sudut pandang teknis ketika sebuah file dihapus dalam sistem file FAT?

  2. Apa yang dapat dilakukan untuk memastikan (dengan kemungkinan besar) bahwa file yang terhapus tidak dapat dipulihkan?

Dan sekarang - ke cerita kita, yang dengan lancar mengalir ke tugas pertama minggu keempat. Selamat datang di Rumah Tudor! Pemilik perkebunan, Tuan John Boddy, tiba-tiba meninggalkan kami, menjadi korban permainan yang tidak jelas. Untuk mengetahui apa yang terjadi, Anda harus mendefinisikan cerita detektif . Sayangnya bagi Anda (walaupun lebih disayangkan lagi bagi Pak Boddy), satu-satunya bukti yang Anda miliki hanyalah file BMP 24-bit petunjuk.bmp . Isinya dapat Anda lihat di bawah. Pak Boddy berhasil membuat dan menyimpannya di komputernya di saat-saat terakhirnya. File tersebut berisi gambar detektif yang tersembunyi di antara kebisingan merah . Sekarang Anda perlu mengerjakan solusinya seperti seorang spesialis teknis sejati. Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 2Tapi pertama-tama, beberapa informasi. Mungkin paling mudah untuk membayangkan gambar sebagai kisi-kisi piksel (yaitu titik), yang masing-masing dapat memiliki warna tertentu. Untuk mengatur warna suatu titik pada gambar hitam putih kita membutuhkan 1 bit. 0 dapat mewakili warna hitam dan 1 dapat mewakili warna putih seperti terlihat pada gambar di bawah ini. Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 3Jadi, gambar yang direpresentasikan dengan cara ini hanyalah peta bit (bitmap atau bitmap, seperti yang mereka katakan dalam bahasa Inggris atau bahasa gaul). Dengan hitam putih semuanya sesederhana mungkin, tetapi untuk mendapatkan gambar berwarna kita hanya membutuhkan lebih banyak bit per piksel. Format file (seperti GIF) yang mendukung "warna 8-bit" menggunakan 8 bit per piksel. Format file (misalnya BMP, JPG, PNG) yang mendukung "warna 24-bit" menggunakan 24 bit per piksel (BMP sebenarnya mendukung warna 1-, 4-, 8-, 16-, 24-, dan 32-bit) . Dalam BMP 24-bit yang digunakan Pak Boddy, dibutuhkan 8 bit untuk menunjukkan jumlah warna merah, jumlah yang sama untuk warna hijau, dan lagi 8 bit untuk menunjukkan jumlah warna biru di setiap piksel. Jika Anda pernah mendengar tentang warna RGB , ini dia (R=merah, G=hijau, B=biru). Jika nilai R, G, dan B dari beberapa piksel dalam BMP adalah, katakanlah, 0xff, 0x00, dan 0x00 dalam heksadesimal, maka piksel tersebut akan berwarna merah murni, karena 0xff (atau dikenal sebagai 255 dalam desimal) berarti "banyak warna merah " pada saat itu 0x00 dan 0x00 masing-masing berarti “tidak ada hijau” dan “biru juga nol”. Mengingat betapa merahnya gambar BMP Mr. Boddy yang tampak bagi kita, maka wajar jika "kompartemen" merah memiliki nilai yang jelas lebih besar daripada "kompartemen" merah dan biru. Namun, tidak semua piksel berwarna merah; beberapa jelas memiliki warna berbeda. Omong-omong, dalam HTML dan CSS (bahasa markup dan style sheet yang membantunya, yang digunakan untuk membuat halaman web), model warna disusun dengan cara yang sama. Jika tertarik, lihat tautannya: https://ru.wikipedia.org/wiki/Colors_HTMLuntuk lebih jelasnya. Sekarang mari kita dekati masalahnya secara lebih teknis. Ingatlah bahwa file hanyalah serangkaian bit yang disusun dalam urutan tertentu. File BMP 24-bit adalah urutan bit, setiap 24 bit (hampir) menentukan warna piksel yang mana. Selain data warna, file BMP juga berisi metadata – informasi tentang lebar dan tinggi gambar. Metadata ini disimpan di awal file dalam bentuk dua struktur data yang biasa disebut "header" (jangan bingung dengan file header C). Header pertama adalah BITMAPFILEHEADER, yang panjangnya 14 byte (atau 14*8 bit). Header kedua adalah BITMAPINFOHEADER (panjang 40 byte). Setelah header ini muncul bitmap: array byte, kembar tiga mewakili warna piksel (1, 4, dan 16-bit dalam BMP, tetapi bukan 24 atau 32, mereka memiliki header tambahan tepat setelah BITMAPINFOHEADER. Ini disebut array RGBQUAD, yang menentukan “nilai intensitas” untuk setiap warna dalam palet). Namun, BMP menyimpan triplet ini secara terbalik (bisa dikatakan seperti BGR), dengan 8 bit untuk warna biru, 8 bit untuk warna hijau, dan 8 bit untuk warna merah. Omong-omong, beberapa BMP juga menyimpan seluruh bitmap secara terbalik, dimulai dari baris atas gambar di akhir file BMP. Dalam tugas kita, kita menyimpan VMR seperti yang dijelaskan di sini, pertama baris atas gambar, lalu baris bawah. Dengan kata lain, kami mengubah emoji satu bit menjadi 24-bit dengan mengganti warna hitam dengan merah. BMP 24-bit akan menyimpan bitmap ini, dengan 0000ff mewakili merah dan ffffff mewakili putih; kami telah menyorot semua contoh 0000ff dengan warna merah. Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 4Karena kami menyajikan potongan-potongan ini dari kiri ke kanan, atas ke bawah, Anda dapat melihat wajah tersenyum merah di huruf-huruf ini jika Anda menjauh sedikit dari monitor. Ingatlah bahwa satu digit dalam sistem bilangan heksadesimal mewakili 4 bit. Oleh karena itu, ffffff dalam heksadesimal sebenarnya berarti 1111111111111111111111111 dalam biner. Sekarang, pelan-pelan, dan jangan melangkah lebih jauh sampai Anda yakin memahami mengapa 0000ff mewakili piksel merah dalam file BMP 24-bit. Di jendela CS50 IDE, perluas (misalnya, dengan mengklik segitiga kecil) folder pset4 , dan di dalamnya - bmp . Di folder ini Anda akan menemukan smiley.bmp , klik dua kali pada file tersebut dan Anda akan menemukan smiley kecil berukuran 8x8 piksel di sana. Di menu tarik-turun, ubah skala gambar, katakanlah dari 100% menjadi 400%, ini akan memungkinkan Anda melihat versi emotikon yang lebih besar, namun pada saat yang sama lebih "buram". Meskipun pada kenyataannya gambar yang sama ini tidak boleh buram meskipun diperbesar. Hanya saja IDE CS50 mencoba membantu Anda (dalam gaya seri CIA) dengan menghaluskan gambar (mengaburkan tepinya secara visual). Seperti inilah tampilan smiley kita jika kita memperbesarnya tanpa menghaluskannya: Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 5Piksel berubah menjadi kotak besar. Ayo lanjutkan. Di terminal, buka ~/workspace/pset4/bmp . Kami rasa Anda sudah ingat cara melakukan ini. Mari kita periksa byte yang dialokasikan di smiley.bmp . Ini dapat dilakukan dengan menggunakan hex editor baris perintah, program xxd . Untuk menjalankannya, jalankan perintah: xxd -c 24 -g 3 -s 54 smiley.bmp Anda akan melihat apa yang ditunjukkan di bawah ini; Kami kembali menyorot dengan warna merah semua contoh 0000ff. Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 6Pada gambar di kolom paling kiri Anda dapat melihat alamat dalam file, yang setara dengan offset dari byte pertama file. Semuanya diberikan dalam sistem bilangan heksadesimal. Jika kita mengonversi heksadesimal 00000036 ke desimal, kita mendapatkan 54. Jadi, Anda sedang melihat byte ke-54 dari smiley.bmp . Ingatlah bahwa dalam file BMP 24-bit, 14 + 40 = 54 byte pertama diisi dengan metadata. Jadi jika ingin melihat metadatanya, jalankan perintah berikut: xxd -c 24 -g 3 smiley.bmp Jika smiley.bmp berisi karakter ASCII , kita akan melihatnya di kolom paling kanan di xxd, bukan di semua titik itu. Jadi smiley adalah BMP 24-bit (setiap piksel diwakili oleh 24 8 = 3 byte) dengan ukuran (resolusi) 8x8 piksel. Setiap baris (atau disebut "Scanline") membutuhkan (8 piksel) x (3 byte per piksel) = 24 byte. Angka ini merupakan kelipatan empat, dan ini penting karena file BMP disimpan sedikit berbeda jika jumlah byte dalam baris bukan kelipatan empat. Jadi, di small.bmp, file BMP 24-bit lainnya di folder kami, Anda dapat melihat kotak hijau 3x3 piksel. Jika Anda membukanya di penampil gambar, Anda akan melihat tampilannya menyerupai gambar di bawah ini, hanya saja ukurannya lebih kecil. Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 7Setiap baris dalam small.bmp menempati (3 piksel) × (3 byte per piksel) = 9 byte, yang bukan merupakan kelipatan 4. Untuk mendapatkan panjang garis yang merupakan kelipatan 4, baris tersebut diisi dengan nol tambahan: antara 0 dan 3 byte kami mengisi setiap baris dalam format BMP 24-bit (bisakah Anda menebak alasannya?). Untuk small.bmp , diperlukan 3 byte nol, karena (3 piksel) x (3 byte per piksel) + (3 byte padding) = 12 byte, yang merupakan kelipatan 4. Untuk "melihat" padding ini, lakukan hal berikut. xxd -c 12 -g 3 -s 54 small.bmp Perhatikan bahwa kami menggunakan nilai yang berbeda untuk -c dibandingkan dengan smiley.bmp , jadi xxd hanya menampilkan 4 kolom kali ini (3 untuk kotak hijau dan 1 untuk padding). Untuk lebih jelasnya, kami telah menyorot semua contoh 00ff00 dengan warna hijau. Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 8Sebagai kontras, mari gunakan xxd untuk file large.bmp . Tampilannya persis sama dengan small.bmp, hanya resolusinya 12x12 piksel, empat kali lebih besar. Jalankan perintah di bawah ini. Anda mungkin perlu memperluas jendela untuk menghindari transfer. xxd -c 36 -g 3 -s 54 large.bmp Anda akan melihat sesuatu seperti ini: Harvard CS50: Tugas Minggu 4 (Kuliah 9 dan 10) - 9Harap dicatat, tidak ada penyimpangan dalam BMP ini! Lagi pula, (12 piksel) × (3 byte per piksel) = 36 byte, dan ini merupakan kelipatan 4. Editor hex xxd menunjukkan kepada kita byte dalam file BMP kita. Bagaimana kita bisa mendapatkannya secara terprogram? Di copy.c ada satu program yang tujuan hidupnya satu-satunya adalah membuat salinan BMP, sepotong demi sepotong. Ya, Anda dapat menggunakan cp untuk ini . Namun cp tidak akan bisa membantu Pak Boddy. Mari kita berharap copy.c melakukan hal ini, jadi ini dia: ./copy smiley.bmp copy.bmp Jika sekarang Anda menjalankan ls (dengan flag yang sesuai), Anda akan melihat bahwa smiley.bmp dan copy.bmp memang berukuran sama. Mari kita periksa lagi apakah ini benar? diff smiley.bmp copy.bmp Jika perintah ini tidak menampilkan apa pun di layar, berarti file tersebut memang identik (penting: beberapa program, seperti Photoshop, menyertakan angka nol di akhir beberapa VMP. Versi salinan kami membuangnya, jadi jangan khawatir jika menyalin BMP lain yang telah Anda unduh atau buat untuk pengujian, salinannya akan lebih kecil beberapa byte dari aslinya). Anda dapat membuka kedua file di penampil gambar Ristretto (klik dua kali) untuk mengonfirmasi hal ini secara visual. Tapi perbandingan ini berbeda byte demi byte, jadi penglihatannya lebih tajam dari Anda! Bagaimana salinan ini dibuat? Ternyata copy.c ada hubungannya dengan bmp.h . Mari kita pastikan: buka bmp.h. Di sana Anda akan melihat definisi sebenarnya dari header yang telah kami sebutkan, diadaptasi dari implementasi Microsoft sendiri. Selain itu, file ini mendefinisikan tipe data BYTE, DWORD, LONG, dan WORD, yang merupakan tipe data yang biasanya ditemukan di dunia pemrograman Win32 (yaitu Windows). Perhatikan bahwa ini pada dasarnya adalah alias untuk primitif yang (mudah-mudahan) sudah Anda kenal. Ternyata BITMAPFILEHEADER dan BITMAPINFOHEADER menggunakan tipe ini. File ini juga mendefinisikan struct yang disebut RGBTRIPLE. Ini “merangkum” tiga byte: satu biru, satu hijau dan satu merah (ini adalah urutan di mana kita akan mencari triplet RGB pada disk). Bagaimana struct ini berguna? Singkatnya, file hanyalah urutan byte (atau akhirnya bit) pada disk. Namun, byte-byte ini biasanya diurutkan sehingga beberapa byte pertama mewakili sesuatu, kemudian beberapa byte berikutnya mewakili sesuatu yang lain, dan seterusnya. File "format" ada karena kita memiliki standar, atau aturan, yang menentukan arti byte. Sekarang, kita cukup membaca file dari disk ke dalam RAM sebagai satu array byte besar. Dan kita ingat bahwa byte pada posisi [i] mewakili satu hal, sedangkan byte pada posisi [j] adalah sesuatu yang lain. Namun mengapa tidak memberi nama beberapa byte ini agar kita dapat lebih mudah mengambilnya dari memori? Inilah tepatnya yang dibantu oleh struktur di bmp.h. Daripada menganggap file sebagai satu rangkaian byte yang panjang, kita melihatnya dipecah menjadi blok-blok yang lebih mudah dipahami - rangkaian struktur. Ingatlah bahwa smiley.bmp memiliki resolusi 8x8 piksel, sehingga memakan 14 + 40 + (8 × 8) × 3 = 246 byte pada disk (Anda dapat memeriksanya menggunakan perintah ls). Berikut tampilannya pada disk menurut Microsoft: Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 10Kita dapat melihat bahwa urutan penting ketika menyangkut anggota struct. Byte 57 adalah rgbtBlue (bukan, katakanlah, rgbtRed) karena rgbtBlue didefinisikan dalam RGBTRIPLE terlebih dahulu. Ngomong-ngomong, penggunaan atributpacked kami memastikan bahwa clang tidak mencoba untuk "menyelaraskan kata" anggota (dengan alamat byte pertama setiap anggota adalah kelipatan 4), sehingga kita tidak mendapatkan lubang di dalamnya. struktur kami yang tidak ada di disk sama sekali. Mari kita lanjutkan. Temukan URL yang cocok dengan BITMAPFILEHEADER dan BITMAPINFOHEADER, sesuai komentar di bmp.h. Perhatian, momen yang luar biasa: Anda mulai menggunakan MSDN (Microsoft Developer Network)! Daripada menelusuri copy.c lebih jauh , jawablah beberapa pertanyaan untuk memahami cara kerja kode. Seperti biasa, perintah man adalah teman sejati Anda, dan sekarang juga MSDN. Jika Anda tidak tahu jawabannya, carilah di Google dan pikirkanlah. Anda juga dapat merujuk ke file stdio.h di https://reference.cs50.net/.
  1. Tetapkan breakpoint di main (dengan mengklik di sebelah kiri penggaris dengan nomor baris utama).

  2. Di tab terminal , buka ~/workspace/pset4/bmp , dan kompilasi copy.c ke dalam program penyalinan menggunakan make.

  3. Jalankan debug50 copy smiley.bmp copy.bmp , ini akan membuka panel debugger di sebelah kanan.

  4. Jalani program langkah demi langkah menggunakan panel di sebelah kanan. Catatan bf dan bi . Di ~/workspace/pset4/questions.txt , jawab pertanyaan:

  • Apa itu stdint.h ?

  • Apa gunanya menggunakan uint8_t , uint32_t , int32_t dan uint16_t dalam sebuah program?

  • Berapa banyak byte yang masing-masing berisi BYTE , DWORD , LONG , dan WORD (Dengan asumsi arsitektur 32-bit)?

  • Berapa (ASCII, desimal atau heksadesimal) dua byte pertama file BMP? (byte awal, yang digunakan untuk mengidentifikasi format file (dengan probabilitas tinggi) sering disebut "angka ajaib").
  • Apa perbedaan antara bfSize dan biSize?

  • Apa yang dimaksud dengan biHeight negatif?

  • Bidang manakah di BITMAPINFOHEADER yang menentukan kedalaman warna dalam BMP (yaitu bit per piksel)?

  • Mengapa fungsi fopen dapat mengembalikan NULL di copy.c 37?

  • Mengapa argumen ketiga untuk takut dalam kode kita sama dengan 1?

  • Nilai apa di copy.c 70 yang mendefinisikan padding jika bi.biWidth adalah 3?

  • Apa yang dilakukan fseek?

  • Apa itu SEEK_CUR?

Kembali ke Tuan Boddy. Latihan:

Tulis sebuah program bernama whodunit dalam file bernama whodunit.c yang memperlihatkan gambar Pak Boddy. Hmmmm, apa? Seperti copy, program harus mengambil tepat dua argumen baris perintah, dan jika Anda menjalankan program seperti gambar di bawah ini, hasilnya akan disimpan di vonis.bmp, di mana gambar Pak Boddy tidak akan berisik. ./whodunit clue.bmp verdict.b Izinkan kami menyarankan Anda untuk mulai memecahkan misteri ini dengan menjalankan perintah di bawah ini. cp copy.c whodunit.c Anda mungkin terkejut dengan banyaknya baris kode yang perlu Anda tulis untuk membantu Pak Boddy. Tidak ada hal yang tidak perlu yang disembunyikan di smiley.bmp , jadi silakan uji program pada file ini. Ini kecil, dan Anda dapat membandingkan keluaran program Anda dan keluaran xxd selama pengembangan (atau mungkin ada sesuatu yang tersembunyi di smiley.bmp ? Sebenarnya tidak). Omong-omong, masalah ini dapat diselesaikan dengan berbagai cara. Setelah Anda mengidentifikasi gambar Tuan Boddy, dia akan beristirahat dengan tenang. Karena whodunit dapat diimplementasikan dalam berbagai cara, Anda tidak akan dapat memeriksa kebenaran implementasi dengan check50 . Dan biarkan hal itu merusak kesenangan Anda, tetapi solusi asisten juga tidak tersedia untuk masalah cerita detektif . Terakhir, di file In ~/workspace/pset4/questions.txt , jawab pertanyaan berikut: Whodunit? //ктоэтосделал?

mengubah ukuran

Nah, sekarang - tes selanjutnya! Mari kita menulis sebuah program bernama resize di resize.c . Ini akan mengubah ukuran gambar BMP 24-bit yang tidak terkompresi dalam langkah n. Aplikasi Anda harus menerima tepat tiga argumen baris perintah, dengan yang pertama (n) berupa bilangan bulat tidak lebih besar dari 100, yang kedua adalah nama file yang akan diubah, dan yang ketiga adalah nama versi tersimpan dari file yang dimodifikasi. mengajukan. Usage: ./resize n infile outfile Dengan program seperti itu, kita dapat membuat large.bmp dari small.bmp dengan mengubah ukurannya menjadi 4 (yaitu, mengalikan lebar dan tinggi dengan 4), seperti yang ditunjukkan di bawah ini. Untuk mempermudah, Anda dapat memulai tugas dengan menyalin copy.c./resize 4 small.bmp large.bmp lagi dan memberi nama salinan resize.c . Tapi pertama-tama, tanyakan pada diri Anda dan jawab pertanyaan-pertanyaan ini: apa artinya mengubah ukuran BMP (Anda dapat berasumsi bahwa n kali ukuran infile tidak akan melebihi 232 - 1) . Tentukan bidang mana di BITMAPFILEHEADER dan BITMAPINFOHEADER yang perlu Anda ubah. Pertimbangkan apakah Anda perlu menambah atau menghapus bidang scanlines . Dan ya, bersyukurlah karena kami tidak meminta Anda mempertimbangkan semua kemungkinan nilai n dari 0 hingga 1! (walaupun, jika Anda tertarik, ini adalah masalah dari buku peretas ;)). Namun, kami berasumsi bahwa untuk n = 1 program akan bekerja dengan benar dan file keluaran file keluar akan berukuran sama dengan file masuk asli. Apakah Anda ingin memeriksa program menggunakan check50? Ketik perintah berikut: check50 2015.fall.pset4.resize bmp.h resize.c Ingin bermain-main dengan implementasi aplikasi buatan asisten CS50? Jalankan yang berikut ini: ~cs50/pset4/resize Nah, jika Anda ingin melihat, misalnya, header large.bmp (dalam bentuk yang lebih mudah digunakan daripada yang dimungkinkan oleh xxd), Anda perlu menjalankan perintah berikut: ~cs50/pset4/peek large.bmp Lebih baik lagi, jika Anda ingin membandingkan header dengan header file asisten CS50. Anda dapat menjalankan perintah di dalam direktori ~/workspace/pset4/bmp Anda (pikirkan apa yang dilakukan setiap perintah). Jika Anda menggunakan malloc , pastikan menggunakan free untuk mencegah kebocoran memori. Coba 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 cara memutuskan?

  • Buka file yang perlu kita perbesar, dan juga buat dan buka file baru di mana gambar yang diperbesar akan direkam;

  • perbarui informasi header untuk file output. Karena gambar kita dalam format BMP dan kita mengubah ukurannya, kita perlu menulis header file baru dengan dimensi baru. Apa yang akan berubah? Ukuran file, serta ukuran gambar - lebar dan tingginya.

Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 11Jika kita melihat deskripsi header, kita akan melihat variabel biSizeImage . Ini menunjukkan ukuran total gambar dalam byte, biWidth adalah lebar gambar dikurangi perataan, biHeight adalah tingginya. Variabel-variabel ini terletak di struktur BITMAPFILEHEADER dan BITMAPINFOHEADER. Anda dapat menemukannya jika Anda membuka file bmp.h. Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 12Deskripsi struktur BITMAPINFOHEADER berisi daftar variabel. Untuk menulis judul file keluaran, Anda perlu mengubah nilai tinggi dan lebar. Namun ada kemungkinan juga nantinya Anda memerlukan tinggi dan lebar asli dari file aslinya. Oleh karena itu, lebih baik pertahankan keduanya. Berhati-hatilah dengan nama variabel agar Anda tidak menulis data yang salah secara tidak sengaja di header file keluaran.
  • Kami membaca file keluar, baris demi baris, piksel demi piksel. Untuk melakukan ini, kita kembali beralih ke perpustakaan file I/O dan fungsi fread. Dibutuhkan sebuah pointer ke struktur yang akan berisi byte yang dibaca, ukuran elemen tunggal yang akan kita baca, jumlah elemen tersebut, dan pointer ke file yang akan kita baca.

    Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 13
  • Kami memperbesar setiap baris secara horizontal sesuai dengan skala yang ditentukan, dan menulis hasilnya ke file keluaran.

    Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 14

    Bagaimana kita menulis file? Kami memiliki fungsi fwrite, yang dengannya kami meneruskan indikator ke struktur tempat data yang akan ditulis ke file berada, ukuran elemen, nomornya, dan penunjuk ke file keluaran. Untuk mengatur perulangan, kita dapat menggunakan perulangan for yang sudah kita kenal .

    Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 15
  • Isilah kekosongannya! Jika jumlah piksel dalam satu baris bukan kelipatan empat, kita harus menambahkan "penyelarasan" - nol byte. Kita memerlukan rumus untuk menghitung ukuran perataan. Untuk menulis byte nol ke file keluaran, Anda dapat menggunakan fungsi fputc, meneruskan karakter yang ingin Anda tulis dan penunjuk ke file keluaran ke dalamnya.

    Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 16

    Sekarang kita telah meregangkan string secara horizontal dan menambahkan perataan ke file keluaran, kita perlu memindahkan posisi saat ini di file keluaran karena kita perlu melompati perataan tersebut.

    Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 17
  • Tingkatkan ukuran vertikal. Ini lebih rumit, tetapi kita dapat menggunakan kode contoh dari copy.c (copy.c membuka file keluaran, menulis header ke file keluaran, membaca gambar dari file sumber baris demi baris, piksel demi piksel, dan menulisnya ke file keluaran). Berdasarkan hal tersebut, hal pertama yang dapat Anda lakukan adalah menjalankan perintah berikut: cp copy.c resize.c

    Meregangkan gambar secara vertikal berarti menyalin setiap baris beberapa kali. Ada beberapa cara berbeda untuk melakukan ini. Misalnya, menggunakan penulisan ulang, ketika kita menyimpan semua piksel dari satu baris ke dalam memori dan menulis baris ini ke file keluaran dalam satu lingkaran sebanyak yang diperlukan. Metode lain adalah menyalin ulang: setelah membaca baris dari file keluar, menulisnya ke file keluaran dan menyelaraskannya, kembalikan fungsi fseek ke awal baris di file keluar dan ulangi semuanya lagi beberapa kali.

    Harvard CS50: Tugas Minggu 4 (Kuliah 9 dan 10) - 18
  • pulih

    Untuk mengantisipasi makalah soal Minggu ke-4, saya menghabiskan beberapa hari terakhir melihat foto-foto yang disimpan dalam format JPEG oleh kamera digital saya pada kartu memori CompactFlash (CF) 1 GB. Tolong jangan beri tahu saya bahwa saya sebenarnya menghabiskan beberapa hari terakhir di Facebook. Sayangnya, keterampilan komputer saya masih kurang, dan tanpa saya sadari, saya tidak sengaja menghapus semua foto! Untungnya, dalam dunia komputer, "dihapus" biasanya tidak sama dengan "dibunuh". Komputer saya bersikeras bahwa kartu memori sekarang kosong, tapi saya tahu itu bohong. Tugas: Tulis program di ~/workspace/pset4/jpg/recover.c yang akan memulihkan foto-foto ini. Hmmm. Oke, ini satu klarifikasi lagi. Meskipun format JPEG lebih kompleks daripada BMP, JPEG memiliki “tanda tangan”, pola byte yang membantu membedakannya dari format file lainnya. Kebanyakan file JPEG dimulai dengan tiga byte berikut: 0xff 0xd8 0xff Dari byte pertama hingga ketiga, dari kiri ke kanan. Byte keempat kemungkinan besar merupakan salah satu dari kombinasi berikut: 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,0xe8, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef. Dengan kata lain, empat bit pertama dari byte keempat file JPEG adalah 1110. Kemungkinannya adalah, jika Anda menemukan salah satu pola ini di drive tempat foto disimpan (seperti kartu memori saya), ini akan menjadi awal dari file JPEG. Tentu saja, Anda mungkin menemukan ini pada disk mana yang murni kebetulan; pemulihan data tidak dapat disebut ilmu pasti.

    Bagaimana cara memutuskan

    1. Buka file dengan isi kartu memori.

    2. Temukan awal file JPEG. Semua file di kartu ini adalah gambar dalam format JPEG.

    Anda sudah mengetahui tentang penanda JPEG: Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 19Penting (dan menyenangkan) untuk mengetahui bahwa setiap file JPEG disimpan dalam memori sebagai satu blok, dan file itu sendiri mengikuti satu demi satu. Mari kita menggambar peta memori skematis. Setiap persegi panjang adalah blok dengan panjang 512 byte. Persegi panjang abu-abu adalah area di mana tidak ada file JPEG; tanda bintang menunjukkan awal file JPEG. Kami percaya bahwa kami tidak memiliki blok abu-abu di antara file. Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 20Bagaimana kita membaca data ini, 512 byte ini, untuk membandingkan awalnya dengan header JPEG? Kita bisa menggunakan fungsi fread yang sudah tidak asing lagi bagi kita, yang mengambil pointer ke struktur data tempat byte yang dibaca akan ditulis, serta ukuran elemen yang sedang dibaca, jumlah elemen tersebut, dan penunjuk ke file tempat kita membaca data. Harvard CS50: Tugas Minggu Keempat (Kuliah 9 dan 10) - 21Kami ingin membaca 512 byte dan menyimpannya dalam buffer. Ini akan menjadi penunjuk &data, dan penunjuk inptr akan menunjuk ke file yang terbuka dengan isi kartu memori. Jadi, mari kita kembali ke struktur file tempat kita menyimpan
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION