Cómo funciona el formato JPEG

Las imágenes en formato JPEG están presentes en todas partes de nuestra vida digital, pero detrás de esta cobertura de conocimiento se ocultan algoritmos que eliminan detalles que el ojo humano no percibe. El resultado es una calidad visual excepcional con el tamaño de archivo más pequeño posible, pero ¿cómo funciona todo esto exactamente? ¡Veamos qué es lo que nuestros ojos no ven!

Cómo funciona el formato JPEG

Es fácil dar por sentado la posibilidad de enviar una foto a un amigo sin preocuparse por qué dispositivo, navegador o sistema operativo está utilizando; sin embargo, esto no siempre fue así. A principios de la década de 1980, las computadoras podían almacenar y mostrar imágenes digitales, pero había muchas ideas competidoras sobre la mejor manera de hacerlo. No se podía simplemente enviar una imagen de una computadora a otra y esperar que todo funcionara.

Para abordar este problema, en 1986 se reunió un comité de expertos de todo el mundo llamado "Grupo Conjunto de Expertos en Fotografía" (Joint Photographic Experts Group, JPEG), formado como parte de la colaboración entre la Organización Internacional de Normalización (ISO) y la Comisión Electrotécnica Internacional (IEC), dos organizaciones internacionales de normalización con sede en Ginebra (Suiza).

El grupo de personas conocido como JPEG creó el estándar de compresión de imágenes digitales JPEG en 1992. Cualquiera que haya usado internet probablemente se ha encontrado con imágenes codificadas en JPEG. Es la forma más común de codificar, enviar y almacenar imágenes. Desde páginas web hasta correos electrónicos y redes sociales, se utiliza JPEG miles de millones de veces al día, prácticamente cada vez que miramos una imagen en línea o la enviamos. Sin JPEG, la web sería menos vibrante, más lenta y probablemente tendría menos fotos de gatos.

Este artículo trata sobre cómo decodificar una imagen JPEG. En otras palabras, se trata de lo que se necesita para convertir los datos comprimidos almacenados en la computadora en una imagen que aparece en la pantalla. Esto es algo que vale la pena saber no solo porque es importante para entender la tecnología que utilizamos a diario, sino también porque al desvelar los niveles de compresión, aprendemos más sobre la percepción y la visión, así como sobre los detalles a los que nuestros ojos son más sensibles.

Además, jugar con imágenes de esta manera es muy interesante.

Cómo funciona el formato JPEG

Mirando dentro de un JPEG

En la computadora, todo se almacena como una secuencia de números binarios. Normalmente, estos bits, ceros y unos, se agrupan de a ocho, formando bytes. Cuando abres una imagen JPEG en la computadora, algo (el navegador, el sistema operativo, algo más) debe decodificar los bytes, restaurando la imagen original como una lista de colores que se pueden mostrar.

Si descargas esta entrañable foto de un gato y la abres en un editor de texto, verás un montón de símbolos sin sentido.

Cómo funciona el formato JPEG
Aquí utilizo Notepad++ para estudiar el contenido del archivo, ya que los editores de texto comunes, como el Bloc de notas de Windows, dañarán el archivo binario después de guardarlo, y dejará de cumplir con el formato JPEG.

Al abrir una imagen en un editor de texto, confundes a la computadora de la misma manera que confundes a tu cerebro cuando frotas tus ojos y comienzas a ver manchas de colores.

Estas manchas que ves son conocidas como fósfenos, y no son el resultado de un estímulo lumínico ni alucinaciones provocadas por la mente. Ocurren porque tu cerebro asume que cualquier señal eléctrica en los nervios ópticos transmite información sobre la luz. El cerebro necesita hacer tales suposiciones, ya que no se puede saber si la señal es sonido, visión o algo más. Todos los nervios en el cuerpo transmiten impulsos eléctricos absolutamente iguales. Al presionar sobre los ojos, envías señales que no son visuales, pero que activan los receptores del ojo, lo que tu cerebro interpreta, en este caso erróneamente, como algo visual. ¡Literalmente puedes ver la presión!

