1 puntos por GN⁺ 21 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Al modificar la estructura de múltiples escaneos de un JPEG progresivo, se puede hacer que, en lugar de mejorar la calidad de imagen a medida que avanza la descarga, la imagen ya mostrada vaya cambiando continuamente por otra
  • Cada escaneo especifica canales de color, rango de frecuencias DCT y precisión; si se eliminan algunos marcadores de JPEG de la misma resolución y se concatenan, es posible sobrescribir los datos de renderizado existentes
  • Los decodificadores limitan la cantidad de escaneos que procesan para evitar problemas similares a las bombas de compresión; Chrome renderiza hasta aproximadamente 90 fotogramas y Firefox y otros procesan más
  • Si en cada fotograma se usa solo un escaneo exclusivo de DC, se puede aumentar la cantidad de fotogramas y evitar imágenes residuales, pero por las características de los bloques DCT la resolución resultante baja a 1/16 de la original
  • Se pueden incluir varios fotogramas en un único JPEG como si fuera un video, pero al no haber información de temporización, la velocidad de reproducción depende de la latencia de red; más que para video práctico, es adecuado para experimentos con HTML y aplicaciones de una sola página usando renderizado parcial

Cómo un JPEG progresivo muestra una imagen

  • JPEG guarda primero los componentes de baja frecuencia, de modo que, aun con solo una parte del archivo descargada, puede mostrar una vista previa de baja resolución en vez de una imagen cortada
  • Los datos comprimidos se dividen en varios escaneos (scan), y cada escaneo lleva un encabezado al inicio
    • FF DA es el marcador de inicio de escaneo
    • Luego vienen el campo de longitud, la cantidad e ID de los canales incluidos y el índice de la tabla Huffman
    • Después de especificar el bin DCT inicial y final y la precisión, se guardan los coeficientes DCT codificados con Huffman
  • El primer escaneo incluye el bin de frecuencia DC más bajo de los tres canales de color

YCbCr y mejora gradual de la calidad

  • Los tres canales de color de JPEG usan YCbCr en lugar del RGB común
    • Y es la luminancia, por lo que necesita alta calidad
    • Cb y Cr son componentes de crominancia, así que reducir su calidad no tiene un gran impacto visual
    • Expresado de forma muy aproximada: Y = G, Cb = B - G, Cr = R - G
  • El JPEG de ejemplo completa los datos de forma gradual desde el escaneo 0 hasta el 9
    • Escaneo 0: guarda Y Cb Cr, bin DCT 0–0, con media precisión, y ofrece una vista previa de muy baja resolución
    • Escaneo 1: agrega Y, bins 1–5, con 1/4 de precisión, para reforzar los detalles de luminancia
    • Escaneos 2 y 3: agregan los bins 1–63 de Cb y Cr con media precisión
    • Escaneo 4: completa los bins 6–63 de Y con 1/4 de precisión, cubriendo el rango que dejó pendiente el escaneo 1
    • Escaneo 5: mejora los bins 1–63 de Y con media precisión
    • Escaneos 6–9: agregan el último bit a cada canal para lograr la calidad completa
  • Aunque los datos de crominancia se completan antes que los de luminancia, la crominancia se guarda a media resolución, es decir, con 1/4 de la cantidad de píxeles, por lo que el tamaño total de Cr + Cb es apenas la mitad del de la luminancia

Cambiar la imagen durante la descarga

  • Como cada escaneo indica el rango de frecuencias al que se aplicará, se puede crear un JPEG que sobrescriba datos de imagen ya renderizados con escaneos posteriores
  • Se implementa concatenando varias imágenes de la misma resolución, pero filtrando los siguientes marcadores
    • inicio de imagen (start-of-image)
    • inicio de cuadro (start-of-frame)
    • fin de imagen (end-of-image)
  • También se puede hacer con un editor hexadecimal, pero para la generación real se usa un programa simple en C
  • Si el archivo se transmite por una red lenta, varias imágenes se van alternando una tras otra mientras avanza la descarga

Límite de escaneos en los decodificadores

  • La mayoría de los decodificadores JPEG se detienen tras procesar cierta cantidad de escaneos
  • Se presume que es una restricción para evitar problemas similares a las bombas de compresión, y con el método de concatenación simple es difícil implementar más de 9 fotogramas
  • Para crear animaciones más largas, hay que minimizar la cantidad de escaneos necesarios por fotograma

