JPEG chạy ngược (Regressive)
(maurycyz.com)- Nếu biến đổi cấu trúc nhiều scan của JPEG lũy tiến, thay vì chất lượng ảnh tốt dần khi tải xuống, ảnh đã hiển thị có thể liên tục đổi thành ảnh khác
- Mỗi scan chỉ định kênh màu, dải tần số DCT và độ chính xác; bằng cách loại bỏ một số marker khỏi các JPEG cùng độ phân giải rồi nối chúng lại, có thể ghi đè dữ liệu render hiện có
- Decoder giới hạn số scan được xử lý để ngăn các vấn đề tương tự bom nén; Chrome render được tới khoảng 90 khung hình, còn Firefox và một số trình duyệt khác xử lý được nhiều hơn
- Nếu mỗi khung hình chỉ dùng một scan chứa riêng DC, có thể tăng số khung hình và tránh bóng mờ, nhưng do đặc tính khối DCT, độ phân giải kết quả giảm xuống còn 1/16 so với bản gốc
- Có thể chứa nhiều khung hình giống video trong một JPEG duy nhất, nhưng vì không có thông tin thời gian nên tốc độ phát phụ thuộc vào độ trễ mạng; phù hợp với các thử nghiệm HTML/ứng dụng một trang tận dụng render từng phần hơn là video thực dụng
Cách JPEG lũy tiến hiển thị hình ảnh
- JPEG lưu thành phần tần số thấp trước, nên ngay cả khi chỉ tải xuống một phần file, nó có thể hiển thị bản xem trước độ phân giải thấp thay vì ảnh bị cắt
- Dữ liệu nén được chia thành nhiều scan, mỗi scan có header phía trước
FF DAlà marker bắt đầu scan- Tiếp theo là trường độ dài, số kênh được bao gồm và ID của chúng, cùng chỉ số bảng Huffman
- Sau khi chỉ định bin DCT bắt đầu/kết thúc và độ chính xác, nó lưu các hệ số DCT được mã hóa Huffman
- Scan đầu tiên chứa bin tần số DC thấp nhất trong ba kênh màu
YCbCr và cải thiện chất lượng theo từng bước
- Ba kênh màu của JPEG dùng YCbCr thay vì RGB thông thường
Ylà độ chói nên cần chất lượng caoCb,Crlà thành phần sắc sai, nên dù giảm chất lượng cũng ít ảnh hưởng thị giác- Nếu biểu diễn rất thô,
Y = G,Cb = B - G,Cr = R - G
- JPEG ví dụ lấp dữ liệu dần dần từ scan 0 đến 9
- Scan 0: lưu
Y Cb Cr, bin DCT0–0ở nửa độ chính xác, cung cấp bản xem trước độ phân giải rất thấp - Scan 1: thêm
Y, bin1–5ở 1/4 độ chính xác để bổ sung chi tiết độ chói - Scan 2·3: thêm bin
1–63củaCb,Crở nửa độ chính xác - Scan 4: điền bin
6–63củaYở 1/4 độ chính xác, bù phần còn lại sau scan 1 - Scan 5: cải thiện bin
1–63củaYlên nửa độ chính xác - Scan 6–9: thêm các bit cuối cùng cho từng kênh để đạt chất lượng đầy đủ
- Scan 0: lưu
- Dữ liệu sắc sai hoàn tất trước độ chói, nhưng vì sắc sai được lưu ở nửa độ phân giải, tức 1/4 số pixel, nên tổng dung lượng
Cr + Cbcũng chỉ bằng một nửa độ chói
Đổi ảnh trong khi tải xuống
- Vì mỗi scan ghi rõ dải tần số sẽ áp dụng, có thể tạo JPEG ghi đè dữ liệu ảnh đã render bằng các scan sau
- Cách triển khai là nối nhiều ảnh cùng độ phân giải lại với nhau, đồng thời lọc bỏ các marker sau
- bắt đầu ảnh (start-of-image)
- bắt đầu khung (start-of-frame)
- kết thúc ảnh (end-of-image)
- Có thể tạo bằng trình sửa hex, nhưng để sinh thực tế thì dùng một chương trình C đơn giản
- Khi truyền file qua mạng chậm, nhiều ảnh sẽ lần lượt chuyển đổi trong lúc quá trình tải xuống diễn ra
Giới hạn scan của decoder
- Hầu hết decoder JPEG sẽ dừng sau khi xử lý một số scan nhất định
- Đây được cho là giới hạn nhằm tránh các vấn đề tương tự bom nén; với cách nối đơn giản, khó triển khai hơn 9 khung hình
- Muốn tạo hoạt ảnh dài hơn, cần tối thiểu hóa số scan cần thiết cho mỗi khung hình
Vì sao không thể dùng Baseline JPEG
- Cách bắt đầu từ Baseline JPEG chỉ dùng một scan không hoạt động
- Trong chế độ lũy tiến, không thể đặt dữ liệu DC là bin 0 và dữ liệu AC là bin từ 1 trở lên trong cùng một scan
- Chế độ Baseline không có giới hạn này, nhưng decoder Baseline dừng xử lý sau scan đầu tiên
- Vì dữ liệu AC phải đến sau dữ liệu DC, khung JPEG lũy tiến nhỏ nhất gồm một scan chỉ chứa DC
Cấu trúc và độ phân giải của khung chỉ DC
- Vì DCT được xử lý theo đơn vị khối 16×16, ngay cả khi chỉ chứa dữ liệu DC, nó vẫn có thể tạo ra ảnh ở 1/16 độ phân giải của ảnh gốc, chứ không phải ảnh một màu
- Khung tối thiểu chỉ dùng một scan lưu bin DCT
0–0của ba kênhY Cb Crvới độ chính xác đầy đủ - Với cấu trúc này, Chrome render khoảng 90 khung hình trước khi dừng xử lý
- Các trình duyệt khác như Firefox xử lý được nhiều scan hơn
- Ảnh gồm 90 scan hoạt động trên hầu hết mọi trình duyệt
Chuyển khung không bóng mờ
- Bóng mờ trong cách nối đơn giản phát sinh vì các scan AC được thiết kế để tinh chỉnh dữ liệu hiện có
- Trong JPEG lũy tiến thông thường, có thể chứa nhiều mức độ chính xác mà không làm tăng đáng kể kích thước file, nhưng điều đó không phù hợp với cách thay thế ảnh
- Nếu chỉ dùng các scan DC mà không cải thiện lũy tiến thực sự, sẽ không có việc tinh chỉnh dữ liệu AC trước đó, nhờ đó tránh được bóng mờ
- Khung chỉ DC là ảnh JPEG tuân thủ chuẩn, nên không cần encoder đặc biệt
- Trong đặc tả scan, chỉ chỉ định các bin DC của ba kênh, như
0,1,2:0-0,0,0;
- Trong đặc tả scan, chỉ chỉ định các bin DC của ba kênh, như
Hạn chế của video trong một JPEG duy nhất
- Nếu nối các khung chỉ DC, có thể chứa toàn bộ video trong một file JPEG
- Scan JPEG không có cách thêm thời gian cho khung hình, nên tốc độ phát hoàn toàn phụ thuộc vào độ trễ mạng
- Ngoài Rickroll phi truyền thống hoặc trò đùa, nó không có ứng dụng thực tế
Thử nghiệm mở rộng render từng phần
- Tận dụng render từng phần còn cho phép các thử nghiệm khác ngoài thay thế khung JPEG
- Triển khai video Bad Apple bằng video HTML thuần chỉ dùng thẻ
<dialog> - Cũng triển khai ứng dụng một trang tương tác không có CSS hay JavaScript, không cần hardcode dữ liệu vào file
- Việc tạo ảnh dùng mã C
merge.c
1 bình luận
Ý kiến trên Hacker News
Tôi đã làm một thứ rất похожий với PNG xen kẽ Adam7: https://www.da.vidbuchanan.co.uk/adamation/image.png
Dù việc phát cuối cùng vẫn phụ thuộc vào độ trễ mạng, tôi đã cấu hình để máy chủ gửi riêng từng khung hình theo các khoảng thời gian cố định. Vì các khung hình nhỏ, nếu mạng không chậm bất thường thì máy chủ sẽ quyết định thời điểm phát
Refreshtrong header phản hồi để client định kỳ lấy khung hình hoạt ảnh mới[1]. Một bài dự thi IOCCC năm 2013 cũng liên tục cập nhật chiếc đồng hồ render bằng PNG theo cách này[2][1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/...
[2] https://www.ioccc.org/2013/mills/index.html
Dòng tiếp theo có header
Refreshđược mã hóa ngược: https://github.com/ioccc-src/winner/blob/619f554bbdb19e5003a...Đúng là một kỹ thuật bị nguyền rủa, nhưng cực kỳ hợp với chỗ này
Tôi tò mò liệu có thể dùng kỹ thuật này để làm steganography bằng cách giấu dữ liệu ngay trước mắt hay không. Phần lớn chương trình phân tích ảnh tự động có lẽ chỉ kiểm tra ảnh cuối cùng, nên học sinh có thể dùng nó để vượt qua bộ lọc nội dung của trường
Tôi nghĩ có thể dùng nó làm thanh tiến trình cho tác vụ tải song song trên cùng một mạng để người dùng ước lượng độ trễ còn lại
Nếu máy chủ web tạo “JPEG” tại chỗ rồi gửi cho client thành các mảnh cách nhau theo thời gian, bạn có thể điều khiển thời điểm phát ở mức nào đó. Nếu lấy webcam làm nguồn thì còn có thể tạo “JPEG” kéo dài vô tận
multipart/x-mixed-replace. Máy chủ bảo client thay thế dữ liệu vừa gửi bằng dữ liệu mới, và nó hoạt động chỉ với HTTP và JPEG thông thường, không cần JavaScriptCó thể điều khiển tốc độ phát bằng Service Worker để giả lập kết nối chậm
Việc nó hoạt động khác nhau tùy môi trường thật kỳ lạ. Trên Firefox desktop thì phát đúng, nhưng trên iOS mobile, “toàn bộ video bên trong JPEG” gần như chỉ hiện 3 khung màu nâu → cam → đỏ đơn sắc cùng đường nét mờ của con mèo
Có thể thấy màu thay đổi theo từng khung nên biết là nó đang chạy, nhưng khó mà gọi đó là video. Trên desktop nó phát như video thật nên khá bất ngờ, có vẻ như đã chạm vào một điều kiện biên kỳ quặc của bộ giải mã ảnh trên iOS
Gần đây tôi làm việc hiển thị ảnh nhanh bằng OpenGL và jpeg-turbo, và khi bật chế độ progressive của JPEG thì việc giải mã chậm đi đáng kể. Lời khuyên cũ rằng progressive JPEG là tốt có lẽ giờ không còn đúng nữa
Trong nhiều thập kỷ tôi hầu như không còn thấy ảnh rõ dần theo từng bước, nên cũng không thấy nhiều giá trị thực tế
Ví dụ: https://youtube.com/watch?v=UphN1_7nP8U
Ban đầu tôi nghĩ đến cách tính ngược các hệ số tần số cao từ các hệ số “sai” của ảnh đầu tiên, nhưng cách chỉ đơn giản ghép hai ảnh lại với nhau mới thật thông minh. Chỉ cần nối thành phần tần số thấp của một ảnh với thành phần tần số cao của ảnh kia mà vẫn hoạt động tốt đến đáng ngạc nhiên
Tôi tự hỏi liệu camera có thể thu trực tiếp thành phần tần số thấp hay không. Nó cũng khiến tôi nhớ đến MRI, nơi người ta thu tần số thấp trước trong k-space