Es curioso pensar en cuánto se parecen las computadoras al cerebro; sin embargo, también es una analogía útil que ilustra cuán dependiente es el significado de los datos, ya sea transmitidos por el cuerpo a través de los nervios o almacenados en una computadora, de su interpretación. Todos los datos binarios están compuestos de ceros y unos, componentes básicos que pueden transmitir información de cualquier tipo. Tu computadora a menudo adivina cómo interpretarlos mediante pistas, como extensiones de archivos. Y ahora le estamos pidiendo que los interprete como texto, ya que eso es lo que espera un editor de texto.

Para entender cómo decodificar un JPEG, necesitamos ver las señales originales: los datos binarios. Esto se puede hacer con un editor hexadecimal, o directamente en la página web del artículo original! Allí hay una imagen junto a la cual en el cuadro de texto se presentan todos sus bytes (excepto el encabezado), representados en forma decimal. Puedes cambiarlos, y el script recodificará y generará una nueva imagen sobre la marcha.

Cómo funciona el formato JPEG

Se puede aprender mucho jugando con este editor. Por ejemplo, ¿puedes decir en qué orden se almacenan los píxeles?

Lo curioso de este ejemplo es que cambiar algunos números no afecta en absoluto la imagen, pero, por ejemplo, si reemplazas el número 17 por 0 en la primera línea, ¡la foto queda completamente arruinada!

Cómo funciona el formato JPEG

Otros cambios, como reemplazar 7 en la línea 1988 por el número 254, cambian el color, pero solo de los píxeles subsiguientes.

Cómo funciona el formato JPEG

Quizás lo más extraño sea que algunos números no solo cambian el color, sino también la forma de la imagen. Cambia el 70 en la línea 12 por 2 y observa la fila superior de la imagen para ver a qué me refiero.

Cómo funciona el formato JPEG

Y sin importar qué imagen JPEG estés utilizando, siempre encontrarás esas misteriosas secuencias de ajedrez al editar bytes.

Al jugar con el editor, es difícil entender cómo se recrea la foto a partir de estos bytes, ya que la compresión JPEG consta de tres tecnologías diferentes que se aplican de manera secuencial a diferentes niveles. Estudiaremos cada una de ellas por separado para desvelar el comportamiento misterioso que observamos.

Tres niveles de compresión JPEG:

  1. Submuestreo de color.
  2. Transformada discreta de coseno y cuantificación.
  3. Codificación de longitud de serie, delta y Huffman

Para que puedas imaginar la magnitud de la compresión, ten en cuenta que la imagen mostrada arriba representa 79,819 números, es decir, alrededor de 79 KB. Si la almacenáramos sin compresión, necesitaríamos tres números por cada píxel, uno para el componente rojo, uno para el verde y otro para el azul. Eso sumaría 917,700 números, o aproximadamente 917 KB. Como resultado de la compresión JPEG, el archivo final se ha reducido más de 10 veces.

De hecho, esta imagen se puede comprimir mucho más. A continuación, se muestran dos imágenes una al lado de la otra: la foto de la derecha fue comprimida a 16 KB, es decir, 57 veces menos que la versión sin comprimir.

Cómo funciona el formato JPEG

Si te fijas bien, verás que estas imágenes no son idénticas. Ambas son imágenes con compresión JPEG, sin embargo, la de la derecha es mucho más pequeña en tamaño. También se ve un poco peor (observa los cuadrados de los colores de fondo). Por eso, la compresión JPEG también se llama compresión con pérdida; durante el proceso de compresión, la imagen cambia y pierde algunos detalles.

1. Submuestreo de color

Esta es una imagen utilizando solo el primer nivel de compresión.

Cómo funciona el formato JPEG
(La versión interactiva está en el original del artículo). La eliminación de un número arruina todos los colores. Sin embargo, si eliminas exactamente seis números, esto prácticamente no afecta a la imagen.

Ahora los números son un poco más fáciles de descifrar. Es casi una lista simple de colores, donde cada byte afecta exactamente un píxel, pero está en dos veces menos tamaño que la imagen sin comprimir (que ocuparía alrededor de 300 KB en este tamaño reducido). ¿Adivinas por qué?