Por qué no se puede usar Baseline JPEG

  • Empezar con un Baseline JPEG, que usa un solo escaneo, no funciona
  • En modo progresivo no se pueden poner juntos en un mismo escaneo el bin 0, que es datos DC, y los bins 1 o superiores, que son datos AC
  • El modo Baseline no tiene esa restricción, pero un decodificador Baseline detiene el procesamiento después del primer escaneo
  • Como los datos AC deben venir después de los datos DC, el fotograma JPEG progresivo más pequeño se compone de un único escaneo exclusivo de DC

Composición y resolución de fotogramas solo DC

  • Como la DCT se procesa en unidades de bloques de 16×16, incluso incluyendo solo datos DC se puede crear una imagen de 1/16 de la resolución original, no una imagen de color sólido
  • El fotograma mínimo usa un solo escaneo que guarda con precisión completa el bin DCT 0–0 de los tres canales Y Cb Cr
  • Con esta configuración, Chrome renderiza aproximadamente 90 fotogramas antes de detener el procesamiento
    • Otros navegadores, como Firefox, procesan más escaneos
    • Una imagen compuesta por 90 escaneos funciona en casi todos los navegadores

Cambio de fotogramas sin imagen residual

  • La imagen residual del método de concatenación simple se produce porque los escaneos AC están diseñados para refinar los datos existentes
  • En un JPEG progresivo normal, se pueden incluir varias etapas de precisión sin aumentar mucho el tamaño del archivo, pero eso no encaja con el método de reemplazar imágenes
  • Si se usan solo escaneos exclusivos de DC, sin mejora progresiva real, no ocurre el refinamiento de datos AC anteriores y se pueden evitar las imágenes residuales
  • Los fotogramas solo DC son imágenes JPEG que cumplen el estándar, así que no se necesita un codificador especial
    • En la especificación de escaneo se indican solo los bins DC de los tres canales, como 0,1,2:0-0,0,0;

Limitaciones de un video en un único JPEG

  • Si se concatenan fotogramas solo DC, se puede incluir un video completo en un solo archivo JPEG
  • En los escaneos JPEG no hay forma de agregar temporización de fotogramas, así que la velocidad de reproducción depende por completo de la latencia de red
  • Fuera de Rickrolls poco convencionales o bromas, no tiene aplicaciones prácticas

Experimentos que amplían el renderizado parcial

