JPEG แบบถอยหลัง (Regressive)
(maurycyz.com)- หากดัดแปลง โครงสร้างหลายสแกน ของ JPEG แบบ progressive แทนที่คุณภาพภาพจะดีขึ้นเรื่อย ๆ ตามการดาวน์โหลด ก็สามารถทำให้ภาพที่แสดงอยู่เปลี่ยนเป็นภาพอื่นไปเรื่อย ๆ ได้
- แต่ละสแกนระบุช่องสี·ช่วงความถี่ DCT·ความละเอียด และหากนำ JPEG ที่มีความละเอียดเท่ากันมาต่อกันโดยลบมาร์กเกอร์บางส่วนออก จะสามารถ เขียนทับข้อมูลเรนเดอร์เดิมได้
- ตัวถอดรหัสจำกัดจำนวนสแกนที่จะประมวลผลเพื่อป้องกันปัญหาคล้าย compression bomb โดย Chrome เรนเดอร์ได้ถึง ประมาณ 90 เฟรม ส่วน Firefox และอื่น ๆ ประมวลผลได้มากกว่า
- หากแต่ละเฟรมใช้สแกนเฉพาะ DC เพียงสแกนเดียว จะเพิ่มจำนวนเฟรมได้พร้อมหลีกเลี่ยงภาพค้างซ้อน แต่ด้วยคุณลักษณะของบล็อก DCT ความละเอียดผลลัพธ์จะลดลงเหลือ 1/16 ของต้นฉบับ
- สามารถใส่หลายเฟรมเหมือนวิดีโอไว้ใน JPEG ไฟล์เดียวได้ แต่ไม่มีข้อมูลจังหวะเวลา ความเร็วการเล่นจึงขึ้นกับความหน่วงของเครือข่าย และเหมาะกับ การทดลอง HTML·แอปหน้าเดียวที่ใช้ partial rendering มากกว่าวิดีโอที่ใช้งานจริง
วิธีที่ JPEG แบบ progressive แสดงภาพ
- JPEG บันทึก องค์ประกอบความถี่ต่ำ ไว้ก่อน จึงสามารถแสดงพรีวิวความละเอียดต่ำแทนภาพที่ถูกตัดขาดได้แม้ดาวน์โหลดไฟล์มาเพียงบางส่วน
- ข้อมูลที่บีบอัดถูกแบ่งเป็นหลาย สแกน (scan) และมีเฮดเดอร์นำหน้าทุกสแกน
FF DAคือมาร์กเกอร์เริ่มสแกน- จากนั้นมีฟิลด์ความยาว จำนวนช่องที่รวมอยู่และ ID ของช่อง รวมถึงดัชนีตาราง Huffman
- ระบุ DCT bin เริ่มต้น·สิ้นสุดและความละเอียด แล้วจึงบันทึกค่าสัมประสิทธิ์ DCT ที่เข้ารหัสแบบ Huffman
- สแกนแรกประกอบด้วย DC frequency bin ที่ต่ำที่สุดจากช่องสีทั้งสามช่อง
YCbCr และการปรับปรุงคุณภาพทีละขั้น
- ช่องสีทั้งสามของ JPEG ใช้ YCbCr แทน RGB ทั่วไป
Yคือความสว่าง จึงต้องมีคุณภาพสูงCb,Crคือองค์ประกอบผลต่างสี แม้ลดคุณภาพลงก็มีผลต่อการมองเห็นไม่มาก- หากอธิบายแบบหยาบมากคือ
Y = G,Cb = B - G,Cr = R - G
- JPEG ตัวอย่างค่อย ๆ เติมข้อมูลตั้งแต่สแกน 0 ถึง 9
- สแกน 0: บันทึก
Y Cb Cr, DCT bin0–0ที่ความละเอียดครึ่งหนึ่ง เพื่อให้พรีวิวความละเอียดต่ำมาก - สแกน 1: เพิ่ม
Y, bin1–5ที่ความละเอียด 1/4 เพื่อเสริมรายละเอียดความสว่าง - สแกน 2·3: เพิ่ม bin
1–63ของCb,Crที่ความละเอียดครึ่งหนึ่ง - สแกน 4: เติม bin
6–63ของYที่ความละเอียด 1/4 เพื่อชดเชยช่วงที่สแกน 1 เหลือไว้ - สแกน 5: ปรับปรุง bin
1–63ของYเป็นความละเอียดครึ่งหนึ่ง - สแกน 6–9: เพิ่มบิตสุดท้ายให้แต่ละช่องจนได้คุณภาพเต็ม
- สแกน 0: บันทึก
- ข้อมูลผลต่างสีเสร็จก่อนความสว่าง แต่ผลต่างสีถูกบันทึกที่ ความละเอียดครึ่งหนึ่ง หรือจำนวนพิกเซล 1/4 ดังนั้นขนาดรวมของ
Cr + Cbก็มีเพียงครึ่งหนึ่งของความสว่างเท่านั้น
เปลี่ยนภาพระหว่างดาวน์โหลด
- เนื่องจากแต่ละสแกนระบุช่วงความถี่ที่จะนำไปใช้ จึงสามารถสร้าง JPEG ที่เขียนทับ ข้อมูลภาพที่เรนเดอร์ไปแล้วด้วยสแกนถัดไปได้
- ทำโดยนำภาพหลายภาพที่มีความละเอียดเท่ากันมาต่อกัน พร้อมกรองมาร์กเกอร์ต่อไปนี้ออก
- จุดเริ่มต้นภาพ (start-of-image)
- จุดเริ่มต้นเฟรม (start-of-frame)
- จุดสิ้นสุดภาพ (end-of-image)
- แม้จะทำด้วย hex editor ได้ แต่ในการสร้างจริงใช้ โปรแกรม C แบบง่าย
- หากส่งไฟล์ผ่านเครือข่ายช้า ๆ ภาพหลายภาพจะสลับกันตามลำดับระหว่างที่การดาวน์โหลดดำเนินไป
ข้อจำกัดจำนวนสแกนของตัวถอดรหัส
- ตัวถอดรหัส JPEG ส่วนใหญ่จะหยุดหลังประมวลผลสแกนไปจำนวนหนึ่ง
- คาดว่าเป็นข้อจำกัดเพื่อหลีกเลี่ยงปัญหาคล้าย compression bomb และด้วยวิธีต่อไฟล์แบบง่ายจึงทำ มากกว่า 9 เฟรม ได้ยาก
- หากต้องการสร้างแอนิเมชันที่ยาวขึ้น ต้องลดจำนวนสแกนที่จำเป็นต่อเฟรมให้เหลือน้อยที่สุด
เหตุผลที่ใช้ Baseline JPEG ไม่ได้
- วิธีเริ่มจาก Baseline JPEG ที่ใช้สแกนเดียวใช้ไม่ได้
- ในโหมด progressive ไม่สามารถใส่ bin 0 ซึ่งเป็น ข้อมูล DC และ bin 1 ขึ้นไปซึ่งเป็น ข้อมูล AC ไว้ในสแกนเดียวกันได้
- โหมด Baseline ไม่มีข้อจำกัดนี้ แต่ตัวถอดรหัส Baseline จะหยุดประมวลผลหลังสแกนแรก
- ข้อมูล AC ต้องมาต่อจากข้อมูล DC ดังนั้นเฟรม JPEG แบบ progressive ที่เล็กที่สุดจึงประกอบด้วยสแกนเฉพาะ DC หนึ่งสแกน
โครงสร้างและความละเอียดของเฟรมเฉพาะ DC
- เนื่องจาก DCT ประมวลผลเป็นหน่วย บล็อก 16×16 แม้มีเพียงข้อมูล DC ก็สามารถสร้างภาพที่ไม่ใช่สีทึบ แต่เป็นภาพความละเอียด 1/16 ของต้นฉบับได้
- เฟรมขั้นต่ำใช้สแกนเพียงหนึ่งสแกนที่บันทึก DCT bin
0–0ของช่องY Cb Crทั้งสามด้วยความละเอียดเต็ม - ด้วยโครงสร้างนี้ Chrome จะเรนเดอร์ได้ประมาณ 90 เฟรม ก่อนหยุดประมวลผล
- เบราว์เซอร์อื่นอย่าง Firefox ประมวลผลสแกนได้มากกว่า
- ภาพที่ประกอบด้วย 90 สแกนทำงานได้ในแทบทุกเบราว์เซอร์
การสลับเฟรมโดยไม่มีภาพค้างซ้อน
- ภาพค้างซ้อนจากวิธีต่อไฟล์แบบง่ายเกิดจากการที่สแกน AC ถูกออกแบบมาให้ เพิ่มความละเอียด ให้ข้อมูลเดิม
- ใน JPEG แบบ progressive ทั่วไป สามารถใส่หลายขั้นความละเอียดได้โดยไม่ทำให้ขนาดไฟล์เพิ่มมากนัก แต่ไม่เหมาะกับวิธีที่สลับภาพ
- หากใช้เฉพาะสแกน DC โดยไม่มีการปรับปรุงแบบ progressive จริง ๆ ก็จะไม่เกิดการเพิ่มความละเอียดของข้อมูล AC ก่อนหน้า จึงหลีกเลี่ยงภาพค้างซ้อนได้
- เฟรมเฉพาะ DC เป็น ภาพ JPEG ที่เป็นไปตามมาตรฐาน จึงไม่ต้องใช้เอนโค้ดเดอร์พิเศษ
- ในข้อกำหนดสแกนระบุเฉพาะ DC bin ของสามช่อง เช่น
0,1,2:0-0,0,0;
- ในข้อกำหนดสแกนระบุเฉพาะ DC bin ของสามช่อง เช่น
ข้อจำกัดของวิดีโอใน JPEG ไฟล์เดียว
- เมื่อต่อเฟรมเฉพาะ DC เข้าด้วยกัน จะสามารถใส่ วิดีโอทั้งเรื่อง ไว้ในไฟล์ JPEG ไฟล์เดียวได้
- สแกนของ JPEG ไม่มีวิธีเพิ่มเวลาเฟรม ความเร็วการเล่นจึงขึ้นกับความหน่วงของเครือข่ายทั้งหมด
- นอกจาก Rickroll แบบแหวกแนวหรือการแกล้งกันแล้ว ก็ไม่มีการใช้งานเชิงปฏิบัติ
การทดลองที่ขยาย partial rendering
- การใช้ partial rendering ยังทำการทดลองอื่นนอกเหนือจากการสลับเฟรม JPEG ได้
- สร้างวิดีโอ Bad Apple ด้วย วิดีโอ HTML ล้วนที่ใช้เฉพาะแท็ก
<dialog> - ยังสร้าง แอปพลิเคชันหน้าเดียวแบบโต้ตอบ ที่ไม่มี CSS หรือ JavaScript และไม่ต้องฮาร์ดโค้ดข้อมูลลงในไฟล์ได้
- การสร้างภาพใช้โค้ด C
merge.c
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
เคยลองทำงานที่คล้ายกันมากด้วย Adam7 interlaced PNG: https://www.da.vidbuchanan.co.uk/adamation/image.png
สุดท้ายการเล่นก็ยังขึ้นอยู่กับความหน่วงของเครือข่าย แต่ได้ตั้งค่าให้เซิร์ฟเวอร์ส่งแต่ละเฟรมแยกกันในช่วงเวลาสม่ำเสมอ เฟรมมีขนาดเล็ก ดังนั้นถ้าเครือข่ายไม่ได้ช้าผิดปกติ เซิร์ฟเวอร์จะเป็นตัวกำหนดจังหวะการเล่น
Refreshใน response header เพื่อให้ไคลเอนต์ดึงเฟรมแอนิเมชันใหม่เป็นระยะได้[1] ผลงาน IOCCC ปี 2013 ก็ใช้เทคนิคนี้เพื่ออัปเดตนาฬิกาที่เรนเดอร์เป็น PNG อย่างต่อเนื่อง[2][1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/...
[2] https://www.ioccc.org/2013/mills/index.html
บรรทัดถัดไปมี header
Refreshถูกเข้ารหัสแบบกลับด้านอยู่: https://github.com/ioccc-src/winner/blob/619f554bbdb19e5003a...เป็นเทคนิคต้องสาป แต่ก็เหมาะกับที่นี่จริง ๆ
สงสัยว่าเทคนิคนี้จะทำ steganography แบบซ่อนข้อมูลไว้ต่อหน้าต่อตาได้ไหม โปรแกรมวิเคราะห์ภาพอัตโนมัติส่วนใหญ่น่าจะตรวจแค่ภาพสุดท้าย จึงดูเหมือนนักเรียนอาจใช้เพื่อหลบเลี่ยง content filter ของโรงเรียนได้
อาจใช้เป็น แถบความคืบหน้า สำหรับงานที่โหลดแบบขนานบนเครือข่ายเดียวกัน เพื่อให้ผู้ใช้พอกะเวลาหน่วงที่เหลือได้หรือเปล่า
ถ้าเว็บเซิร์ฟเวอร์สร้าง “JPEG” ขึ้นมาแบบทันทีและส่งให้ไคลเอนต์เป็น ชิ้นส่วนที่เว้นช่วงเวลา ก็จะควบคุมจังหวะการเล่นได้ระดับหนึ่ง ถ้าใช้เว็บแคมเป็นแหล่งข้อมูล ก็ทำ “JPEG” ที่ต่อเนื่องไม่รู้จบได้
multipart/x-mixed-replaceเป็นวิธีที่เซิร์ฟเวอร์สั่งให้ไคลเอนต์แทนที่ข้อมูลที่เพิ่งส่งไปด้วยข้อมูลใหม่ และทำงานได้ด้วย HTTP กับ JPEG ธรรมดา โดยไม่ต้องใช้ JavaScriptถ้าจำลองการเชื่อมต่อที่ช้าด้วย Service Worker ก็จะควบคุมความเร็วการเล่นได้
แปลกที่พฤติกรรมแตกต่างกันตามสภาพแวดล้อม บน Firefox เดสก์ท็อปเล่นได้ถูกต้อง แต่บนมือถือ iOS “วิดีโอทั้งเรื่องใน JPEG” เห็นเป็นเฟรมเกือบสีล้วน 3 เฟรม จากน้ำตาล→ส้ม→แดง และเห็นเพียงเค้าโครงแมวแบบเบลอ ๆ
สีเปลี่ยนไปตามเฟรม จึงรู้ว่ามันทำงานอยู่ แต่เรียกว่าวิดีโอคงยาก บนเดสก์ท็อปมันเล่นเหมือนวิดีโอจริง ๆ จนน่าทึ่ง และดูเหมือนจะไปแตะ เงื่อนไขขอบเขตประหลาดของตัวถอดรหัสภาพบน iOS
ช่วงหลังได้ทำงานแสดงภาพให้เร็วด้วย OpenGL และ jpeg-turbo แล้วพบว่าเมื่อเปิด โหมด progressive ของ JPEG การถอดรหัสช้าลงมาก คำแนะนำเก่า ๆ ที่ว่ามี progressive JPEG แล้วดี อาจไม่จริงแล้วก็ได้
ตลอดหลายสิบปีที่ผ่านมาแทบไม่เคยเห็นภาพค่อย ๆ ชัดขึ้นทีละขั้น ดังนั้นดูเหมือนจะไม่มีคุณค่าในทางปฏิบัติเท่าไร
ตัวอย่าง: https://youtube.com/watch?v=UphN1_7nP8U
ตอนแรกนึกถึงวิธีคำนวณค่าสัมประสิทธิ์ความถี่สูงจากค่าสัมประสิทธิ์ “ผิด” ของภาพแรกแบบยุ่งยาก แต่การแค่รวมสองภาพเข้าด้วยกันนี่ฉลาดดี แค่ต่อ องค์ประกอบความถี่ต่ำ ของภาพหนึ่งด้วย องค์ประกอบความถี่สูง ของอีกภาพ ก็ทำงานได้ดีอย่างน่าประหลาดใจ
สงสัยว่าจะดึง องค์ประกอบความถี่ต่ำ ได้โดยตรงด้วยกล้องหรือไม่ นึกถึงวิธีของ MRI ที่เก็บข้อมูลความถี่ต่ำใน k-space ก่อน