
Paghahanda para sa trabaho
Gaya ng nakasanayan, buksan muna ang isang terminal window at patakbuhin ang command.update50
upang matiyak na napapanahon na ang iyong aplikasyon. Bago ka magsimula, sundin ito cd ~ / workspace
wget http://cdn.cs50.net/2015/fall/psets/4/pset4/pset4.zip
upang mag-download ng ZIP archive ng gawaing ito. Ngayon kung tatakbo ka ls makikita mo na mayroon kang file na tinatawag na pset4.zip sa iyong ~/workspace directory . I-extract ito gamit ang command: Kung patakbuhin mo unzip pset4.zip
muli ang ls command , makikita mong may lumabas na ibang direktoryo. Ngayon ay maaari mong tanggalin ang zip file tulad ng ipinapakita sa ibaba: rm -f pset4.zip
Buksan natin ang direktoryo ng pset4 cd pset4
, patakbuhin ang ls , at tiyaking naglalaman ang direktoryo bmp / jpg / questions.txt
whodunit o "Sino ang gumawa nito?"
Kung nakita mo na ang default na desktop ng Windows XP (https://en.wikipedia.org/wiki/Bliss_(image)) (mga burol at asul na langit), nakita mo na ang BMP. Sa mga web page, malamang na nakakita ka ng mga GIF. Nakatingin ka na ba sa mga digital na larawan? Kaya, nagkaroon kami ng kagalakan na makita ang JPEG. Kung nakakuha ka na ng screenshot sa isang Mac, malamang na nakakita ka ng PNG. Magbasa sa Internet tungkol sa BMP, GIF, JPEG, PNG na mga format at sagutin ang mga tanong na ito:-
Ilang kulay ang sinusuportahan ng bawat format?
-
Aling format ang sumusuporta sa animation?
-
Ano ang pagkakaiba sa pagitan ng lossy at lossless compression?
-
Alin sa mga format na ito ang gumagamit ng lossy compression?
-
Ano ang mangyayari mula sa isang teknikal na punto ng view kapag ang isang file ay tinanggal sa isang FAT file system?
-
Ano ang maaaring gawin upang matiyak (na may mataas na posibilidad) na ang mga tinanggal na file ay hindi na mababawi?




xxd -c 24 -g 3 -s 54 smiley.bmp
Dapat mong makita kung ano ang ipinapakita sa ibaba; Muli naming na-highlight sa pula ang lahat ng pagkakataon ng 0000ff. 
xxd -c 24 -g 3 smiley.bmp
Kung ang smiley.bmp ay naglalaman ng mga ASCII na character , makikita natin ang mga ito sa pinakakanang column sa xxd sa halip na lahat ng mga tuldok na iyon. Kaya, ang smiley ay isang 24-bit na BMP (ang bawat pixel ay kinakatawan ng 24 ÷ 8 = 3 bytes) na may sukat (resolution) na 8x8 pixels. Ang bawat linya (o "Scanline" kung tawagin) ay tumatagal ng hanggang (8 pixels) x (3 bytes per pixel) = 24 bytes. Ang numerong ito ay isang multiple ng apat, at ito ay mahalaga dahil ang BMP file ay bahagyang naiiba kung ang bilang ng mga byte sa linya ay hindi isang multiple ng apat. Kaya, sa small.bmp, isa pang 24-bit na BMP file sa aming folder, makakakita ka ng berdeng 3x3 pixel box. Kung bubuksan mo ito sa isang viewer ng imahe, makikita mo na ito ay kahawig ng larawang ipinapakita sa ibaba, mas maliit lamang ang laki. 
xxd -c 12 -g 3 -s 54 small.bmp
Tandaan na gumagamit kami ng ibang value para sa -c kaysa sa smiley.bmp , kaya 4 na column lang ang output ng xxd sa pagkakataong ito (3 para sa berdeng parisukat at 1 para sa padding). Para sa kalinawan, na-highlight namin ang lahat ng pagkakataon ng 00ff00 sa berde. 
xxd -c 36 -g 3 -s 54 large.bmp
Makakakita ka ng ganito: 
./copy smiley.bmp copy.bmp
Kung magpapatakbo ka na ngayon ng ls (na may naaangkop na flag), makikita mo na ang smiley.bmp at copy.bmp ay talagang magkapareho ang laki. Suriin natin muli kung ito ay totoo? diff smiley.bmp copy.bmp
Kung ang command na ito ay hindi nagpapakita ng anuman sa screen, nangangahulugan ito na ang mga file ay talagang magkapareho (mahalaga: ang ilang mga programa, tulad ng Photoshop, ay may kasamang mga trailing zero sa dulo ng ilang VMP. Ang aming bersyon ng kopya ay nagtatapon sa kanila, kaya huwag mag-alala kung sakaling makopya ang iba pang mga BMP na iyong na-download o ginawa para sa pagsubok, ang kopya ay magiging ilang byte na mas maliit kaysa sa orihinal). Maaari mong buksan ang parehong mga file sa viewer ng imahe ni Ristretto (double-click) upang kumpirmahin ito nang makita. Ngunit naiiba ang ginagawa nitong paghahambing na byte sa pamamagitan ng byte, kaya ang kanyang paningin ay mas matalas kaysa sa iyo! Paano ginawa ang kopyang ito? Lumalabas na ang copy.c ay nauugnay sa bmp.h . Siguraduhin natin: buksan ang bmp.h. Doon mo makikita ang aktwal na mga kahulugan ng mga header na nabanggit na namin, na inangkop mula sa sariling mga pagpapatupad ng Microsoft. Bukod pa rito, tinutukoy ng file na ito ang mga uri ng data na BYTE, DWORD, LONG, at WORD, na mga uri ng data na karaniwang matatagpuan sa mundo ng Win32 (ibig sabihin, Windows) programming. Tandaan na ang mga ito ay mahalagang mga alias para sa mga primitive na (sana) pamilyar ka na. Lumalabas na ang BITMAPFILEHEADER at BITMAPINFOHEADER ay gumagamit ng mga ganitong uri. Tinutukoy din ng file na ito ang isang struct na tinatawag na RGBTRIPLE. Ito ay "nagpapaloob" ng tatlong byte: isang asul, isang berde at isang pula (ito ang pagkakasunud-sunod kung saan hahanapin natin ang mga RGB triplets sa disk). Paano kapaki-pakinabang ang mga istrukturang ito? Upang recap, ang isang file ay simpleng pagkakasunud-sunod ng mga byte (o sa huli ay mga bit) sa disk. Gayunpaman, ang mga byte na ito ay karaniwang nakaayos upang ang unang ilan ay kumakatawan sa isang bagay, pagkatapos ay ang susunod na ilan ay kumakatawan sa iba pa, at iba pa. Umiiral ang "mga format" ng file dahil mayroon kaming mga pamantayan, o mga panuntunan, na tumutukoy kung ano ang ibig sabihin ng mga byte. Ngayon, maaari na nating basahin ang file mula sa disk papunta sa RAM bilang isang malaking byte array. At naaalala namin na ang byte sa posisyon [i] ay kumakatawan sa isang bagay, habang ang byte sa posisyon [j] ay ibang bagay. Ngunit bakit hindi bigyan ang ilan sa mga byte na ito ng mga pangalan upang mas madaling makuha ang mga ito mula sa memorya? Ito mismo ang nakatulong sa amin ng mga istruktura sa bmp.h. Sa halip na isipin ang isang file bilang isang mahabang pagkakasunud-sunod ng mga byte, nakikita natin itong pinaghiwa-hiwalay sa mas mauunawaang mga bloke - mga pagkakasunud-sunod ng mga istruktura. Alalahanin na ang smiley.bmp ay may resolution na 8x8 pixels, kaya tumatagal ito ng 14 + 40 + (8 × 8) × 3 = 246 bytes sa disk (maaari mong suriin ito gamit ang ls command). Narito kung ano ang hitsura nito sa disk ayon sa Microsoft: 
-
Magtakda ng breakpoint sa main (sa pamamagitan ng pag-click sa kaliwa ng ruler na may mga pangunahing numero ng linya).
-
Sa isang tab na terminal , pumunta sa ~/workspace/pset4/bmp , at i-compile ang copy.c sa copy program gamit ang make.
-
Patakbuhin ang debug50 copy smiley.bmp copy.bmp , bubuksan nito ang panel ng debugger sa kanan.
-
Maglakad sa programa nang sunud-sunod gamit ang panel sa kanan. Tandaan bf at bi . Sa ~/workspace/pset4/questions.txt , sagutin ang mga tanong:
-
Ano ang stdint.h ?
-
Ano ang punto ng paggamit ng uint8_t , uint32_t , int32_t at uint16_t sa isang programa?
-
Ilang byte ang nilalaman ng BYTE , DWORD , LONG , at WORD ayon sa pagkakabanggit (Ipagpalagay na 32-bit na arkitektura)?
- Ano (ASCII, decimal o hexadecimal) ang dapat na unang dalawang byte ng isang BMP file? (nangungunang mga byte, na ginagamit upang matukoy ang format ng file (na may mataas na posibilidad) ay madalas na tinatawag na "magic number").
-
Ano ang pagkakaiba ng bfSize at biSize?
-
Ano ang ibig sabihin ng negatibong biHeight?
-
Aling field sa BITMAPINFOHEADER ang tumutukoy sa lalim ng kulay sa BMP (ibig sabihin, mga bit bawat pixel)?
-
Bakit maaaring ibalik ng fopen function ang NULL sa copy.c 37?
-
Bakit ang pangatlong argumento sa fread sa aming code ay katumbas ng 1?
-
Anong halaga sa copy.c 70 ang tumutukoy sa padding kung ang bi.biWidth ay 3?
-
Ano ang ginagawa ng fseek?
-
Ano ang SEEK_CUR?
Bumalik sa Mr. Boddy. Pagsasanay:
Sumulat ng program na tinatawag na whodunit sa isang file na tinatawag na whodunit.c na nagpapakita ng drawing ni Mr. Boddy. Hmmmm, ano? Tulad ng kopya, ang programa ay dapat kumuha ng eksaktong dalawang argumento ng command line, at kung patakbuhin mo ang iyong programa tulad ng ipinapakita sa ibaba, ang resulta ay maiimbak sa verdict.bmp, kung saan ang pagguhit ni Mr. Boddy ay hindi maingay../whodunit clue.bmp verdict.b
Iminumungkahi namin na sisimulan mong lutasin ang misteryong ito sa pamamagitan ng pagpapatakbo ng utos sa ibaba. cp copy.c whodunit.c
Maaaring mamangha ka sa kung gaano karaming mga linya ng code ang kailangan mong isulat upang matulungan si Mr. Boddy. Walang hindi kinakailangang nakatago sa smiley.bmp , kaya huwag mag-atubiling subukan ang program sa file na ito. Ito ay maliit, at maaari mong ihambing ang output ng iyong programa at ang output ng xxd sa panahon ng pag-unlad (o baka may nakatago sa smiley.bmp ? Sa totoo lang, hindi). Sa pamamagitan ng paraan, ang problemang ito ay maaaring malutas sa iba't ibang paraan. Kapag natukoy mo na ang iginuhit ni Mr. Boddy, siya ay magpapahinga sa kapayapaan. Dahil maaaring ipatupad ang whodunit sa maraming paraan, hindi mo masusuri ang kawastuhan ng mga pagpapatupad gamit ang check50 . At hayaang sirain nito ang iyong kasiyahan, ngunit hindi rin available ang solusyon ng mga katulong para sa problemang whodunit . Panghuli, sa file Sa ~/workspace/pset4/questions.txt , sagutin ang sumusunod na tanong: Whodunit? //ктоэтосделал?
baguhin ang laki
Well, ngayon - ang susunod na pagsubok! Sumulat tayo ng program na tinatawag na resize in resize.c . Babaguhin nito ang laki ng isang hindi naka-compress na 24-bit na BMP na imahe sa mga hakbang ng n. Dapat tanggapin ng iyong aplikasyon ang eksaktong tatlong argumento ng command line, na ang una (n) ay isang integer na hindi hihigit sa 100, ang pangalawa ay ang pangalan ng file na babaguhin, at ang pangatlo ay ang pangalan ng naka-save na bersyon ng binagong file.Usage: ./resize n infile outfile
Sa ganoong programa, maaari tayong lumikha ng large.bmp mula sa small.bmp sa pamamagitan ng pagbabago ng laki sa huli ng 4 (ibig sabihin, pagpaparami ng lapad at taas sa 4), tulad ng ipinapakita sa ibaba. ./resize 4 small.bmp large.bmp
Para sa pagiging simple, maaari mong simulan ang gawain sa pamamagitan ng pagkopya muli sa copy.c at pagpapangalan sa kopyang resize.c . Ngunit una, tanungin ang iyong sarili at sagutin ang mga tanong na ito: ano ang ibig sabihin ng pagbabago ng laki ng BMP (maaari mong ipagpalagay na n beses ang laki ng infile ay hindi lalampas sa 232 - 1) . Tukuyin kung aling mga field sa BITMAPFILEHEADER at BITMAPINFOHEADER ang kailangan mong baguhin. Isaalang-alang kung kailangan mong magdagdag o mag-alis ng mga field ng scanlines . At, oo, magpasalamat na hindi namin hinihiling sa iyo na isaalang-alang ang lahat ng posibleng halaga ng n mula 0 hanggang 1! (bagaman, kung interesado ka, ito ay isang problema mula sa libro ng isang hacker ;)). Gayunpaman, ipinapalagay namin na para sa n = 1 ang programa ay gagana nang tama at ang output file outfile ay magiging kapareho ng laki ng orihinal na infile. Gusto mo bang suriin ang program gamit ang check50? I-type ang sumusunod na command: ~cs50/pset4/resize
Buweno, kung gusto mong makita, halimbawa, ang mga
large.bmp header (sa isang mas madaling gamitin na anyo kaysa sa pinapayagan ng xxd), kailangan mong patakbuhin ang sumusunod na command:
~cs50/pset4/peek large.bmp
Mas mabuti, kung gusto mong ihambing ang iyong mga header na may mga header ng CS50 assistant file. Maaari kang magpatakbo ng mga utos sa loob ng iyong
~/workspace/pset4/bmp na direktoryo (isipin kung ano ang ginagawa ng bawat utos). Kung gumamit ka
ng malloc , siguraduhing gumamit
ng libre upang maiwasan ang mga pagtagas ng memorya. Subukang gumamit
ng valgrind upang suriin kung may mga tagas.
./resize 4 small.bmp student.bmp
~cs50/pset4/resize 4 small.bmp staff.bmp
~cs50/pset4/peek student.bmp staff.bmp
Paano magdesisyon?
-
Buksan ang file na kailangan nating palakihin, at lumikha at magbukas din ng bagong file kung saan ire-record ang pinalaki na imahe;
-
i-update ang impormasyon ng header para sa output file. Dahil ang aming imahe ay nasa BMP format at binabago namin ang laki nito, kailangan naming isulat ang header ng bagong file na may mga bagong sukat. Ano ang magbabago? Ang laki ng file, pati na rin ang laki ng imahe - ang lapad at taas nito.