1 comentarios

 
Comentarios de Hacker News
  • Hice algo muy parecido con PNG entrelazado Adam7: https://www.da.vidbuchanan.co.uk/adamation/image.png
    La reproducción al final sí depende de la latencia de red, pero configuré el servidor para enviar cada fotograma por separado a intervalos regulares. Como los fotogramas son pequeños, salvo que la red sea inusualmente lenta, el servidor decide el momento de reproducción

    • Si puedes controlar el servidor HTTP, también podrías configurar Refresh en la cabecera de respuesta para que el cliente obtenga periódicamente un nuevo fotograma de animación[1]. Una entrada del IOCCC de 2013 también actualiza continuamente un reloj renderizado en PNG con esta técnica[2]
      [1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/...
      [2] https://www.ioccc.org/2013/mills/index.html
      En la línea siguiente, la cabecera Refresh está codificada al revés: https://github.com/ioccc-src/winner/blob/619f554bbdb19e5003a...
    • También hice algo parecido para transmitir video en tiempo real con un GIF infinito: https://github.com/jbochi/gifstreaming#live-video-streaming-...
    • Mientras usamos trucos para volver animado a PNG, APNG parece estar al lado gritando “¡yo también existo!”
    • Hace 20 años hice lo mismo con un GIF animado para agregar una capa de calidad del aire en tiempo real a la aplicación de mapas de mi trabajo. Las imágenes se renderizaban con Java2D, e incluso desarrollé una versión con JOGL para generar masas de gradiente en lugar de nubes de puntos, pero no pude terminarla porque el administrador del servidor no permitió instalar los controladores de OpenGL
  • Es una técnica maldita, pero definitivamente encaja aquí

    • Seguro que las grandes empresas tecnológicas ya están pensando cómo usar esto para fingerprinting del navegador
  • Me pregunto si sería posible hacer esteganografía con esta técnica para ocultar datos a simple vista. Es probable que la mayoría de los programas automáticos de análisis de imágenes solo inspeccionen la imagen final, así que parece algo que estudiantes podrían usar para saltarse los filtros de contenido de la escuela

    • Podría usarse como una técnica para confundir a la IA, poniendo un mensaje para humanos en el primer fotograma y otro para la IA en el último. Básicamente derrotar a Skynet enviándose fotos de gatos
    • No parece haber una forma mejor que la esteganografía convencional
  • Creo que podría usarse como barra de progreso para tareas que se cargan en paralelo en la misma red, para que el usuario pueda estimar cuánto retraso queda

    • Recuerdo que en sitios como 4chan bloquearon por completo este comportamiento porque se abusaba de él para ocultar imágenes desagradables o ilegales
  • Si el servidor web genera un “JPEG” al vuelo y se lo envía al cliente en fragmentos espaciados en el tiempo, se puede controlar hasta cierto punto el momento de reproducción. Si usas una webcam como fuente, incluso sería posible un “JPEG” interminable

    • Algunas webcams ya implementan esto con una técnica MIME llamada multipart/x-mixed-replace. El servidor le indica al cliente que reemplace los datos que acaba de enviar con datos nuevos; funciona con HTTP y JPEG normales, sin JavaScript
    • Muchas cámaras IP ya hacen esto con https://en.wikipedia.org/wiki/Motion_JPEG
    • También se puede con GIF. Una vez hice un CGI de juguete que enviaba un GIF fotograma por fotograma y manejaba clics con image maps, de modo que podía usarse como una especie de escritorio remoto sin JavaScript. Quizá JPEG habría sido mejor; valdría la pena intentarlo otra vez
  • Con un Service Worker puedes simular una conexión lenta para controlar la velocidad de reproducción

  • Es raro que el comportamiento cambie según el entorno. En Firefox de escritorio se reproduce bien, pero en iOS móvil el “video completo dentro del JPEG” solo muestra 3 fotogramas casi monocromáticos en marrón→naranja→rojo y apenas el contorno borroso de un gato
    Se nota que funciona porque el color cambia en cada fotograma, pero cuesta llamarlo video. En escritorio sí se reproduce como video real, lo cual me sorprendió, y parece que activa alguna condición límite extraña del decodificador de imágenes de iOS

  • Hace poco estuve trabajando en mostrar imágenes rápidamente con OpenGL y jpeg-turbo, y al activar el modo progresivo de JPEG la decodificación se volvió mucho más lenta. Es posible que aquel viejo consejo de que conviene tener JPEG progresivo ya no sea válido
    Como en décadas casi nunca he visto imágenes volverse gradualmente más nítidas, tampoco parece tener mucho valor práctico

    • Puede que te hayas perdido el momento justo después de cargar la página en que la imagen se veía un poco borrosa y luego se volvía nítida en la siguiente pasada. Ya no es tan irreconocible como antes, pero sigue teniendo valor ofrecer una vista previa de baja resolución con apenas ~30% del tamaño total del archivo, casi gratis
    • Uso cjpegli como codificador, y la mejor compresión sale con la combinación predeterminada de progresivo y 4:4:4 completo, así que no es solo una función extra sin importancia
    • Las fotos JPEG guardadas como progresivas suelen ser aprox. 5% más pequeñas, y también es posible convertir JPEG a formato progresivo sin pérdida. Si lo conviertes sin pérdida a JPEG XL, puedes ahorrar aún más espacio
    • La decodificación progresiva no busca acelerar la decodificación en sí, sino hacer que las imágenes grandes aparezcan antes, sobre todo en conexiones móviles lentas
      Ejemplo: https://youtube.com/watch?v=UphN1_7nP8U
  • Primero pensé en métodos para calcular con dificultad coeficientes de alta frecuencia a partir de los coeficientes “incorrectos” de la primera imagen, pero simplemente combinar dos imágenes es ingenioso. Funciona sorprendentemente bien con solo poner los componentes de baja frecuencia de una imagen seguidos de los componentes de alta frecuencia de otra

  • Me pregunto si también se podrían obtener directamente los componentes de baja frecuencia con una cámara. También me hace pensar en cómo la MRI adquiere primero las bajas frecuencias en el espacio-k