Se puede ver que estos números no designan los componentes estándar rojo, verde y azul, ya que si reemplazamos todos los números por ceros, obtendremos una imagen verde (y no blanca).

Cómo funciona el formato JPEG

Esto se debe a que estos bytes representan Y (brillo),

Cómo funciona el formato JPEG

Cb (azul relativo),

Cómo funciona el formato JPEG

y Cr (rojo relativo) de la imagen.

Cómo funciona el formato JPEG

¿Por qué no usar RGB? Después de todo, así es como funciona la mayoría de las pantallas modernas. Tu monitor puede mostrar cualquier color, incluidos los colores rojo, verde y azul con diferentes intensidades para cada píxel. El blanco se obtiene al encender los tres a máxima intensidad, y el negro al apagarlos.

Cómo funciona el formato JPEG

Esto también es muy similar a cómo funciona el ojo humano. Los receptores de color de nuestros ojos se llaman “conos«, y se dividen en tres tipos, cada uno de los cuales es más sensible ya sea al rojo, al verde o al azul [los conos S son sensibles en la parte violeta-azulada (S de inglés Short — espectro de onda corta), los M en la parte verde-amarilla (M de inglés Medium — onda media), y los L en la parte amarillo-roja (L de inglés Long — onda larga) del espectro. La presencia de estos tres tipos de conos (y bastones, sensibles en la parte verde esmeralda del espectro) le da al ser humano visión a color. / nota del traductor]. Bastones, otro tipo de fotorreceptores en nuestros ojos, capaz de detectar cambios en el brillo, aunque es mucho más sensible al color. En nuestros ojos hay aproximadamente 120 millones de bastones y solo 6 millones de conos.

Por lo tanto, nuestros ojos son mucho mejores para notar cambios en el brillo que cambios en el color. Si se separa el color del brillo, se puede quitar un poco de color y nadie notará la diferencia. La subdiscretización del color es el proceso de representar los componentes de color de una imagen en una menor resolución en comparación con los componentes de brillo. En el ejemplo anterior, cada píxel tiene exactamente un componente Y, mientras que cada grupo de cuatro píxeles tiene exactamente un componente Cb y un Cr. Por lo tanto, la imagen contiene cuatro veces menos información de color que la original.

El espacio de color YCbCr se utiliza no solo en JPEG. Fue concebido originalmente en 1938 para transmisiones de televisión. No todos tienen un televisor en color, por lo que la separación del color y el brillo permitió que todos recibieran la misma señal, y los televisores en blanco y negro simplemente usaban solo el componente de brillo.

Por lo tanto, eliminar un número del editor derriba completamente todos los colores. Los componentes se almacenan en forma de Y Y Y Y Cb Cr (en realidad, no necesariamente en ese orden — el orden de almacenamiento se define en el encabezado del archivo). Eliminar el primer número hará que el primer valor de Cb se perciba como Y, Cr como Cb, y en general se obtendrá un efecto dominó que cambiará todos los colores de la imagen.

La especificación JPEG no le obliga a utilizar YCbCr. Pero en la mayoría de los archivos, se utiliza, ya que proporciona imágenes de mejor calidad después de la subsampling en comparación con RGB. Pero no tiene por qué creerme en mi palabra. Véalo usted mismo en la tabla a continuación, cómo se verán la submuestreo de cada componente individual tanto en RGB como en YCbCr.

Cómo funciona el formato JPEG
(La versión interactiva está en el original artículos).

La eliminación del azul no es tan notable como la del rojo o el verde. Esto se debe a que de los seis millones de conos en sus ojos, alrededor del 64 % son sensibles al rojo, el 32 % al verde y el 2 % al azul.

La submuestreo del componente Y (abajo a la izquierda) es la más visible. Incluso un pequeño cambio es notable.

Convertir una imagen de RGB a YCbCr no reduce el tamaño del archivo, pero facilita la búsqueda de detalles menos visibles que se pueden eliminar. La compresión con pérdida ocurre en la segunda etapa. Se basa en la idea de representar los datos de una manera más comprimible.

2. Transformada discreta del coseno y submuestreo