-
Binabasa namin ang papalabas na file, linya sa linya, pixel bawat pixel. Upang gawin ito, muli kaming bumaling sa aming file I/O library at ang fread function. Kinakailangan ang isang pointer sa isang istraktura na naglalaman ng mga byte na nabasa, ang laki ng solong elemento na babasahin natin, ang bilang ng mga naturang elemento, at isang pointer sa file kung saan tayo magbabasa.
-
Pinapataas namin ang bawat linya nang pahalang ayon sa tinukoy na sukat, at isulat ang resulta sa output file.
Paano tayo magsusulat ng mga file? Mayroon kaming isang function na fwrite, kung saan ipinapasa namin ang isang tagapagpahiwatig sa istraktura kung saan matatagpuan ang data na isusulat sa file, ang laki ng elemento, ang kanilang numero at isang pointer sa output file. Upang ayusin ang loop, maaari naming gamitin ang para sa loop na pamilyar na sa amin .
-
Punan ang mga espasyo! Kung ang bilang ng mga pixel sa isang linya ay hindi multiple ng apat, dapat tayong magdagdag ng "alignment" - zero bytes. Kakailanganin namin ang isang formula upang makalkula ang laki ng pagkakahanay. Upang magsulat ng mga null byte sa isang output file, maaari mong gamitin ang function na fputc, na ipinapasa dito ang character na gusto mong isulat at isang pointer sa output file.
Ngayong naunat na natin ang string nang pahalang at nagdagdag ng alignment sa output file, kailangan nating ilipat ang kasalukuyang posisyon sa output file dahil kailangan nating tumalon sa alignment.
-
Palakihin ang vertical na laki. Mas kumplikado ito, ngunit magagamit natin ang sample code mula sa copy.c (binubuksan ng copy.c ang output file, nagsusulat ng header sa output file, binabasa ang imahe mula sa source file line by line, pixel by pixel, at isinusulat ang mga ito sa output file). Batay dito, ang unang bagay na maaari mong gawin ay patakbuhin ang sumusunod na command: cp copy.c resize.c
Upang i-stretch ang isang imahe nang patayo ay nangangahulugang kopyahin ang bawat linya nang maraming beses. Mayroong ilang iba't ibang paraan upang gawin ito. Halimbawa, gamit ang muling pagsulat, kapag nai-save namin ang lahat ng mga pixel ng isang linya sa memorya at isulat ang linyang ito sa output file sa isang loop nang maraming beses kung kinakailangan. Ang isa pang paraan ay muling pagkopya: pagkatapos basahin ang isang linya mula sa papalabas na file, isulat ito sa output file at ihanay ito, ibalik ang fseek function pabalik sa simula ng linya sa papalabas na file at ulitin muli ang lahat ng ilang beses.
-
Buksan ang file na may mga nilalaman ng memory card.
-
Hanapin ang simula ng JPEG file. Ang lahat ng mga file sa card na ito ay mga larawan sa JPEG na format.
gumaling
Bilang pag-asam sa papel ng problema sa Linggo 4, ginugol ko ang mga huling araw sa pagtingin sa mga larawang na-save sa format na JPEG ng aking digital camera sa isang 1 GB CompactFlash (CF) memory card. Mangyaring huwag sabihin sa akin na sa halip ay ginugol ko ang mga huling araw sa Facebook. Sa kasamaang palad, ang aking mga kasanayan sa computer ay nag-iiwan ng maraming nais, at nang hindi ko alam, hindi ko sinasadyang natanggal ang lahat ng mga larawan! Sa kabutihang palad, sa mundo ng computer, ang "tinanggal" ay karaniwang hindi katumbas ng "pinatay." Iginiit ng aking computer na ang memory card ay walang laman, ngunit alam kong nagsisinungaling ito. Takdang-aralin: Sumulat ng program sa ~/workspace/pset4/jpg/recover.c na magre-recover sa mga larawang ito. Hmmm. Okay, narito ang isa pang paglilinaw. Bagama't ang JPEG format ay mas kumplikado kaysa sa BMP, ang JPEG ay may "mga lagda," mga byte pattern na tumutulong na makilala ito mula sa iba pang mga format ng file. Karamihan sa mga JPEG file ay nagsisimula sa sumusunod na tatlong byte:0xff 0xd8 0xff
Mula sa unang byte hanggang sa pangatlo, mula kaliwa hanggang kanan. Ang ikaapat na byte ay malamang na isa sa mga sumusunod na kumbinasyon: 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,0xe8, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, 0xee, 0xed. Sa madaling salita, ang unang apat na bits ng ikaapat na byte ng isang JPEG file ay 1110. Malamang, kung makakita ka ng isa sa mga pattern na ito sa drive kung saan naka-imbak ang mga larawan (tulad ng aking memory card), ito ang magiging simula ng JPEG file. Siyempre, maaari mong makatagpo ito kung saan ang disk ay nagkataon lamang; ang pagbawi ng data ay hindi matatawag na isang eksaktong agham.
Paano magdesisyon



GO TO FULL VERSION