1 คะแนน โดย GN⁺ 21 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • หากดัดแปลง โครงสร้างหลายสแกน ของ 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 bin 0–0 ที่ความละเอียดครึ่งหนึ่ง เพื่อให้พรีวิวความละเอียดต่ำมาก
    • สแกน 1: เพิ่ม Y, bin 1–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: เพิ่มบิตสุดท้ายให้แต่ละช่องจนได้คุณภาพเต็ม
  • ข้อมูลผลต่างสีเสร็จก่อนความสว่าง แต่ผลต่างสีถูกบันทึกที่ ความละเอียดครึ่งหนึ่ง หรือจำนวนพิกเซล 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;

ข้อจำกัดของวิดีโอใน JPEG ไฟล์เดียว

  • เมื่อต่อเฟรมเฉพาะ DC เข้าด้วยกัน จะสามารถใส่ วิดีโอทั้งเรื่อง ไว้ในไฟล์ JPEG ไฟล์เดียวได้
  • สแกนของ JPEG ไม่มีวิธีเพิ่มเวลาเฟรม ความเร็วการเล่นจึงขึ้นกับความหน่วงของเครือข่ายทั้งหมด
  • นอกจาก Rickroll แบบแหวกแนวหรือการแกล้งกันแล้ว ก็ไม่มีการใช้งานเชิงปฏิบัติ

การทดลองที่ขยาย partial rendering

