JavaRush /Java Blog /Random-TL /Harvard CS50: Linggo 4 na Takdang-aralin (Mga Lektura 9 a...
Masha
Antas

Harvard CS50: Linggo 4 na Takdang-aralin (Mga Lektura 9 at 10)

Nai-publish sa grupo
Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 1

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:
  1. Ilang kulay ang sinusuportahan ng bawat format?

  2. Aling format ang sumusuporta sa animation?

  3. Ano ang pagkakaiba sa pagitan ng lossy at lossless compression?

  4. Alin sa mga format na ito ang gumagamit ng lossy compression?

Ang mga nagsasalita ng Ingles ay pinapayuhan na sumangguni sa artikulo mula sa MIT . Kung pag-aaralan mo ito (o maghanap ng iba pang mapagkukunan sa Internet tungkol sa pag-iimbak ng mga file sa mga disk at file system), masasagot mo ang mga sumusunod na tanong:
  1. Ano ang mangyayari mula sa isang teknikal na punto ng view kapag ang isang file ay tinanggal sa isang FAT file system?

  2. Ano ang maaaring gawin upang matiyak (na may mataas na posibilidad) na ang mga tinanggal na file ay hindi na mababawi?

At ngayon - sa aming kuwento, na maayos na dumadaloy sa unang gawain ng ikaapat na linggo. Maligayang pagdating sa Tudor Mansion! Bigla kaming iniwan ng may-ari ng ari-arian na si Mr. John Boddy, na naging biktima ng hindi kilalang laro. Upang malaman kung ano ang nangyari, dapat mong tukuyin kung sino . Sa kasamaang palad para sa iyo (kahit na higit pa sa kasamaang palad para kay Mr. Boddy), ang tanging ebidensya na mayroon ka ay ang 24-bit na BMP file clue.bmp . Ito ang mga nilalaman nito na makikita mo sa ibaba. Nagawa at nai-save ito ni Mr. Boddy sa kanyang computer sa kanyang mga huling sandali. Ang file ay naglalaman ng isang whodunit na imahe na nakatago sa pulang ingay . Ngayon ay kailangan mong magtrabaho sa solusyon tulad ng isang tunay na teknikal na espesyalista. Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 2Ngunit una, ilang impormasyon. Malamang na pinakamadaling isipin ang isang imahe bilang isang grid ng mga pixel (mga tuldok, iyon ay), ang bawat isa ay maaaring isang partikular na kulay. Upang itakda ang kulay ng isang punto sa isang itim at puting imahe, kailangan namin ng 1 bit. Ang 0 ay maaaring kumatawan sa itim at ang 1 ay maaaring kumatawan sa puti tulad ng ipinapakita sa larawan sa ibaba. Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 3Kaya, ang mga imaheng kinakatawan sa ganitong paraan ay isang mapa lamang ng mga bit (bitmap o bitmap, gaya ng sinasabi nila sa Ingles o slang). Sa itim at puti ang lahat ay kasing simple hangga't maaari, ngunit upang makakuha ng mga larawang may kulay kailangan lang namin ng higit pang mga bit bawat pixel. Ang isang format ng file (gaya ng GIF) na sumusuporta sa "8-bit na kulay" ay gumagamit ng 8 bits bawat pixel. Ang isang format ng file (hal., BMP, JPG, PNG) na sumusuporta sa "24-bit na kulay" ay gumagamit ng 24 bits bawat pixel (talagang sinusuportahan ng BMP ang 1-, 4-, 8-, 16-, 24-, at 32-bit na kulay) . Sa 24-bit na BMP na ginagamit ni Mr. Boddy, kailangan ng 8 bits upang ipahiwatig ang dami ng pula, ang parehong halaga para sa berde, at muli 8 bits upang isaad ang dami ng asul sa bawat pixel. Kung narinig mo na ang mga kulay ng RGB , ito na (R=red, G=green, B=blue). Kung ang halaga ng R, G, at B ng ilang pixel sa BMP ay, sabihin nating, 0xff, 0x00, at 0x00 sa hexadecimal, kung gayon ang pixel ay magiging purong pula, dahil ang 0xff (na kilala bilang 255 sa decimal) ay nangangahulugang "maraming pula " sa oras na iyon bilang 0x00 at 0x00 ay nangangahulugang "walang berde" at "asul din ang mga zero", ayon sa pagkakabanggit. Dahil sa kung paano lumilitaw sa amin ang pulang imahe ng BMP ni Mr. Boddy, intuitive na ang pulang "compartment" ay may malinaw na mas malaking halaga kaysa sa pula at asul na "compartment." Gayunpaman, hindi lahat ng pixel ay pula; ang ilan ay malinaw na may ibang kulay. Sa pamamagitan ng paraan, sa HTML at CSS (ang markup language at mga style sheet na tumutulong dito, na ginagamit upang lumikha ng mga web page), ang mga modelo ng kulay ay nakaayos sa parehong paraan. Kung interesado, tingnan ang link: https://ru.wikipedia.org/wiki/Colors_HTMLpara sa karagdagang detalye. Ngayon lapitan natin ang problema nang mas teknikal. Alalahanin na ang isang file ay simpleng pagkakasunud-sunod ng mga bit na nakaayos sa ilang pagkakasunud-sunod. Ang isang 24-bit na BMP file ay isang pagkakasunud-sunod ng mga bit, bawat 24 nito (well, halos) ay tumutukoy sa kulay ng kung aling pixel. Bilang karagdagan sa data ng kulay, naglalaman din ang isang BMP file ng metadata - impormasyon tungkol sa lapad at taas ng larawan. Ang metadata na ito ay naka-imbak sa simula ng file sa anyo ng dalawang istruktura ng data na karaniwang tinatawag na "mga header" (hindi dapat malito sa mga C header file). Ang una sa mga header na ito ay BITMAPFILEHEADER, na 14 byte ang haba (o 14*8 bits). Ang pangalawang header ay BITMAPINFOHEADER (40 bytes ang haba). Pagkatapos ng mga header na ito, darating ang bitmap: isang hanay ng mga byte, ang mga triplet na kumakatawan sa kulay ng pixel (1, 4 at 16-bit sa BMP, ngunit hindi 24 o 32, mayroon silang karagdagang header pagkatapos mismo ng BITMAPINFOHEADER. Ito ay tinatawag na ang RGBQUAD array, na tumutukoy sa "intensity value" para sa bawat isa sa mga kulay sa palette). Gayunpaman, iniimbak ng BMP ang mga triplet na ito nang baligtad (masasabi nating tulad ng BGR), na may 8 bits para sa asul, 8 bits para sa berde, at 8 bits para sa pula. Siyanga pala, iniimbak din ng ilang BMP ang buong bitmap pabalik, simula sa tuktok na linya ng imahe sa dulo ng BMP file. Sa aming gawain, na-save namin ang VMR tulad ng inilarawan dito, una ang tuktok na hilera ng imahe, pagkatapos ay ang mga ibaba. Sa madaling salita, ginawa naming 24-bit ang isang one-bit na emoji sa pamamagitan ng pagpapalit ng itim ng pula. Ang isang 24-bit na BMP ay mag-iimbak ng bitmap na ito, kung saan ang 0000ff ay kumakatawan sa pula at ang ffffff ay kumakatawan sa puti; na-highlight namin ang lahat ng pagkakataon ng 0000ff sa pula. Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 4Dahil ipinakita namin ang mga pirasong ito mula kaliwa hanggang kanan, itaas hanggang ibaba, makikita mo ang pulang smiley na mukha sa mga titik na ito kung lalayo ka nang kaunti sa monitor. Alalahanin na ang isang digit sa sistema ng hexadecimal na numero ay kumakatawan sa 4 na bits. Alinsunod dito, ang ffffff sa hexadecimal ay talagang nangangahulugang 11111111111111111111111111 sa binary. Ngayon, dahan-dahan, at huwag nang magpatuloy hanggang sa sigurado ka na naiintindihan mo kung bakit kumakatawan ang 0000ff ng pulang pixel sa isang 24-bit na BMP file. Sa window ng CS50 IDE, palawakin (halimbawa, sa pamamagitan ng pag-click sa maliit na tatsulok) ang pset4 folder , at sa loob nito - bmp . Sa folder na ito makikita mo ang smiley.bmp , i-double click ang file at makakakita ka ng maliit na 8x8 pixel na smiley doon. Sa drop-down na menu, baguhin ang sukat ng imahe, sabihin nating mula 100% hanggang 400%, ito ay magbibigay-daan sa iyong makakita ng mas malaki, ngunit sa parehong oras ay mas "malabo" na bersyon ng emoticon. Bagama't sa katotohanan ang parehong imaheng ito ay hindi dapat malabo kahit na pinalaki. Ito ay lamang na ang CS50 IDE ay sinusubukan na gawin sa iyo ng isang pabor (sa estilo ng CIA serye) sa pamamagitan ng smoothing ang larawan (visual blurring ang mga gilid). Ganito ang magiging hitsura ng ating smiley kung palakihin natin ito nang hindi nagpapakinis: Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 5Ang mga pixel ay naging malalaking parisukat. Ituloy natin. Sa terminal pumunta sa ~/workspace/pset4/bmp . Sa tingin namin ay naaalala mo na kung paano ito gawin. Suriin natin ang mga inilaan na byte sa smiley.bmp . Magagawa ito gamit ang command line hex editor, ang xxd program . Upang patakbuhin ito, patakbuhin ang utos: 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. Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 6Sa larawan sa pinakakaliwang column makikita mo ang mga address sa file, na katumbas ng offset mula sa unang byte ng file. Lahat ng mga ito ay ibinigay sa hexadecimal number system. Kung iko-convert natin ang hexadecimal 00000036 sa decimal, makakakuha tayo ng 54. Kaya't tinitingnan mo ang ika-54 na byte mula sa smiley.bmp . Alalahanin na sa 24-bit na BMP file, ang unang 14 + 40 = 54 byte ay puno ng metadata. Kaya kung gusto mong makita ang metadata, patakbuhin ang sumusunod na command: 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. Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 7Ang bawat linya sa small.bmp ay sumasakop sa (3 pixels) × (3 bytes bawat pixel) = 9 bytes, na hindi isang multiple ng 4. Upang makakuha ng haba ng linya na multiple ng 4, ito ay may padded na may karagdagang mga zero: sa pagitan ng 0 at 3 byte ay pinupuno namin ang bawat linya sa 24-bit na BMP na format (mahuhulaan mo ba kung bakit ganoon?). Para sa small.bmp , 3 byte ng mga zero ang kailangan, dahil (3 pixels) x (3 bytes bawat pixel) + (3 bytes ng padding) = 12 bytes, na talagang isang multiple ng 4. Upang "makita" ang padding na ito, gawin ang sumusunod. 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. Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 8Para sa kaibahan, gamitin natin ang xxd para sa large.bmp file . Kamukha ito ng small.bmp, tanging ang resolution nito ay 12x12 pixels, ibig sabihin, apat na beses na mas malaki. Patakbuhin ang command sa ibaba. Maaaring kailanganin mong palawakin ang window para maiwasan ang paglipat. xxd -c 36 -g 3 -s 54 large.bmp Makakakita ka ng ganito: Harvard CS50: Linggo 4 na Takdang-aralin (Mga Lektura 9 at 10) - 9Pakitandaan, walang mga digression sa BMP na ito! Pagkatapos ng lahat, (12 pixels) × (3 bytes bawat pixel) = 36 bytes, at ito ay isang multiple ng 4. Ipinakita sa amin ng xxd hex editor ang mga byte sa aming mga BMP file. Paano natin makukuha ang mga ito sa programmatically? Sa copy.c mayroong isang programa na ang tanging layunin sa buhay ay lumikha ng isang kopya ng BMP, pira-piraso. Oo, maaari mong gamitin ang cp para dito . Gayunpaman, hindi matutulungan ng cp si Mr. Boddy. Sana magawa ito ng copy.c , kaya narito: ./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: Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 10Makikita natin na mahalaga ang order pagdating sa mga miyembro ng structs. Ang Byte 57 ay rgbtBlue (hindi, sabihin nating, rgbtRed) dahil ang rgbtBlue ay tinukoy sa RGBTRIPLE muna. Siyanga pala, tinitiyak ng aming paggamit ng naka-pack na katangian na hindi sinusubukan ng clang na "i-align ng salita" ang mga miyembro (na ang address ng unang byte ng bawat miyembro ay multiple ng 4), upang hindi tayo magkaroon ng mga butas sa ang aming mga istraktura na hindi umiiral sa disk sa lahat. Mag-move on na tayo. Hanapin ang mga URL na tumutugma sa BITMAPFILEHEADER at BITMAPINFOHEADER, ayon sa mga komento sa bmp.h. Pansin, magandang sandali: nagsisimula kang gumamit ng MSDN (Microsoft Developer Network)! Sa halip na mag-scroll pa sa copy.c , sagutin ang ilang tanong para maunawaan kung paano gumagana ang code. Gaya ng dati, ang man command ay ang iyong tunay na kaibigan, at ngayon din MSDN. Kung hindi mo alam ang mga sagot, i-Google ito at pag-isipan ito. Maaari ka ring sumangguni sa stdio.h file sa https://reference.cs50.net/.
  1. Magtakda ng breakpoint sa main (sa pamamagitan ng pag-click sa kaliwa ng ruler na may mga pangunahing numero ng linya).

  2. Sa isang tab na terminal , pumunta sa ~/workspace/pset4/bmp , at i-compile ang copy.c sa copy program gamit ang make.

  3. Patakbuhin ang debug50 copy smiley.bmp copy.bmp , bubuksan nito ang panel ng debugger sa kanan.

  4. 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: check50 2015.fall.pset4.resize bmp.h resize.c Gusto mo bang laruin ang pagpapatupad ng application na ginawa ng CS50 assistants? Patakbuhin ang sumusunod: ~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.

Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 11Kung titingnan natin ang paglalarawan ng header, makikita natin ang variable na biSizeImage . Ipinapahiwatig nito ang kabuuang sukat ng imahe sa mga byte, ang biWidth ay ang lapad ng imahe na minus alignment, ang biHeight ay ang taas. Ang mga variable na ito ay matatagpuan sa mga istruktura ng BITMAPFILEHEADER at BITMAPINFOHEADER. Mahahanap mo ang mga ito kung bubuksan mo ang bmp.h file . Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 12Ang paglalarawan ng istraktura ng BITMAPINFOHEADER ay naglalaman ng isang listahan ng mga variable. Upang isulat ang pamagat ng output file, kakailanganin mong baguhin ang mga halaga ng taas at lapad. Ngunit mayroon ding pagkakataon na sa ibang pagkakataon kakailanganin mo ang orihinal na taas at lapad ng orihinal na file. Samakatuwid, ito ay mas mahusay na panatilihin ang pareho. Mag-ingat sa mga variable na pangalan upang hindi mo sinasadyang magsulat ng maling data sa header ng output file.
  • 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.

    Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 13
  • Pinapataas namin ang bawat linya nang pahalang ayon sa tinukoy na sukat, at isulat ang resulta sa output file.

    Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 14

    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 .

    Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 15
  • 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.

    Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 16

    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.

    Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 17
  • 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.

    Harvard CS50: Linggo 4 na Takdang-aralin (Mga Lektura 9 at 10) - 18
  • 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

    1. Buksan ang file na may mga nilalaman ng memory card.

    2. Hanapin ang simula ng JPEG file. Ang lahat ng mga file sa card na ito ay mga larawan sa JPEG na format.

    Alam mo na ang tungkol sa mga JPEG marker: Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 19Mahalaga (at maganda) na malaman na ang bawat JPEG file ay naka-imbak sa memorya bilang isang bloke, at ang mga file mismo ay sumusunod sa isa't isa. Gumuhit tayo ng isang schematic memory map. Ang bawat parihaba ay isang bloke na 512 bytes ang haba. Ang mga gray na parihaba ay mga lugar kung saan walang mga JPEG file; ang mga asterisk ay nagpapahiwatig ng simula ng JPEG file. Naniniwala kami na wala kaming kulay abong mga bloke sa pagitan ng mga file. Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 20Paano natin babasahin ang data na ito, ang 512 byte na ito, upang ihambing ang simula nito sa header ng JPEG? Magagamit natin ang function ng fread , na pamilyar na sa atin, na kumukuha ng pointer sa istruktura ng data kung saan isusulat ang mga read byte, pati na rin ang laki ng elementong binabasa, ang bilang ng mga naturang elemento, at isang pointer sa file kung saan namin binabasa ang data. Harvard CS50: Ikaapat na Linggo ng mga Takdang-aralin (Mga Lektura 9 at 10) - 21Gusto naming basahin ang 512 bytes at iimbak ang mga ito sa isang buffer. Ito ang magiging &data pointer, at ang inptr pointer ay ituturo sa bukas na file na may mga nilalaman ng memory card. Kaya, bumalik tayo sa istraktura ng aming file, kung saan kami nagse-save
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION