2011-01-03 41 views
17

Estoy enviando muchas imágenes de mi servidor al cliente en secuencia continuamente a través de TCP. Ahora en el cliente, ¿cómo debo detectar eficientemente que este es el final de mi imagen así que anótelo en el sistema de archivos y luego la siguiente imagen y así sucesivamente.Detectar Eof para imágenes JPG

Saludos, ...

+0

"Enviando" usando qué protocolo? ¿Su protocolo no sabe cuándo termina un archivo automáticamente? –

+1

¿Por qué no enviar la longitud de la imagen de antemano? – Kornel

+0

Use un protocolo. –

Respuesta

26

Bueno, no hay garantía de que no encontrará FFD9 dentro de una imagen JPEG. La mejor forma de encontrar el final de una imagen jpeg es analizarla. Cada marcador, excepto FFD0 a FFD9 y FF01 (reservado), es seguido inmediatamente por un especificador de longitud que le dará la longitud de ese segmento marcador, incluyendo el especificador de longitud pero no el marcador. FF00 no es un marcador, pero para sus propósitos puede tratarlo como marcador sin un especificador de longitud.

El especificador de longitud tiene dos bytes de longitud y es big endian. Entonces lo que harás es buscar FF, y si el siguiente byte no es uno de 0x00, 0x01 o 0xD0-0xD8, lees el especificador de longitud y salta hacia adelante en la secuencia, siempre que el especificador de longitud indique menos dos bytes.

Además, cada marcador se puede rellenar al principio con cualquier cantidad de FF.

Cuando llegue a FFD9, se encontrará al final de la transmisión.

Por supuesto, podría leer la secuencia palabra por palabra, buscando FF si desea rendimiento, pero eso queda como un ejercicio para el lector. ;-)

+1

Debo aclarar la primera oración. Es obvio que FFD9 está al final de una imagen. Pero FFD9 podría aparecer incrustado dentro de una imagen JPEG sin ser un marcador EOI. Es por eso que tienes que analizar el JPEG para encontrar el marcador EOI. – onemasse

+4

** Resumido **: Lea 0xFF. Marcador de lectura Lea el especificador de longitud L y omita avanzar por L - 2 bytes. Después de un segmento SOS (0xFFDA) (seguido de datos comprimidos) salte al primer 0xFF ** not ** seguido por 0x00 o 0xD0-0xD8. Repita desde el principio hasta que encuentre 0xFFD9. Funciona en [este JPEG de escaneo múltiple] (http://hodapple.com/blag/assets/obscure_jpeg_features/20100713-0107-interleave.jpg). –

+1

Este enfoque es vulnerable a imágenes corruptas (ya sean archivos que se cortaron por accidente o imágenes falsas creadas de forma malintencionada) –

12

Un rápido vistazo a Wikipedia's JPEG article te habría dado la respuesta:

  • bytes 0xFF, 0xd8 indican inicio de imagen
  • bytes 0xFF, 0xD9 indicar el final de la imagen
+5

Es importante tener en cuenta que puede haber archivos JPEG incrustados en archivos JPEG (la imagen en miniatura, por ejemplo), por lo que puede ver los marcadores SOI SOI EOI EOI. Asegúrese de tomar eso en consideración. –

+0

@SB: cierto. Una manera infalible sería escanear en busca de marcadores EOI SOI si no se termina la lectura de la secuencia, y para EOI si está terminado. – darioo

-3

onemase

¿Por qué estás diciendo que no hay garantía de encontrar EOI? Debe estar allí al final.

Hay al menos un marcador más que no está seguido por el campo de 2 bytes de longitud. Es SOS, Inicio del escaneo, 0xFFDA. Esta es seguida por

longitud - Ls especifican como 6 + 2xNs (dos bytes)

número de segmentos Ns (un byte)

siguientes campos de esta cabecera no contienen el tamaño de los datos de entropía que sigue el encabezado SOS. Por lo tanto, la única manera de encontrar el tamaño es buscar byte por byte para EOI (Fin de la imagen) = 0xFFD9.

Me encantaría encontrar otra manera.

+0

Usted está equivocado. No hay garantía de que una imagen JPEG no esté incrustada como una miniatura dentro de un segmento de APP. Al escanear secuencialmente, encontrará EOI prematuramente. – onemasse

+0

Sí. No dije acerca de las imágenes incrustadas. Por lo tanto, la única forma de buscar el tamaño de una secuencia es buscar todos los pares de StartOfImage y EndOfImage en el mismo lugar. Confiar en la longitud no funcionará porque el marcador SOS no va seguido de la longitud. – whobertoos

+1

No, porque la imagen incrustada es solo un ejemplo. El segmento de APP podría contener cualquier cosa, incluido FFD9. Debe buscar de forma secuencial, pero omita los segmentos que pueda. La forma de hacerlo se describe en mi respuesta. – onemasse

0

Si envía las imágenes a través de una matriz de bytes, puede simplemente agregar el tamaño del archivo de la imagen como un par de bytes antes del inicio del archivo.
El cliente toma los dos primeros bytes para encontrar el número especificado de bytes (llamaremos a ese x) y los descarta, luego bombea el siguiente x número de bytes en un búfer que puede escribir en el archivo.
Enjuague y repita para todos los siguientes jpegs.

Una alternativa es simplemente buscar el marcador FFD9 - si no me equivoco, cualquier valor comprimido FF se codificará como FF00 (el octeto de 00 se descarta y el byte FF se mantiene).
El problema con esto es que se obtienen cosas como miniaturas con sus propios encabezados FFD9, pero esos están contenidos dentro de un segmento en los encabezados. Esos segmentos tienen un valor de longitud en los dos bytes después de su marcador, por lo que puede saltar al final de cualquier segmento que encuentre para evitar la detección eoi prematura.