2011-01-03 37 views
17

Tôi gửi nhiều hình ảnh từ máy chủ đến máy khách theo thứ tự liên tục qua TCP.Now tại máy khách, làm cách nào để phát hiện có hiệu quả rằng đây là phần cuối của hình ảnh của tôi để ghi vào hệ thống tệp và sau đó hình ảnh tiếp theo và vân vân.Phát hiện EOF cho hình ảnh JPG

Trân trọng, ...

+0

"Đang gửi" bằng giao thức nào? Giao thức của bạn có biết khi một tệp kết thúc tự động không? –

+1

Tại sao không gửi chiều dài của hình ảnh trước? – Kornel

+0

Sử dụng giao thức. –

Trả lời

26

Vâng, không có gì đảm bảo rằng bạn sẽ không tìm thấy FFD9 trong một hình ảnh jpeg. Cách tốt nhất bạn có thể tìm thấy kết thúc của một hình ảnh jpeg là phân tích nó. Mỗi điểm đánh dấu, ngoại trừ FFD0 đến FFD9 và FF01 (dành riêng), được theo sau bởi một chỉ số độ dài sẽ cung cấp cho bạn độ dài của đoạn nhãn đó, bao gồm chỉ số độ dài chứ không phải điểm đánh dấu. FF00 không phải là điểm đánh dấu, nhưng với mục đích của bạn, bạn có thể coi nó là điểm đánh dấu không có chỉ số độ dài.

Trình chỉ định độ dài dài hai byte và đó là phần cuối lớn. Vì vậy, những gì bạn sẽ làm là tìm kiếm FF, và nếu byte sau đây không phải là một trong 0x00, 0x01 hoặc 0xD0-0xD8, bạn đọc độ dài specifier và bỏ qua về phía trước trong dòng miễn là chiều dài specifier nói trừ hai byte.

Ngoài ra, mỗi điểm đánh dấu có thể được đệm vào đầu bằng bất kỳ số lượng FF nào.

Khi bạn truy cập FFD9, bạn đang ở cuối luồng.

Tất nhiên bạn có thể đọc từng dòng một từ, tìm kiếm FF nếu bạn muốn biểu diễn nhưng đó là một bài tập cho người đọc. ;-)

+1

Tôi nên làm rõ câu đầu tiên. Rõ ràng FFD9 ở cuối hình ảnh. Nhưng FFD9 có thể xuất hiện được nhúng trong một hình ảnh JPEG mà không bị đánh dấu EOI. Đó là lý do tại sao bạn _have_ phân tích cú pháp JPEG để tìm điểm đánh dấu EOI. – onemasse

+4

** Tóm tắt **: Đọc 0xFF. Đọc điểm đánh dấu. Đọc thông số độ dài L và bỏ qua chuyển tiếp bằng L - 2 byte. Sau phân đoạn SOS (0xFFDA) (tiếp theo là dữ liệu nén), hãy chuyển tiếp tới 0xFF đầu tiên ** không ** theo sau là 0x00 hoặc 0xD0-0xD8. Lặp lại từ đầu cho đến khi bạn gặp 0xFFD9. Hoạt động trên [JPEG đa quét này] (http://hodapple.com/blag/assets/obscure_jpeg_features/20100713-0107-interleave.jpg). –

+1

Cách tiếp cận này dễ bị tổn thương đối với hình ảnh bị hỏng (hoặc các tệp bị cắt do tai nạn hoặc hình ảnh giả mạo được thiết kế độc hại) –

12

Một cái nhìn nhanh chóng tại Wikipedia's JPEG article sẽ cho bạn câu trả lời:

  • byte 0xFF, 0xD8 chỉ bắt đầu của hình ảnh
  • byte 0xFF, 0xD9 cho biết phần cuối của hình ảnh
+5

Điều quan trọng cần lưu ý là có thể có các tệp JPEG được nhúng trong các ảnh JPEG (ví dụ như hình thu nhỏ) để bạn có thể thấy các điểm đánh dấu SOI SOI EOI EOI. Hãy chắc chắn để có mà xem xét. –

+0

@ SB: đúng. Một cách dễ dàng là quét các dấu EOI SOI theo thứ tự nếu đọc từ luồng không hoàn thành, và cho EOI nếu nó kết thúc. – darioo

-3

onemase

Sao anh lại nói có là không đảm bảo để tìm EOI? Nó phải có ở cuối.

Có ít nhất một điểm đánh dấu khác không được theo sau bởi trường độ dài 2 byte. Đó là SOS, Bắt đầu quét, 0xFFDA. Tiếp theo là

dài - Ls quy định như 6 2xNs + (hai byte)

số phân khúc Ns (một byte)

lĩnh vực tiếp theo của tiêu đề này không chứa kích thước của dữ liệu entropy theo tiêu đề SOS. Do đó, cách duy nhất để tìm kích thước là tìm byte theo byte cho EOI (End Of Image) = 0xFFD9.

Tôi rất muốn tìm cách khác.

+0

Bạn đã sai. Không có gì đảm bảo rằng hình ảnh jpeg không được nhúng dưới dạng hình thu nhỏ trong phân đoạn APP. Bằng cách quét tuần tự bạn sẽ tìm thấy EOI sớm. – onemasse

+0

Có. Tôi không nói về hình ảnh nhúng. Vì vậy, cách duy nhất để tìm kiếm kích thước của luồng là tìm tất cả các cặp StartOfImage, EndOfImage imho. Dựa vào độ dài sẽ không hoạt động vì điểm đánh dấu SOS không được theo sau bởi độ dài. – whobertoos

+1

Không, vì hình ảnh được nhúng chỉ là một ví dụ. Phân đoạn APP có thể chứa bất kỳ thứ gì, kể cả FFD9. Bạn cần phải tìm kiếm tuần tự, nhưng bỏ qua các phân đoạn bạn có thể. Cách để làm điều đó được mô tả trong câu trả lời của tôi. – onemasse

0

Nếu bạn đang gửi hình ảnh qua mảng byte thì bạn có thể chỉ cần thêm kích thước tệp của hình ảnh dưới dạng một cặp byte trước khi bắt đầu tệp.
Khách hàng lấy hai byte đầu tiên để tìm số byte được chỉ định (chúng tôi sẽ gọi x) và loại bỏ chúng, sau đó bơm số byte x tiếp theo vào bộ đệm mà nó có thể ghi vào tệp.
Rửa sạch và lặp lại cho tất cả các jpeg sau đây.

Một giải pháp thay thế là chỉ tìm kiếm điểm đánh dấu FFD9 - nếu tôi không nhầm bất kỳ giá trị nén nào FF sẽ được mã hóa thành FF00 (byte bị loại bỏ và byte FF được giữ).
Vấn đề với điều này là bạn nhận được những thứ như hình thu nhỏ với tiêu đề FFD9 của riêng họ, nhưng những phần đó được chứa trong một phân đoạn trong tiêu đề. Những phân đoạn này có giá trị độ dài trong hai byte sau dấu của chúng để bạn có thể bỏ qua đến cuối bất kỳ phân đoạn nào bạn gặp phải để tránh phát hiện eoi sớm.

Các vấn đề liên quan