การเตรียมงาน
เช่นเคย ก่อนอื่นให้เปิดหน้าต่างเทอร์มินัลแล้วรันคำสั่งupdate50
เพื่อให้แน่ใจว่าใบสมัครของคุณเป็นข้อมูลล่าสุดอยู่แล้ว ก่อนที่คุณจะเริ่มต้น ให้ปฏิบัติตามสิ่งนี้ cd ~ / workspace
wget http://cdn.cs50.net/2015/fall/psets/4/pset4/pset4.zip
เพื่อดาวน์โหลดไฟล์ ZIP ของงานนี้ ตอนนี้ถ้าคุณรันls คุณ จะเห็นว่ามีไฟล์ชื่อpset4.zipอยู่ใน ไดเร็กทอรี ~/workspace ของคุณ แยกออกโดยใช้คำสั่ง: หากคุณรันคำสั่ง lsunzip pset4.zip
อีกครั้งคุณจะเห็นว่ามีไดเร็กทอรีอื่นปรากฏขึ้น ตอนนี้คุณสามารถลบไฟล์ zip ได้ตามที่แสดงด้านล่าง: มาเปิด ไดเร็กทอรี pset4 รันlsและตรวจสอบให้แน่ใจว่าไดเร็กทอรีมี rm -f pset4.zip
cd pset4
bmp / jpg / questions.txt
whodunit หรือ "ใครทำสิ่งนี้"
หากคุณเคยเห็นเดสก์ท็อป Windows XP เริ่มต้น (https://en.wikipedia.org/wiki/Bliss_(image)) (เนินเขาและท้องฟ้าสีคราม) แสดงว่าคุณเคยเห็น BMP แล้ว บนหน้าเว็บ คุณน่าจะเคยเห็น GIF มาก่อน คุณเคยดูภาพถ่ายดิจิทัลหรือไม่? ดังนั้นเราจึงมีความสุขที่ได้เห็น JPEG หากคุณเคยจับภาพหน้าจอบน Mac คุณน่าจะเคยเห็น PNG อ่านบนอินเทอร์เน็ตเกี่ยวกับรูปแบบ BMP, GIF, JPEG, PNG และตอบคำถามเหล่านี้:-
แต่ละรูปแบบรองรับกี่สี?
-
รูปแบบใดที่รองรับแอนิเมชั่น?
-
การบีบอัดแบบ lossy และ lossless แตกต่างกันอย่างไร?
-
รูปแบบใดต่อไปนี้ใช้การบีบอัดแบบสูญเสียข้อมูล
-
จะเกิดอะไรขึ้นจากมุมมองทางเทคนิคเมื่อไฟล์ถูกลบในระบบไฟล์ FAT
-
สิ่งที่สามารถทำได้เพื่อให้แน่ใจว่า (มีความเป็นไปได้สูง) ว่าไฟล์ที่ถูกลบไม่สามารถกู้คืนได้?
xxd -c 24 -g 3 -s 54 smiley.bmp
คุณควรเห็นสิ่งที่แสดงด้านล่าง เราได้เน้นสีแดงอีกครั้งทุกกรณีของ 0000ff ในรูปภาพในคอลัมน์ซ้ายสุด คุณจะเห็นที่อยู่ในไฟล์ ซึ่งเทียบเท่ากับออฟเซ็ตจากไบต์แรกของไฟล์ ทั้งหมดถูกกำหนดไว้ในระบบเลขฐานสิบหก ถ้าเราแปลงเลข ฐานสิบหก 00000036 เป็นทศนิยม เราจะได้ 54 ดังนั้นคุณกำลังดูไบต์ที่ 54 จากsmiley.bmp โปรดจำไว้ว่าในไฟล์ BMP 24 บิต 14 + 40 = 54 ไบต์แรกจะถูกเติมด้วยข้อมูลเมตา ดังนั้นหากคุณต้องการดูข้อมูลเมตา ให้รันคำสั่งต่อไปนี้: xxd -c 24 -g 3 smiley.bmp
หากsmiley.bmpมีอักขระ ASCIIเราจะเห็นอักขระเหล่านั้นในคอลัมน์ขวาสุดในหน่วย xxd แทนที่จะเป็นจุดทั้งหมด ดังนั้น สไมลี่จึงเป็น BMP 24 บิต (แต่ละพิกเซลแทนด้วย 24 ÷ 8 = 3 ไบต์) โดยมีขนาด (ความละเอียด) 8x8 พิกเซล แต่ละบรรทัด (หรือ "สแกนไลน์" ตามที่เรียกว่า) จึงใช้ (8 พิกเซล) x (3 ไบต์ต่อพิกเซล) = 24 ไบต์ จำนวนนี้คือผลคูณของสี่ และเป็นสิ่งสำคัญเนื่องจากไฟล์ BMP จะถูกจัดเก็บแตกต่างออกไปเล็กน้อยหากจำนวนไบต์ในบรรทัดไม่ใช่ผลคูณของสี่ ดังนั้น ใน Small.bmp ซึ่งเป็นไฟล์ BMP 24 บิตอีกไฟล์ในโฟลเดอร์ของเรา คุณจะเห็นกล่องพิกเซลสีเขียวขนาด 3x3 หากคุณเปิดมันในโปรแกรมดูรูปภาพ คุณจะเห็นว่ามันคล้ายกับภาพที่แสดงด้านล่าง แต่มีขนาดเล็กกว่าเท่านั้น แต่ละบรรทัดในsmall.bmpจึงใช้พื้นที่ (3 พิกเซล) × (3 ไบต์ต่อพิกเซล) = 9 ไบต์ ซึ่งไม่ใช่ผลคูณของ 4 หากต้องการรับความยาวของบรรทัดที่เป็นผลคูณของ 4 บรรทัดนั้นจะถูกเติมด้วยศูนย์เพิ่มเติม: ระหว่าง 0 ถึง 3 ไบต์ เราเติมแต่ละบรรทัดในรูปแบบ BMP 24 บิต (คุณเดาได้ไหมว่าทำไมถึงเป็นเช่นนั้น) สำหรับsmall.bmpจำเป็นต้องมีศูนย์ 3 ไบต์ เนื่องจาก (3 พิกเซล) x (3 ไบต์ต่อพิกเซล) + (ช่องว่างภายใน 3 ไบต์) = 12 ไบต์ ซึ่งก็คือผลคูณของ 4 จริงๆ หากต้องการ "ดู" ช่องว่างภายในนี้ ทำสิ่งต่อไปนี้ xxd -c 12 -g 3 -s 54 small.bmp
โปรดทราบว่าเราใช้ค่าที่แตกต่างกันสำหรับ-cมากกว่ากับsmiley.bmpดังนั้น xxd จึงส่งออกเพียง 4 คอลัมน์ในครั้งนี้ (3 สำหรับสี่เหลี่ยมสีเขียวและ 1 สำหรับช่องว่างภายใน) เพื่อความชัดเจน เราได้เน้นอินสแตนซ์ทั้งหมดของ 00ff00 เป็นสีเขียว ในทางตรงกันข้าม ลองใช้ xxd สำหรับไฟล์large.bmp มันดูเหมือนกับsmall.bmp ทุกประการมีเพียงความละเอียดเท่านั้นคือ 12x12 พิกเซล ซึ่งก็คือใหญ่กว่าสี่เท่า รันคำสั่งด้านล่าง คุณอาจต้องขยายหน้าต่างเพื่อหลีกเลี่ยงการถ่ายโอน xxd -c 36 -g 3 -s 54 large.bmp
คุณจะเห็นข้อความดังนี้: โปรดทราบว่า BMP นี้ไม่มีการถดถอย! ท้ายที่สุดแล้ว (12 พิกเซล) × (3 ไบต์ต่อพิกเซล) = 36 ไบต์ และนี่คือผลคูณของ 4 โปรแกรมแก้ไข xxd hex แสดงจำนวนไบต์ในไฟล์ BMP ของเรา เราจะรับพวกมันโดยทางโปรแกรมได้อย่างไร? ในcopy.cมีโปรแกรมหนึ่งที่มีวัตถุประสงค์ในชีวิตเพียงอย่างเดียวคือการสร้างสำเนาของ BMP ทีละชิ้น ใช่ คุณสามารถใช้cp สำหรับสิ่ง นี้ อย่างไรก็ตามซีพีไม่สามารถช่วยเหลือคุณบอดดี้ได้ หวังว่าcopy.cจะทำสิ่งนี้ ลุยเลย: ./copy smiley.bmp copy.bmp
หากคุณเรียกใช้ls (ด้วยแฟล็กที่เหมาะสม) คุณจะเห็นว่าsmiley.bmpและcopy.bmpมีขนาดเท่ากันจริงๆ มาตรวจสอบอีกครั้งว่าจริงหรือไม่? diff smiley.bmp copy.bmp
หากคำสั่งนี้ไม่แสดงสิ่งใดบนหน้าจอ แสดงว่าไฟล์นั้นเหมือนกันทุกประการ (สำคัญ: บางโปรแกรม เช่น Photoshop มีเลขศูนย์ต่อท้ายที่ส่วนท้ายของ VMP บางรายการ เวอร์ชันสำเนาของเราจะละทิ้งมัน ดังนั้นอย่า กังวลว่าในกรณีที่คัดลอก BMP อื่นๆ ที่คุณดาวน์โหลดหรือสร้างขึ้นเพื่อการทดสอบ สำเนาจะมีขนาดเล็กกว่าต้นฉบับสองสามไบต์) คุณสามารถเปิดทั้งสองไฟล์ในโปรแกรมดูรูปภาพของ Ristretto (ดับเบิลคลิก) เพื่อยืนยันสิ่งนี้ด้วยสายตา แต่การเปรียบเทียบนี้ต่างกันทีละไบต์ ดังนั้นการมองเห็นของเธอจึงคมชัดกว่าของคุณ! สำเนานี้ถูกสร้างขึ้นมาอย่างไร? ปรากฎว่าcopy.c เกี่ยวข้องกับbmp.h มาตรวจสอบให้แน่ใจกัน: เปิดbmp.h. คุณจะเห็นคำจำกัดความที่แท้จริงของส่วนหัวที่เราได้กล่าวไปแล้ว ซึ่งดัดแปลงมาจากการใช้งานของ Microsoft นอกจากนี้ ไฟล์นี้ยังกำหนดประเภทข้อมูล BYTE, DWORD, LONG และ WORD ซึ่งเป็นประเภทข้อมูลที่พบโดยทั่วไปในโลกของการเขียนโปรแกรม Win32 (เช่น Windows) โปรดทราบว่าสิ่งเหล่านี้เป็นนามแฝงโดยพื้นฐานสำหรับคำดั้งเดิมที่คุณ (หวังว่า) คุ้นเคยอยู่แล้ว ปรากฎว่า BITMAPFILEHEADER และ BITMAPINFOHEADER กำลังใช้ประเภทเหล่านี้ ไฟล์นี้ยังกำหนดโครงสร้างที่เรียกว่า RGBTRIPLE มัน "ห่อหุ้ม" สามไบต์: หนึ่งสีน้ำเงิน, หนึ่งสีเขียวและหนึ่งสีแดง (นี่คือลำดับที่เราจะค้นหา RGB triplets บนดิสก์) โครงสร้างเหล่านี้มีประโยชน์อย่างไร? สรุป ไฟล์เป็นเพียงลำดับของไบต์ (หรือบิตสุดท้าย) บนดิสก์ อย่างไรก็ตาม โดยปกติแล้วไบต์เหล่านี้จะถูกเรียงลำดับเพื่อให้สองสามไบต์แรกแทนบางสิ่ง จากนั้นสองสามไบต์ถัดไปแทนสิ่งอื่น และอื่นๆ ไฟล์ "รูปแบบ" มีอยู่เพราะเรามีมาตรฐานหรือกฎเกณฑ์ที่กำหนดว่าไบต์หมายถึงอะไร ตอนนี้เราสามารถอ่านไฟล์จากดิสก์ลงใน RAM ในรูปแบบอาร์เรย์ไบต์ขนาดใหญ่ได้ และเราจำได้ว่าไบต์ที่ตำแหน่ง [i] เป็นตัวแทนสิ่งหนึ่ง ในขณะที่ไบต์ที่ตำแหน่ง [j] เป็นอย่างอื่น แต่ทำไมไม่ระบุชื่อไบต์เหล่านี้บางส่วนเพื่อให้เราสามารถดึงข้อมูลจากหน่วยความจำได้ง่ายขึ้น นี่คือสิ่งที่โครงสร้างใน bmp.h ช่วยเราจริงๆ แทนที่จะคิดว่าไฟล์เป็นลำดับไบต์ยาวๆ ลำดับเดียว เราจะเห็นว่าไฟล์แบ่งออกเป็นบล็อกที่เข้าใจได้มากขึ้น นั่นก็คือ ลำดับของโครงสร้าง จำได้ว่าsmiley.bmpมีความละเอียด 8x8 พิกเซล ดังนั้นจึงใช้พื้นที่ 14 + 40 + (8 × 8) × 3 = 246 ไบต์บนดิสก์ (คุณสามารถตรวจสอบได้โดยใช้คำสั่ง ls) ต่อไปนี้คือลักษณะที่ปรากฏบนดิสก์ตามข้อมูลของ Microsoft: เราจะเห็นว่าลำดับนั้นมีความสำคัญเมื่อพูดถึงสมาชิกของโครงสร้าง ไบต์ 57 คือ rgbtBlue (ไม่ใช่พูด rgbtRed) เนื่องจาก rgbtBlue ถูกกำหนดไว้ใน RGBTRIPLE ก่อน อย่างไรก็ตาม การใช้แอ็ตทริบิวต์ที่แพ็คของเราทำให้มั่นใจได้ว่าเสียงดังกราวจะไม่พยายาม "จัดเรียงคำ" สมาชิก (โดยที่อยู่ของไบต์แรกของสมาชิกแต่ละคนเป็นผลคูณของ 4) เพื่อที่เราจะได้ไม่จบลงด้วยช่องโหว่ใน โครงสร้างของเราที่ไม่มีอยู่บนดิสก์เลย เดินหน้าต่อไป ค้นหา URL ที่ตรงกับ BITMAPFILEHEADER และ BITMAPINFOHEADER ตามความคิดเห็นใน bmp.h โปรดทราบ ช่วงเวลาที่ยอดเยี่ยม: คุณเริ่มใช้ MSDN (Microsoft Developer Network)! แทนที่จะเลื่อนดูผ่านcopy.c เพิ่มเติม ให้ตอบคำถามสองสามข้อเพื่อทำความเข้าใจวิธีการทำงานของโค้ด เช่นเคย คำสั่ง man คือเพื่อนแท้ของคุณ และตอนนี้ก็รวมถึง MSDN ด้วย ถ้าไม่รู้คำตอบก็ Google แล้วลองคิดดู คุณยังสามารถอ้างถึงไฟล์ stdio.h ได้ที่ https://reference.cs50.net/
-
ตั้งค่าเบรกพอยต์ใน main (โดยคลิกทางด้านซ้ายของไม้บรรทัดที่มีหมายเลขบรรทัดหลัก)
-
ในแท็บ เทอร์มินัล ให้ไปที่~/workspace/pset4/bmpและคอมไพล์ copy.c ลงในโปรแกรมคัดลอกโดยใช้ make
-
เรียกใช้debug50 copy smiley.bmp copy.bmpซึ่งจะเปิดแผงดีบักเกอร์ทางด้านขวา
-
เดินผ่านโปรแกรมทีละขั้นตอนโดยใช้แผงทางด้านขวา หมายเหตุbfและbi _ ใน~/workspace/pset4/questions.txtให้ตอบคำถาม:
-
stdint.hคืออะไร?
-
จุดประสงค์ของการใช้uint8_t , uint32_t , int32_tและuint16_tในโปรแกรมคืออะไร?
-
BYTE , DWORD , LONGและWORD มี กี่ไบต์ตามลำดับ (สมมติว่าสถาปัตยกรรม 32 บิต)
- สองไบต์แรกของไฟล์ BMP ควรเป็นอย่างไร (ASCII, ทศนิยมหรือฐานสิบหก) (ไบต์นำซึ่งใช้ในการระบุรูปแบบไฟล์ (ที่มีความน่าจะเป็นสูง) มักเรียกว่า "ตัวเลขมหัศจรรย์")
-
bfSize และ biSize แตกต่างกันอย่างไร
-
BiHeight ที่เป็นลบหมายถึงอะไร
-
ฟิลด์ใดใน BITMAPINFOHEADER กำหนดความลึกของสีใน BMP (เช่น บิตต่อพิกเซล)
-
เหตุใดฟังก์ชัน fopen จึงสามารถส่งคืน NULL ใน copy.c 37 ได้
-
เหตุใดอาร์กิวเมนต์ที่สามที่ต้องอ่านในโค้ดของเราจึงเท่ากับ 1
-
ค่าใดใน copy.c 70 กำหนดช่องว่างภายในถ้า bi.biWidth คือ 3
-
fseek ทำอะไร?
-
SEEK_CUR คืออะไร?
กลับไปหาคุณบ๊อดดี้ ออกกำลังกาย:
เขียนโปรแกรมชื่อwhodunitในไฟล์ชื่อwhodunit.cที่แสดงภาพวาดของ Mr. Boddy อืม อะไรนะ? เช่นเดียวกับการคัดลอก โปรแกรมจะต้องรับอาร์กิวเมนต์บรรทัดคำสั่งสองตัวพอดี และหากคุณรันโปรแกรมตามที่แสดงด้านล่าง ผลลัพธ์จะถูกเก็บไว้ใน verdict.bmp ซึ่งรูปวาดของ Mr. Boddy จะไม่ส่งเสียงดัง./whodunit clue.bmp verdict.b
เราขอแนะนำให้คุณเริ่มไขปริศนานี้ด้วยการรันคำสั่งด้านล่าง cp copy.c whodunit.c
คุณอาจประหลาดใจกับจำนวนโค้ดที่คุณต้องเขียนเพื่อช่วย Mr. Boddy ไม่มีอะไรที่ไม่จำเป็นซ่อนอยู่ ในsmiley.bmpดังนั้นอย่าลังเลที่จะทดสอบโปรแกรมในไฟล์นี้ มันมีขนาดเล็ก และคุณสามารถเปรียบเทียบผลลัพธ์ของโปรแกรมของคุณกับผลลัพธ์ของ xxd ในระหว่างการพัฒนาได้ (หรืออาจมีบางอย่างซ่อนอยู่ในsmiley.bmpจริง ๆ แล้วไม่มี) อย่างไรก็ตามปัญหานี้สามารถแก้ไขได้หลายวิธี เมื่อคุณระบุภาพวาดของคุณบอดดี้ได้แล้ว เขาจะพักผ่อนอย่างสงบ เนื่องจากwhodunitสามารถนำไปใช้ได้หลายวิธี คุณจะไม่สามารถตรวจสอบความถูกต้องของการใช้งานด้วยcheck50ได้ และปล่อยให้มันเสียความ สนุกของคุณ แต่วิธีแก้ปัญหาของผู้ช่วยก็ไม่สามารถใช้ได้สำหรับ ปัญหา การสืบสวน สุดท้ายนี้ ในไฟล์In ~/workspace/pset4/questions.txtให้ตอบคำถามต่อไปนี้: Whodunit? //ктоэтосделал?
ปรับขนาด
ตอนนี้ - การทดสอบครั้งต่อไป! มาเขียนโปรแกรมชื่อ resizeใน resize.c กันดีกว่า มันจะปรับขนาดอิมเมจ BMP 24 บิตที่ไม่มีการบีบอัดในขั้นตอนที่ n แอปพลิเคชันของคุณต้องยอมรับอาร์กิวเมนต์บรรทัดคำสั่งสามรายการเท่านั้น โดยอาร์กิวเมนต์แรก (n) เป็นจำนวนเต็มไม่เกิน 100 อาร์กิวเมนต์ที่สองเป็นชื่อของไฟล์ที่จะได้รับการแก้ไข และตัวที่สามเป็นชื่อของเวอร์ชันที่บันทึกไว้ของเวอร์ชันแก้ไข ไฟล์.Usage: ./resize n infile outfile
ด้วยโปรแกรมดังกล่าว เราสามารถสร้าง large.bmp จาก small.bmp โดยการปรับขนาดอันหลังด้วย 4 (เช่น คูณทั้งความกว้างและความสูงด้วย 4) ดังที่แสดงด้านล่าง เพื่อความง่าย คุณสามารถเริ่มงานได้ด้วยการคัดลอก copy.c./resize 4 small.bmp large.bmp
อีกครั้งและตั้งชื่อสำเนาresize.c แต่ก่อนอื่น ให้ถามตัวเองและตอบคำถามเหล่านี้: การเปลี่ยนขนาด BMP หมายความว่าอย่างไร (คุณสามารถสรุปได้ว่า n คูณขนาดไฟล์จะไม่เกิน 232 - 1 ) กำหนดเขตข้อมูลใน BITMAPFILEHEADER และ BITMAPINFOHEADER ที่คุณต้องการเปลี่ยนแปลง พิจารณาว่าคุณจำเป็นต้องเพิ่มหรือลบฟิลด์scanlines และใช่ จงขอบคุณที่เราไม่ได้ขอให้คุณพิจารณาค่าที่เป็นไปได้ทั้งหมดของ n จาก 0 ถึง 1! (แม้ว่าหากคุณสนใจ นี่เป็นปัญหาจากหนังสือของแฮ็กเกอร์ ;)) อย่างไรก็ตาม เราถือว่าสำหรับ n = 1 โปรแกรมจะทำงานได้อย่างถูกต้อง และoutfile ของไฟล์เอาต์พุต จะมีขนาดเท่ากับ infile ดั้งเดิม คุณต้องการตรวจสอบโปรแกรมโดยใช้ check50 หรือไม่? พิมพ์คำสั่งต่อไปนี้: ~cs50/pset4/resize
เช่น(ในรูปแบบที่ใช้งานง่ายกว่าที่ xxd อนุญาต) คุณต้องเรียกใช้คำสั่งต่อไปนี้: ดียิ่งขึ้นถ้าคุณต้องการเปรียบเทียบของคุณ ส่วนหัวที่มีส่วนหัวของไฟล์ผู้ช่วย CS50 คุณสามารถรันคำสั่งภายใน ไดเร็กทอรี
~/workspace/pset4/bmp ของคุณ ได้ (ลองนึกถึงว่าแต่ละคำสั่งทำอะไรได้บ้าง) หากคุณใช้
mallocต้องแน่ใจว่าใช้
freeเพื่อป้องกันหน่วยความจำรั่ว ลองใช้
valgrindเพื่อตรวจสอบรอยรั่ว
~cs50/pset4/peek large.bmp
./resize 4 small.bmp student.bmp
~cs50/pset4/resize 4 small.bmp staff.bmp
~cs50/pset4/peek student.bmp staff.bmp
จะตัดสินใจอย่างไร?
-
เปิดไฟล์ที่เราต้องการขยายและสร้างและเปิดไฟล์ใหม่ที่จะบันทึกภาพที่ขยายใหญ่ขึ้น
-
อัปเดตข้อมูลส่วนหัวสำหรับไฟล์เอาต์พุต เนื่องจากรูปภาพของเราอยู่ในรูปแบบ BMP และเรากำลังเปลี่ยนขนาด เราจึงต้องเขียนส่วนหัวของไฟล์ใหม่ด้วยขนาดใหม่ อะไรจะเปลี่ยนไป? ขนาดไฟล์ รวมถึงขนาดภาพ - ความกว้างและความสูง
-
เราอ่านไฟล์ขาออกทีละบรรทัด พิกเซลต่อพิกเซล ในการดำเนินการนี้ เราจะหันไปใช้ไลบรารีไฟล์ I/O และฟังก์ชัน fread อีกครั้ง มันจะนำตัวชี้ไปยังโครงสร้างที่จะมีไบต์ที่อ่าน ขนาดขององค์ประกอบเดี่ยวที่เราจะอ่าน จำนวนขององค์ประกอบดังกล่าว และตัวชี้ไปยังไฟล์ที่เราจะอ่าน
-
เราเพิ่มแต่ละบรรทัดในแนวนอนตามมาตราส่วนที่ระบุ และเขียนผลลัพธ์ลงในไฟล์เอาต์พุต
เราจะเขียนไฟล์ได้อย่างไร? เรามีฟังก์ชัน fwrite ซึ่งเราจะส่งตัวบ่งชี้ไปยังโครงสร้างที่มีข้อมูลที่จะเขียนลงในไฟล์ขนาดขององค์ประกอบหมายเลขและตัวชี้ไปยังไฟล์เอาต์พุต ในการจัดระเบียบลูป เราสามารถใช้for loop ที่เราคุ้นเคยอยู่ แล้ว
-
เติมคำลงในช่องว่าง! หากจำนวนพิกเซลในบรรทัดไม่เป็นผลคูณของสี่ เราต้องเพิ่ม "การจัดตำแหน่ง" - ศูนย์ไบต์ เราจะต้องมีสูตรในการคำนวณขนาดการจัดตำแหน่ง หากต้องการเขียนไบต์ว่างไปยังไฟล์เอาต์พุต คุณสามารถใช้ฟังก์ชัน fputc โดยส่งอักขระที่คุณต้องการเขียนและตัวชี้ไปยังไฟล์เอาต์พุต
ตอนนี้เราได้ขยายสตริงในแนวนอนและเพิ่มการจัดตำแหน่งให้กับไฟล์เอาต์พุตแล้ว เราจำเป็นต้องย้ายตำแหน่งปัจจุบันในไฟล์เอาต์พุตเนื่องจากเราจำเป็นต้องข้ามข้ามการจัดตำแหน่ง
-
เพิ่มขนาดแนวตั้ง มันซับซ้อนกว่า แต่เราสามารถใช้โค้ดตัวอย่างจากcopy.cได้ (copy.c เปิดไฟล์เอาต์พุต เขียนส่วนหัวไปยังไฟล์เอาต์พุต อ่านรูปภาพจากไฟล์ต้นฉบับทีละบรรทัด พิกเซลต่อพิกเซล และเขียนมัน ไปยังไฟล์เอาต์พุต) จากสิ่งนี้ สิ่งแรกที่คุณสามารถทำได้คือรันคำสั่งต่อไปนี้: cp copy.c resize.c
การยืดภาพในแนวตั้งหมายถึงการคัดลอกแต่ละบรรทัดหลายครั้ง มีหลายวิธีในการทำเช่นนี้ ตัวอย่างเช่น เมื่อใช้การเขียนใหม่ เมื่อเราบันทึกพิกเซลทั้งหมดของบรรทัดเดียวในหน่วยความจำ และเขียนบรรทัดนี้ลงในไฟล์เอาต์พุตแบบวนซ้ำได้บ่อยเท่าที่ต้องการ อีกวิธีหนึ่งคือการคัดลอกใหม่: หลังจากอ่านบรรทัดจากไฟล์ขาออกแล้ว เขียนลงในไฟล์เอาต์พุตและจัดตำแหน่ง ให้ส่งคืนฟังก์ชัน fseek กลับไปที่จุดเริ่มต้นของบรรทัดในไฟล์ขาออก และทำซ้ำทุกอย่างอีกครั้งหลาย ๆ ครั้ง
-
เปิดไฟล์ที่มีเนื้อหาอยู่ในการ์ดหน่วยความจำ
-
ค้นหาจุดเริ่มต้นของไฟล์ JPEG ไฟล์ทั้งหมดในการ์ดใบนี้เป็นภาพในรูปแบบ JPEG
ฟื้นตัว
เพื่อเตรียมพร้อมสำหรับรายงานปัญหาของสัปดาห์ที่ 4 ฉันใช้เวลาสองสามวันที่ผ่านมาดูภาพที่บันทึกในรูปแบบ JPEG โดยกล้องดิจิตอลของฉันในการ์ดหน่วยความจำ CompactFlash (CF) ขนาด 1 GB โปรดอย่าบอกฉันว่าฉันใช้เวลาสองสามวันที่ผ่านมาบน Facebook แทน น่าเสียดายที่ทักษะการใช้คอมพิวเตอร์ของฉันยังเหลือความต้องการอีกมาก และฉันก็ลบรูปภาพทั้งหมดโดยไม่รู้ตัว! โชคดีที่ในโลกคอมพิวเตอร์ การ "ลบ" มักจะไม่เท่ากับ "ถูกฆ่า" คอมพิวเตอร์ของฉันยืนยันว่าขณะนี้การ์ดหน่วยความจำว่างเปล่า แต่ฉันรู้ว่าการ์ดนั้นโกหก งานที่ได้รับมอบหมาย: เขียนโปรแกรมใน ~/workspace/pset4/jpg/recover.c ที่จะกู้คืนรูปภาพเหล่านี้ อืม. เอาล่ะ นี่คืออีกหนึ่งคำชี้แจง แม้ว่ารูปแบบ JPEG จะซับซ้อนกว่า BMP แต่ JPEG ก็มีรูปแบบไบต์ "ลายเซ็น" ที่ช่วยแยกความแตกต่างจากรูปแบบไฟล์อื่นๆ ไฟล์ JPEG ส่วนใหญ่เริ่มต้นด้วยสามไบต์ต่อไปนี้:0xff 0xd8 0xff
จากไบต์แรกไปที่สาม จากซ้ายไปขวา ไบต์ที่สี่มักจะเป็นหนึ่งในชุดค่าผสมต่อไปนี้: 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,0xe8, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef กล่าวอีกนัยหนึ่ง สี่บิตแรกของไบต์ที่สี่ของไฟล์ JPEG คือ 1110 มีโอกาสที่หากคุณพบรูปแบบใดรูปแบบหนึ่งเหล่านี้บนไดรฟ์ที่เก็บรูปภาพไว้ (เช่น การ์ดหน่วยความจำของฉัน) นี่จะเป็นจุดเริ่มต้นของไฟล์ JPEG แน่นอนคุณอาจพบสิ่งนี้โดยบังเอิญบนดิสก์ใด ๆ การกู้คืนข้อมูลไม่สามารถเรียกได้ว่าเป็นวิทยาศาสตร์ที่แน่นอน
GO TO FULL VERSION