Este nivel de compresión en gran medida define la esencia de JPEG. Después de convertir los colores a YCbCr, los componentes se comprimen por separado, por lo que después podemos centrarnos solo en el componente Y. Y así es como se ven los bytes del componente Y después de aplicar este nivel.

Cómo funciona el formato JPEG
(La versión interactiva está en el original artículos). En la versión interactiva, hacer clic en un píxel desplaza el editor a la línea que lo designa. Intente eliminar números desde el final o añadir algunos ceros a un número determinado.

A primera vista, parece una compresión muy mala. En una imagen de 100,000 píxeles, se requieren 102,400 números para denotar su brillo (componentes Y); ¡eso es peor que no comprimir nada en absoluto!

Sin embargo, tenga en cuenta que la mayoría de estos números son cero. Además, todos esos ceros al final de las filas se pueden eliminar sin alterar la imagen. Quedan alrededor de 26,000 números, ¡eso ya es casi 4 veces menos!

En este nivel se encuentra el secreto de los patrones de ajedrez. A diferencia de otros efectos que hemos visto, la aparición de estos patrones no es un glitch. Son los bloques de construcción de toda la imagen. En cada fila del editor hay exactamente 64 números, coeficientes de la transformada discreta del coseno (DCT), que corresponden a las intensidades de 64 patrones únicos.

Estos patrones se forman en base a la gráfica del coseno. Así es como se ven algunos de ellos:

Cómo funciona el formato JPEG
8 de 64 coeficientes

A continuación, se muestra una imagen que demuestra todos los 64 patrones.

Cómo funciona el formato JPEG
(La versión interactiva está en el original artículos).

Estos patrones tienen un significado especial, ya que forman la base de las imágenes de tamaño 8x8. Si no estás familiarizado con el álgebra lineal, esto significa que cualquier imagen de tamaño 8x8 se puede obtener a partir de estos 64 patrones. DCT es el proceso de dividir imágenes en bloques de 8x8 y transformar cada bloque en una combinación de estos 64 coeficientes.

Que cualquier imagen se pueda componer de 64 patrones determinados parece magia. Sin embargo, es lo mismo que decir que cualquier lugar en la Tierra se puede describir con dos números: latitud y longitud [indicando hemisferios / nota del traductor]. A menudo consideramos la superficie de la Tierra como bidimensional, por lo que solo necesitamos dos números. Una imagen de 8x8 tiene 64 dimensiones, así que necesitamos 64 números.

Aún no está claro cómo esto nos ayuda en términos de compresión. Si necesitamos 64 números para representar una imagen de 8x8, ¿por qué este método sería mejor que simplemente almacenar 64 componentes de brillo? Lo hacemos por la misma razón que convertimos tres números RGB en tres números YCbCr: esto nos permite eliminar detalles imperceptibles.

Es difícil ver qué detalles se eliminan en esta etapa, ya que JPEG aplica DCT a bloques de 8x8. Sin embargo, nadie nos impide aplicarlo a toda la imagen. Así es como se ve DCT aplicado al componente Y en una imagen completa:

Cómo funciona el formato JPEG

Desde el final se pueden eliminar más de 60,000 números prácticamente sin cambios visibles en la foto.

Cómo funciona el formato JPEG

Sin embargo, ten en cuenta que si anulamos los primeros cinco números, la diferencia será evidente.

Cómo funciona el formato JPEG

Los números al principio representan cambios de baja frecuencia en la imagen, y nuestros ojos los detectan mejor. Los números más cercanos al final representan cambios de alta frecuencia, que son más difíciles de notar. Para 'ver lo que no ve el ojo', podemos aislar estos detalles de alta frecuencia anulando los primeros 5000 números.

Cómo funciona el formato JPEG

Vemos todas las áreas de la imagen donde ocurren los cambios más significativos de un píxel a otro. Se destacan los ojos del gato, sus bigotes, la manta de felpa y las sombras en la esquina inferior izquierda. Se puede ir más allá, anulando los primeros 10,000 números:

Cómo funciona el formato JPEG

20 000:

Cómo funciona el formato JPEG