1 ความคิดเห็น

 
ความคิดเห็นบน Hacker News
  • เคยลองทำงานที่คล้ายกันมากด้วย Adam7 interlaced PNG: https://www.da.vidbuchanan.co.uk/adamation/image.png
    สุดท้ายการเล่นก็ยังขึ้นอยู่กับความหน่วงของเครือข่าย แต่ได้ตั้งค่าให้เซิร์ฟเวอร์ส่งแต่ละเฟรมแยกกันในช่วงเวลาสม่ำเสมอ เฟรมมีขนาดเล็ก ดังนั้นถ้าเครือข่ายไม่ได้ช้าผิดปกติ เซิร์ฟเวอร์จะเป็นตัวกำหนดจังหวะการเล่น

    • ถ้าควบคุม HTTP server ได้ ก็อาจตั้งค่า 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...
    • เคยลองทำงานคล้ายกันในการสตรีมวิดีโอแบบเรียลไทม์ด้วย GIF ไม่รู้จบ: https://github.com/jbochi/gifstreaming#live-video-streaming-...
    • ระหว่างที่กำลังใช้วิธีลัดเพื่อทำให้ PNG เป็นแอนิเมชัน APNG ก็ดูเหมือนจะตะโกนอยู่ข้าง ๆ ว่า “ฉันก็มีตัวตนนะ!”
    • เมื่อ 20 ปีก่อน ที่ทำงานเคยทำแบบเดียวกันด้วย animated GIF เพื่อเพิ่มเลเยอร์คุณภาพอากาศแบบเรียลไทม์ในแอปพลิเคชันแผนที่ รูปภาพเรนเดอร์ด้วย Java2D และยังพัฒนาเวอร์ชัน JOGL เพื่อสร้างก้อนเกรเดียนต์แทนกลุ่มจุดด้วย แต่ทำไม่เสร็จเพราะผู้ดูแลเซิร์ฟเวอร์ไม่อนุญาตให้ติดตั้งไดรเวอร์ OpenGL
  • เป็นเทคนิคต้องสาป แต่ก็เหมาะกับที่นี่จริง ๆ

    • บริษัทเทคโนโลยีรายใหญ่น่าจะกำลังคิดว่าจะใช้สิ่งนี้กับ browser fingerprinting ได้อย่างไร
  • สงสัยว่าเทคนิคนี้จะทำ steganography แบบซ่อนข้อมูลไว้ต่อหน้าต่อตาได้ไหม โปรแกรมวิเคราะห์ภาพอัตโนมัติส่วนใหญ่น่าจะตรวจแค่ภาพสุดท้าย จึงดูเหมือนนักเรียนอาจใช้เพื่อหลบเลี่ยง content filter ของโรงเรียนได้

    • ใช้เป็น เทคนิคก่อกวน AI ได้ โดยใส่ข้อความสำหรับมนุษย์ไว้ในเฟรมแรก และข้อความสำหรับ AI ไว้ในเฟรมสุดท้าย ประมาณว่าส่งรูปแมวให้กันเพื่อเอาชนะ Skynet
    • ดูไม่เห็นว่าจะมีวิธีไหนดีกว่า steganography ทั่วไป
  • อาจใช้เป็น แถบความคืบหน้า สำหรับงานที่โหลดแบบขนานบนเครือข่ายเดียวกัน เพื่อให้ผู้ใช้พอกะเวลาหน่วงที่เหลือได้หรือเปล่า

    • จำได้ว่าเว็บอย่าง 4chan เคยถูกนำไปใช้ในทางที่ผิดเพื่อซ่อนภาพที่น่ารังเกียจหรือผิดกฎหมาย เลยบล็อกพฤติกรรมแบบนี้ทั้งหมด
  • ถ้าเว็บเซิร์ฟเวอร์สร้าง “JPEG” ขึ้นมาแบบทันทีและส่งให้ไคลเอนต์เป็น ชิ้นส่วนที่เว้นช่วงเวลา ก็จะควบคุมจังหวะการเล่นได้ระดับหนึ่ง ถ้าใช้เว็บแคมเป็นแหล่งข้อมูล ก็ทำ “JPEG” ที่ต่อเนื่องไม่รู้จบได้

    • เว็บแคมบางรุ่นทำแบบนี้อยู่แล้วด้วยเทคนิค MIME ที่เรียกว่า multipart/x-mixed-replace เป็นวิธีที่เซิร์ฟเวอร์สั่งให้ไคลเอนต์แทนที่ข้อมูลที่เพิ่งส่งไปด้วยข้อมูลใหม่ และทำงานได้ด้วย HTTP กับ JPEG ธรรมดา โดยไม่ต้องใช้ JavaScript
    • กล้อง IP จำนวนมากทำแบบนี้อยู่แล้วด้วย https://en.wikipedia.org/wiki/Motion_JPEG
    • ทำด้วย GIF ก็ได้ ครั้งหนึ่งเคยทำ CGI เล่น ๆ ที่ส่ง GIF ทีละเฟรมและใช้ image map จัดการการคลิก ทำให้ใช้งานได้เหมือน remote desktop โดยไม่ต้องใช้ JavaScript บางที JPEG อาจดีกว่า น่าลองทำใหม่
  • ถ้าจำลองการเชื่อมต่อที่ช้าด้วย Service Worker ก็จะควบคุมความเร็วการเล่นได้

  • แปลกที่พฤติกรรมแตกต่างกันตามสภาพแวดล้อม บน Firefox เดสก์ท็อปเล่นได้ถูกต้อง แต่บนมือถือ iOS “วิดีโอทั้งเรื่องใน JPEG” เห็นเป็นเฟรมเกือบสีล้วน 3 เฟรม จากน้ำตาล→ส้ม→แดง และเห็นเพียงเค้าโครงแมวแบบเบลอ ๆ
    สีเปลี่ยนไปตามเฟรม จึงรู้ว่ามันทำงานอยู่ แต่เรียกว่าวิดีโอคงยาก บนเดสก์ท็อปมันเล่นเหมือนวิดีโอจริง ๆ จนน่าทึ่ง และดูเหมือนจะไปแตะ เงื่อนไขขอบเขตประหลาดของตัวถอดรหัสภาพบน iOS

  • ช่วงหลังได้ทำงานแสดงภาพให้เร็วด้วย OpenGL และ jpeg-turbo แล้วพบว่าเมื่อเปิด โหมด progressive ของ JPEG การถอดรหัสช้าลงมาก คำแนะนำเก่า ๆ ที่ว่ามี progressive JPEG แล้วดี อาจไม่จริงแล้วก็ได้
    ตลอดหลายสิบปีที่ผ่านมาแทบไม่เคยเห็นภาพค่อย ๆ ชัดขึ้นทีละขั้น ดังนั้นดูเหมือนจะไม่มีคุณค่าในทางปฏิบัติเท่าไร

    • คุณอาจพลาดช่วงที่ภาพเบลอเล็กน้อยหลังหน้าเว็บโหลดเสร็จใหม่ ๆ แล้วค่อยชัดขึ้นในขั้นถัดไปก็ได้ แม้ขั้นแรกจะไม่ถึงกับดูไม่ออกเหมือนสมัยก่อน แต่คุณค่าของการให้ พรีวิวความละเอียดต่ำ ด้วยข้อมูลเพียงประมาณ 30% ของขนาดไฟล์ทั้งหมดแทบจะฟรี ๆ ก็ยังมีอยู่
    • ใช้ cjpegli เป็นเอนโค้ดเดอร์ และค่าปริยายที่เป็น progressive ร่วมกับ 4:4:4 เต็มรูปแบบให้สัดส่วนการบีบอัดดีที่สุด ดังนั้นมันไม่ใช่แค่ฟีเจอร์เสริมธรรมดา
    • ภาพถ่าย JPEG ที่บันทึกแบบ progressive มักจะ เล็กลงประมาณ 5% และยังสามารถแปลง JPEG เป็นรูปแบบ progressive แบบไม่สูญเสียข้อมูลได้ด้วย ถ้าแปลงแบบไม่สูญเสียข้อมูลเป็น JPEG XL ก็จะประหยัดพื้นที่ได้มากขึ้นอีก
    • progressive decoding ไม่ได้มีไว้เพื่อให้การถอดรหัสเร็วขึ้นเอง แต่เพื่อให้ ภาพขนาดใหญ่แสดงผลได้เร็วขึ้น โดยเฉพาะบนการเชื่อมต่อมือถือที่ช้า
      ตัวอย่าง: https://youtube.com/watch?v=UphN1_7nP8U
  • ตอนแรกนึกถึงวิธีคำนวณค่าสัมประสิทธิ์ความถี่สูงจากค่าสัมประสิทธิ์ “ผิด” ของภาพแรกแบบยุ่งยาก แต่การแค่รวมสองภาพเข้าด้วยกันนี่ฉลาดดี แค่ต่อ องค์ประกอบความถี่ต่ำ ของภาพหนึ่งด้วย องค์ประกอบความถี่สูง ของอีกภาพ ก็ทำงานได้ดีอย่างน่าประหลาดใจ

  • สงสัยว่าจะดึง องค์ประกอบความถี่ต่ำ ได้โดยตรงด้วยกล้องหรือไม่ นึกถึงวิธีของ MRI ที่เก็บข้อมูลความถี่ต่ำใน k-space ก่อน