40 000:

Cómo funciona el formato JPEG

60 000:

Cómo funciona el formato JPEG

Estos componentes de alta frecuencia JPEG se eliminan en la etapa de compresión. La conversión de colores a coeficientes DCT no tiene pérdidas. Las pérdidas ocurren en el paso de muestreo, donde se eliminan las magnitudes de alta frecuencia o cercanas a cero. Al reducir la calidad de guardado JPEG, el programa aumenta el umbral de la cantidad de valores eliminados, lo que resulta en una disminución del tamaño del archivo, pero hace que la imagen se vea más pixelada. Por lo tanto, la imagen en la primera sección, que era 57 veces más pequeña, se veía así. Cada bloque de 8x8 se representaba con una cantidad mucho menor de coeficientes DCT en comparación con una versión de mayor calidad.

Se puede lograr un efecto increíble, como la transmisión progresiva de imágenes. Se puede mostrar una imagen borrosa que se vuelve cada vez más detallada a medida que se descargan más coeficientes.

Aquí, solo por curiosidad, lo que resultará al usar solo 24,000 números:

Cómo funciona el formato JPEG

O solo 5,000:

Cómo funciona el formato JPEG

Muy borroso, ¡pero reconocible!

3. Codificación de longitud de serie, delta y Huffman

Hasta ahora, todas las etapas de compresión han sido con pérdida. La última etapa, en cambio, es sin pérdida. No elimina información, pero reduce significativamente el tamaño del archivo.

¿Cómo se puede comprimir algo sin desechar información? Imagina cómo describiríamos un simple rectángulo negro de 700 x 437.

JPEG utiliza para esto 5,000 números, pero se puede lograr un resultado mucho mejor. ¿Puedes imaginar un esquema de codificación que describa tal imagen con la menor cantidad posible de bytes?

El esquema mínimo que se me ocurrió utiliza cuatro: tres para representar el color y el cuarto — cuántos píxeles tienen ese color. La idea de representar valores repetidos de esta manera tan compacta se llama codificación de longitud de serie. No tiene pérdidas, ya que podemos restaurar los datos codificados en su forma original.

El tamaño del archivo JPEG con un rectángulo negro es mucho mayor de 4 bytes; recuerde que a nivel de DCT, la compresión se aplica a bloques de 8x8 píxeles. Por lo tanto, necesitamos al menos un coeficiente DCT por cada 64 píxeles. Necesitamos uno porque, en lugar de almacenar un coeficiente DCT seguido de 63 ceros, la codificación por longitud de series nos permite almacenar un solo número y señalar que 'todos los demás son ceros'.

La codificación delta es una técnica en la que cada byte contiene la diferencia respecto a un cierto valor, en lugar de una magnitud absoluta. Por lo tanto, editar ciertos bytes cambia el color de todos los otros píxeles. Por ejemplo, en lugar de almacenar

12 13 14 14 14 13 13 14

Podríamos comenzar con 12 y luego simplemente indicar cuánto hay que sumar o restar para obtener el siguiente número. Y esta secuencia en la codificación delta toma la forma de:

12 1 1 0 0 -1 0 1

Los datos transformados no son menores que los originales, pero son más fáciles de comprimir. La aplicación de la codificación delta antes de la codificación por longitud de series puede ser de gran ayuda, manteniéndose como una compresión sin pérdidas.

La codificación delta es una de las pocas técnicas utilizadas fuera de los bloques de 8x8. De los 64 coeficientes DCT, uno es simplemente una función de onda constante (color sólido). Representa el brillo promedio de cada bloque para los componentes de brillo, o la media de azul para los componentes Cb, y así sucesivamente. El primer valor de cada bloque DCT se llama valor DC, y cada valor DC se codifica en delta en relación con los anteriores. Por lo tanto, el cambio en el brillo del primer bloque afectará a todos los bloques.

Queda un último misterio: ¿cómo puede el cambio de un solo número arruinar completamente toda la imagen? Hasta ahora, no había propiedades como estas en los niveles de compresión. La respuesta radica en el encabezado JPEG. Los primeros 500 bytes contienen metadatos sobre la imagen: ancho, alto, etc., y hasta que no hayamos trabajado con ellos.

Sin el encabezado, es prácticamente imposible (bueno, o muy difícil) decodificar un JPEG. Sería como si tratara de describirle una pintura y comenzara a inventar palabras para transmitir mi impresión. La descripción probablemente será bastante concisa, ya que puedo inventar palabras con el significado que quiero transmitir, sin embargo, para todos los demás, no tendrán sentido.

Suena tonto, pero así es como ocurre. Cada imagen JPEG se comprime con códigos específicos para ella. El diccionario de códigos se almacena en el encabezado. Esta técnica se llama 'código Huffman', y el diccionario es la tabla de Huffman. En el encabezado, la tabla está marcada por dos bytes: 255 y luego 196. Cada componente de color puede tener su propia tabla.

Los cambios en las tablas afectarán radicalmente a cualquier imagen. Un buen ejemplo es cambiar el 1 en la línea 15 por un 12.

Cómo funciona el formato JPEG

Esto sucede porque las tablas indican cómo leer los bits individuales. Hasta ahora, solo hemos trabajado con números binarios en forma decimal. Pero esto oculta el hecho de que si deseas almacenar el número 1 en un byte, se verá como 00000001, ya que en cada byte debe haber exactamente ocho bits, incluso si solo se necesita uno de ellos.

Potencialmente, esto es un gran desperdicio de espacio si tienes muchos números pequeños. El código Huffman es una técnica que nos permite relajar este requisito de que cada número debe ocupar ocho bits. Esto significa que si ves dos bytes:

234 115

dependiendo de la tabla de Huffman, esto puede representar tres números. Para extraerlos, primero necesitas dividirlos en bits individuales:

11101010 01110011

Luego, consultamos la tabla para entender cómo agruparlos. Por ejemplo, pueden ser los primeros seis bits (111010), o 58 en sistema decimal, seguidos de cinco bits (10011), o 19, y finalmente los últimos cuatro bits (0011), o 3.

Por lo tanto, es muy difícil entender los bytes en esta etapa de compresión. Los bytes no representan lo que parece. No entraré en los detalles del funcionamiento de la tabla en este artículo, pero materiales sobre este tema en la red hay suficiente.

Uno de los trucos interesantes que se pueden hacer al saber esto es separar el encabezado del JPEG y almacenarlo por separado. En esencia, solo tú podrás leer el archivo. Facebook hace esto para reducir aún más los archivos.

Otra cosa que se puede hacer es modificar ligeramente la tabla de Huffman. Para otros, esto parecerá una imagen dañada. Y solo tú sabrás la versión mágica para corregirla.

En resumen, ¿qué se necesita para decodificar un JPEG? Es necesario:

  1. Extraer la tabla (tablas) de Huffman del encabezado y decodificar los bits.
  2. Extraer los coeficientes de la transformación discreta del coseno para cada componente de color y brillo de cada bloque 8x8, realizando las transformaciones inversas de codificación de longitud de series y deltas.
  3. Combinar los cosenos en base a los coeficientes para obtener los valores de píxeles para cada bloque de 8x8.
  4. Escalar los componentes de color si se realizó la submuestreo (esta información está en el encabezado).
  5. Convertir los valores YCbCr obtenidos para cada píxel a RGB.
  6. ¡Mostrar la imagen en la pantalla!

¡Un trabajo serio para simplemente ver una foto de un gato! Sin embargo, lo que me gusta de esto es cómo la tecnología JPEG está centrada en el ser humano. Se basa en las características de nuestra percepción, lo que permite lograr una compresión mucho mejor que las tecnologías convencionales. Y ahora, al entender cómo funciona JPEG, se puede imaginar cómo estas tecnologías podrían trasladarse a otras áreas. Por ejemplo, la codificación delta en el video podría proporcionar una reducción significativa del tamaño del archivo, ya que a menudo hay áreas completas que no cambian de un fotograma a otro (por ejemplo, el fondo).

El código utilizado en el artículo, es abierto y contiene instrucciones sobre cómo reemplazar imágenes por las propias.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster