Estaba buscando métodos de rotación de imágenes sin pérdidas y encontré esta pregunta que lo explica bastante bien:
¿Son las rotaciones de "Windows Photo Viewer" sin pérdidas?
Así que creé un JPEG de 256 × 256 con píxeles aleatorios (filtro de nube de Photoshop) y luego lo giré usando Windows Picture Viewer. Después de la rotación, el tamaño del archivo aumentó, pero solo en la primera rotación. Cada rotación posterior a partir de entonces, el tamaño del archivo se mantuvo estático. Sé que está girando sin pérdidas porque lo he girado varias veces sin pérdida de calidad notable, mientras que una imagen de 257 × 257 rotada 20 veces se volvió muy con pérdidas.
Lo más probable es que esto se deba a la codificación de entropía , que es la etapa final sin pérdidas de la compresión JPEG, después de que los datos de la imagen se han cuantificado para reducir su tamaño.
Cuando una imagen JPEG se gira sin pérdidas, esta capa final de codificación sin pérdidas se debe deshacer, los coeficientes DCT desempaquetados se mezclan y luego los coeficientes mezclados deben codificarse en entropía nuevamente. Dado que la eficiencia de la capa de codificación de entropía depende del orden de los coeficientes DCT dentro de cada bloque, que cambiará al rotar la imagen, no debería sorprender que el archivo de imagen rotado pueda ser un poco más pequeño o más grande que el original.
También hay varias formas diferentes en las que se puede realizar el paso de codificación de entropía, por lo que es muy posible que el tamaño del archivo de exactamente la misma imagen JPEG varíe según el software que realiza la codificación. Algunas de las posibles diferencias entre los codificadores incluyen:
Además, los "archivos JPEG" con los que la gente trabaja normalmente contienen datos de imagen comprimidos en JPEG envueltos en un contenedor JFIF o Exif , que combina los datos de imagen con uno o más bloques de metadatos e introduce su propio conjunto de complicaciones. Incluso si el software que gira la imagen en realidad no realiza ningún cambio sustancial en los metadatos JFIF/Exif, simplemente reorganizar los datos podría afectar el tamaño del archivo en unos pocos bytes.
En particular, los metadatos JFIF/Exif pueden contener una o más miniaturas de la imagen de tamaño completo, y el software que rota las imágenes realmente debería regenerar (¡o también rotar sin pérdidas!) las miniaturas para que coincidan con la nueva orientación de la imagen completa. imagen de tamaño Esto solo podría explicar fácilmente la diferencia de tamaño observada.
Seguí adelante y repetí el experimento para ver si podía averiguar qué estaba pasando.
Generé una imagen RGB aleatoria de 256 por 256 píxeles usando el filtro "Ruido sólido" en GIMP (Filtros> Renderizar> Nubes> Ruido sólido...) usando la configuración predeterminada (que se muestra a continuación):
Y el resultado:
Luego guardé la imagen como JPEG usando la configuración predeterminada:
Luego transfirí la imagen a Windows y la abrí con Windows Photo Viewer haciendo clic con el botón derecho en la imagen en el Explorador de archivos y eligiendo Vista previa en el menú. Luego giré la imagen usando los botones en la parte inferior y guardé la imagen navegando a la siguiente imagen usando las teclas de flecha.
Para cada una de las siguientes pruebas, comencé con una copia de la imagen original y giré (haciendo clic en el botón de rotación) la cantidad correspondiente de veces antes de guardar. Aquí están los tamaños restantes ( ls -l -r
):
size in bytes last-modified date
VVVVV VVVVV
-rwxrwx--- 1 root vboxsf 6258 Nov 8 11:24 original.jpg
-rwxrwx--- 1 root vboxsf 23645 Nov 8 11:30 cw.jpg
-rwxrwx--- 1 root vboxsf 23636 Nov 8 11:30 cw-cw.jpg
-rwxrwx--- 1 root vboxsf 23649 Nov 8 11:30 cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf 6258 Nov 8 11:27 cw-cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf 23649 Nov 8 11:31 cw-cw-cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf 23649 Nov 8 11:29 ccw.jpg
-rwxrwx--- 1 root vboxsf 23636 Nov 8 11:29 ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf 23645 Nov 8 11:29 ccw-ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf 6258 Nov 8 11:27 ccw-ccw-ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf 23649 Nov 8 11:30 ccw-ccw-ccw-ccw-ccw.jpg
El uso cmp -l
de archivos que deberían tener contenido idéntico nos permite ver dónde difieren los archivos.
robert@unity ../jpeg-rotate-test % cmp -l cw.jpg ccw-ccw-ccw.jpg
2223 63 62
2224 60 71
2226 60 64
2227 60 66
robert@unity ../jpeg-rotate-test % cmp -l cw-cw.jpg ccw-ccw.jpg
2223 63 62
2224 60 71
2226 60 64
2227 62 64
robert@unity ..jpeg-rotate-test % cmp -l ccw.jpg cw-cw-cw.jpg
2223 62 63
2224 71 60
2226 64 60
2227 61 64
robert@unity ../jpeg-rotate-test % cmp -l cw.jpg cw-cw-cw-cw-cw.jpg
2221 60 61
2223 63 61
2224 60 66
2226 60 61
2227 60 61
robert@unity ../jpeg-rotate-test % cmp -l ccw.jpg ccw-ccw-ccw-ccw-ccw.jpg
2223 62 63
2224 71 60
2226 64 65
2227 61 64
Estos archivos difieren en solo cuatro bytes (en realidad, en una marca de tiempo), lo que significa que WPV hace lo mismo cada vez; ahora solo tenemos que averiguar qué es eso.
Para esto usé JPEGsnoop para ver qué había exactamente en las imágenes.
Dado que los resultados son bastante largos, los he vinculado como esencia . He aquí un resumen de las diferencias:
GIMP usa solo un segmento APP0
(JFIF) y COM
(comentario) para los metadatos. WPV deja el APP0
segmento intacto, pero curiosamente agrega un byte nulo al comentario (para que termine en nulo).
WPV agrega dos APP1
segmentos, que son metadatos Exif y XMP. Estos segmentos son 4286 y 12726 bytes, respectivamente. Juntos representan casi todo el aumento en el tamaño del archivo.
GIMP produce un JPEG progresivo, mientras que WPV produce un JPEG básico (no progresivo). Por esta razón, la imagen de GIMP tiene varios segmentos de escaneo, mientras que la imagen de WPV solo tiene uno. En mi experiencia, la imagen progresiva a veces es un poco más pequeña.
GIMP usó submuestreo de croma 1 × 1, mientras que WPV usó submuestreo 2 × 2. Esto me lleva a creer que WPV no está utilizando una rotación sin pérdidas "verdadera", a menos que de alguna manera pueda detectar que se trata de una imagen en blanco y negro.
Para resolver estos problemas, realicé una segunda prueba.
Seguí pasos similares a la primera prueba. Creé una imagen RGB aleatoria de 256 × 256 usando el filtro de ruido RGB (Filtros > Nariz > Nariz RGB...) con la siguiente configuración:
Aquí está el resultado:
Exporté el archivo como JPEG usando la siguiente configuración:
El progresivo se ha desactivado, pero el submuestreo aún está configurado en 4:4:4 (que es otro nombre para el submuestreo 1×1). La calidad se incrementa a 98.
Copié la imagen y giré la copia en el sentido de las agujas del reloj; luego copió la versión rotada y giró esa copia en sentido contrario a las agujas del reloj, de modo que podamos comparar directamente la calidad entre el original y la copia procesada por WPV.
-rwxrwx--- 1 root vboxsf 159774 Nov 8 16:21 original-random.jpg
-rwxrwx--- 1 root vboxsf 222404 Nov 8 16:24 cw-random.jpg
-rwxrwx--- 1 root vboxsf 222467 Nov 8 16:24 cw-ccw-random.jpg
Aunque el aumento esta vez es menor en términos relativos (alrededor del 40%), el aumento absoluto es aún mayor, alrededor de 62 kB. Esto sugiere que WMV está utilizando una codificación menos eficiente.
Usaré ImageMagick para comparar las dos imágenes:
robert@unity ../jpeg-rotate-test % compare -verbose -metric AE original-random.jpg cw-ccw-random.jpg null:
original-random.jpg JPEG 256x256 256x256+0+0 8-bit sRGB 160KB 0.000u 0:00.009
cw-ccw-random.jpg JPEG 256x256 256x256+0+0 8-bit sRGB 222KB 0.010u 0:00.010
Image: original-random.jpg
Channel distortion: AE
red: 0
green: 0
blue: 0
all: 0
original-random.jpg=> JPEG 256x256 256x256+0+0 8-bit sRGB 0.050u 0:00.020
Hay cero píxeles diferentes entre el original y la copia girada. Por lo tanto, incluso si WPV no usa una rotación sin pérdidas "verdadera", está haciendo un trabajo suficientemente bueno. Sospecho que sé lo que está pasando, y para explicarlo, me desviaré un poco hacia las matemáticas detrás de la compresión JPEG.
El algoritmo de compresión JPEG divide una imagen en bloques de 8×8 píxeles. A continuación, cada uno de estos bloques se somete a una transformada de coseno discreta (DCT) . Los coeficientes DCT resultantes describen el bloque como una suma de ondas de diferentes frecuencias. Luego, el algoritmo "descarta" cierta información en las ondas de alta frecuencia que corresponden al ruido y al detalle muy pequeño. El proceso de decodificación invierte la DCT, sumando las ondas almacenadas para recuperar el bloque.
Es posible rotar las "ondas" DCT sin deshacer y rehacer realmente la transformación (básicamente, convierte todas las ondas horizontales en ondas verticales y viceversa). Lo que creo que sucede en WPV es que la imagen en realidad se decodifica, gira y luego se vuelve a codificar. Durante el proceso de recodificación, dado que el tamaño de nuestra imagen es múltiplo de 8 en ambas dimensiones, cada uno de los nuevos bloques corresponde a uno de los bloques originales. Es importante destacar que, dado que cada bloque no tiene componentes de alta frecuencia, el algoritmo no descarta ninguna información y encuentra exactamente los componentes DCT correctos que tendría una rotación "verdadera" sin pérdidas.
Por último, volveré a examinar los componentes de los archivos JPEG. Los resultados están nuevamente vinculados como esencias . Comparando los dos:
La imagen WPV contiene 4286+2 bytes adicionales de metadatos Exif, 1 byte adicional en el comentario y 12 726+2 bytes de metadatos XMP. Esto es un total de 17.017 bytes de metadatos adicionales. ¿Para qué se utilizan todos esos datos? Miré el archivo con mi confiable editor hexadecimal y una copia de los estándares relevantes:
Los metadatos Exif están estructurados como una imagen TIFF, que contiene una serie de etiquetas (hay mucha más complejidad, pero lo pasaré por alto). La mayoría de los bytes en el segmento Exif están contenidos en dos etiquetas idénticas con número de etiqueta EA1C
(59,932 decimal). Ese número de etiqueta no está documentado en ningún lugar que pueda encontrar. Ambas etiquetas contienen 2060 bytes de tipo "indefinido", que son todos bytes nulos excepto los primeros seis ( 1C EA 00 00 00 08
). No tengo idea de qué son estas etiquetas, por qué hay dos y por qué deben tener 2 kB cada una.
Los metadatos XMP son en realidad un documento XML incrustado completo con espacio de nombres y UUID largos, que solo contiene la cadena de versión WPV (que ya estaba en los metadatos Exif). Sin embargo, eso solo representa alrededor de 400 bytes. El resto del segmento son 122 repeticiones de 100 espacios seguidos de una nueva línea . Eso es más de 12.000 bytes de espacio totalmente desperdiciado.
Al igual que la prueba anterior, tanto GIMP como WPV utilizan las mismas tablas de cuantificación DCT. Esto significa que deberían estar calculando exactamente los mismos coeficientes DCT, razón por la cual las imágenes son exactamente iguales. No estoy seguro de si WPV está usando las mismas tablas de cuantificación o si copia las tablas de la entrada.
A diferencia de la prueba anterior, esta vez WPV usa submuestreo 1×1, por lo que en realidad puede estar detectando que se trata de una imagen en color (o al menos que se necesitan muestras más altas para volver a codificar la imagen sin pérdidas).
GIMP y WPV usan diferentes tablas de Huffman (parte del paso de codificación de entropía). Las tablas para WPV son más grandes en un total de 279 bytes y en un caso contienen 7 veces más códigos.
Mirando las estadísticas de JPEGsnoop, podemos ver que algunos de estos códigos rara vez se usan. Por ejemplo, en la ID: 1, Class: AC
tabla, de los 119 códigos de 16 bits definidos, solo se utilizan 23. En general, el segmento de escaneo real es un 28,5 % más grande en la versión WPV.
Es posible que WPV no esté haciendo rotaciones "verdaderas" sin pérdidas, pero las rotaciones parecen ser prácticamente sin pérdidas.
El tamaño adicional se debe en parte a una cantidad fija de metadatos agregados y en parte a una codificación de entropía menos eficiente.
Sistema operativo (Linux) ( uname -a
):
Linux unity 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux
SO (Windows):
GIMP (Linux): 2.8.14 (del paquete gimp
, versión 2.8.14-1+deb8u1
)
Window Photo Viewer (según los metadatos de la imagen):
Microsoft Windows Photo Viewer 10.0.10586.0
EDITAR : esta respuesta se publicó antes de que supiera que los archivos habían aumentado de tamaño en alrededor de 9 KiB (9055 bytes para la imagen de 256 × 256, 9612 KiB para la imagen de 512 × 512).
Con toda probabilidad, cuando giró la imagen por primera vez, Windows Picture Viewer hizo una (o ambas) de las siguientes cosas:
Esto aumentó el tamaño del archivo debido a la etiqueta EXIF adicional (y/o datos adicionales a las etiquetas existentes).
Las rotaciones posteriores no aumentaron el tamaño del archivo porque todas las etiquetas y/o datos de etiquetas que WPV habría agregado/modificado ya estaban allí. Solo cambió el valor de la etiqueta de orientación (y quizás también los valores de la etiqueta de fecha/hora).
EDITAR : es casi seguro que esta explicación no puede dar cuenta de aproximadamente 9 KiB de datos adicionales en el archivo. Además, en ausencia de otras razones para el aumento de tamaño, esta explicación esperaría que el aumento de tamaño fuera más o menos constante (módulo algunas diferencias de longitud entre representaciones de cadena de datos numéricos, probablemente unos pocos bytes). Obviamente, eso no es lo que está sucediendo aquí, al menos no la explicación completa.
Sin ingeniería inversa, el jpeg en/decodificador es imposible decirlo con seguridad. En realidad, hay una serie de estándares jpeg y, contrariamente a la creencia popular, no todos pueden modificarse sin volver a codificarlos.
Es posible que el primer guardado sea una reescritura con pérdidas en su versión jpeg favorita y las rotaciones posteriores sean un simple ajuste de metadatos o una operación directamente en la tabla DCT (lo cual es posible para algunos esquemas de codificación).
El aumento en el tamaño del archivo también puede incluir algunos metadatos adicionales, aunque 9k parece mucho, es posible. El aumento también puede explicarse por la adición de una miniatura que puede no haber estado presente en la salida de GIMP. Es posible que podamos obtener más información de los archivos directamente (antes de WPV y después).
En cualquier caso, tratar de trabajar sin pérdidas con jpeg es realmente una tontería, ya que solo es útil con ciertos tamaños de imagen, no todos los decodificadores y codificadores son idénticos y requiere que esos editores trabajen directamente con el contenido jpeg en el que no puede confiar para ser el caso... El hecho de que lo haga ahora no significa que lo seguirá haciendo en el futuro.
Su mejor apuesta es trabajar con un formato sin pérdidas y evitar el dolor por completo.
La rotación de JPEG sin pérdidas solo es posible sin la introducción de artefactos de contorno si las dimensiones de la imagen son múltiplos del tamaño del bloque (normalmente [/siempre?] 8). Consulte la página de manual de jpegtran (lo siento, no tengo un buen enlace canónico para él; si lo encuentra, siéntase libre de editarlo) para obtener detalles sobre lo que implica:
La transformación de transposición no tiene restricciones con respecto a las
dimensiones de la imagen. Las otras transformaciones funcionan de manera bastante extraña si las dimensiones de la imagen no son un múltiplo del tamaño de la iMCU (generalmente 8 o 16 píxeles), porque solo pueden transformar bloques completos de datos de coeficiente DCT de la manera deseada.El comportamiento predeterminado de jpegtran al transformar una imagen de tamaño extraño
está diseñado para preservar la reversibilidad exacta y la
consistencia matemática del conjunto de transformación. Como se indicó, la transposición
puede voltear toda el área de la imagen. La duplicación horizontal deja intacta cualquier columna iMCU parcial en el borde derecho, pero puede voltear todas las filas de la imagen. De manera similar, la duplicación vertical deja intacta cualquier fila parcial de iMCU en el borde inferior, pero puede voltear todas las columnas. Las otras transformaciones se pueden construir como secuencias de operaciones de transposición y volteo; para mantener la coherencia, sus acciones en los píxeles de borde se definen como el mismo resultado final de la correspondiente secuencia de transposición y giro.Para un uso práctico, es posible que prefiera descartar cualquier
píxel de borde no transformable en lugar de tener una tira de aspecto extraño a lo largo de los
bordes derecho y/o inferior de una imagen transformada. Para hacer esto, agregue el interruptor -trim:
Sospecho que Windows Photo Viewer está evitando este problema al realizar una descompresión y una recompresión de alta calidad extrema para simular un comportamiento sin pérdidas cuando las dimensiones de la imagen no son múltiplos de 8, en lugar de realizar una rotación sin pérdidas. Una buena utilidad simplemente haría sin pérdidas, artefactos y todo, o dejaría caer algunos píxeles, en lugar de arruinar la calidad de toda la imagen (y aumentar el tamaño del archivo).
No tengo una respuesta definitiva, pero algunas posibles teorías de por qué sucedió eso. Algunos tipos de archivos funcionan de tal manera que dos códigos diferentes para una imagen de ese tipo de archivo no necesariamente producen imágenes diferentes. Por ejemplo, el tipo de archivo PNG funciona de esa manera porque permite un fondo transparente, pero una imagen con un fondo transparente y otra que es igual excepto que el mismo fondo es blanco aparecen exactamente de la misma manera. Se dice que un archivo de imagen está comprimido si ocupa menos de 3 bytes de memoria por píxel. Creo que, a excepción de los que tienen un fondo transparente, no hay dos archivos PNG que generen exactamente la misma imagen. Cada vez que guarda una imagen como PNG, la convierte en un código que genera la imagen original y, a excepción de imágenes muy inusuales como una en la que cada píxel es un color aleatorio de los 2^24 colores, el código ocupará menos memoria que 3 bytes por píxel, por lo que se dice que guardar como PNG es una compresión sin pérdidas. Por otro lado, para ahorrar memoria, solo ciertas imágenes pueden ser generadas por el código de un archivo de imagen JPEG. Probablemente haya más de un tipo de archivo JPEG y no sé si alguno de ellos tiene la propiedad de que dos imágenes diferentes de ese tipo de archivo puedan generar exactamente la misma imagen. Supongo que un montón de veces simplemente rotaste una imagen y luego la guardaste como JPEG y darás una explicación de lo que sucedió bajo el supuesto de que eso es lo que hiciste, lo cual no sé si es cierto. Una rotación que hizo no tiene pérdidas si hay una manera de recuperar exactamente el mismo código de archivo de imagen que tenía antes de rotarlo y guardarlo. Puede que no estés en lo cierto en cuanto a que realmente hiciste una rotación sin pérdidas. Si realmente no tuviera pérdidas,
Las razones detrás de esto son algunas
la forma en que se codifican y comprimen las imágenes cambiará el tamaño simplemente debido al algoritmo de compresión. puede probar esto guardándolo como un mapa de bits y luego girándolo. En ese formato o en cualquier formato sin procesar, el tamaño debe permanecer igual. Si no es así, el programa que guarda la imagen está agregando nuevos datos, posiblemente algunos metadatos o algo así.
Pero, ¿por qué rotas un jpeg 20 veces?
Por cómo funciona la compresión de imágenes . Cualquier formato como PNG o JPG en general no conserva el tamaño del archivo después de la rotación.
Para el compresor, la imagen rotada es solo una imagen diferente, debido a cómo funciona la heurística de compresión, no hay garantía de que comprima una imagen rotada de la misma manera .
Por supuesto, si la compresión es sin pérdidas, si gira la imagen 4 veces la cuarta vez, la imagen vuelve a ser la misma (girada hasta que se inclina como original): en ese caso, debería volver a tener el mismo tamaño comprimido, si no, entonces es por una de las siguientes razones :
La compresión de imágenes funciona comprimiendo imágenes en trozos de 4x4 u otros tamaños. En general, un compresor ve una imagen rotada como una imagen diferente, sin embargo, dado que un fragmento de píxel comprimido es solo una descomposición lineal, si los fragmentos de la imagen son los mismos, es posible transponer/duplicar las matrices de descomposición lineal de manera efectiva manteniendo lo mismo. calidad:
Tenga en cuenta que esto debe implementarse por función , y eso también explica el aumento inicial de tamaño => en la primera rotación, solo intenta comprimir la imagen en fragmentos que son rotables:
Si tiene éxito, aumenta el tamaño solo una vez, luego cada rotación mantiene la misma calidad.
Esa operación es exitosa solo si la imagen está hecha por partes iguales. (el tamaño de la imagen es múltiplo del tamaño del trozo).
La respuesta de scottbb es incorrecta y puedes hacer una prueba simple:
Verá que la imagen ha cambiado (se vuelve a comprimir en la primera rotación). Sin embargo, ese cambio está limitado en el tiempo, ahora puede girarlo nuevamente sin pérdida de calidad (si la imagen tiene un tamaño que es un múltiplo de 8)
Para responder directamente OP:
Sé que está girando sin pérdidas
No, no está girando sin pérdidas, pierde calidad al menos una vez (en la primera rotación: porque primero debe comprimirse de manera que pueda girar), luego mantiene su calidad.
<?xpacket
etiquetas.<?xpacket
agregada. No tengo una diferencia binaria adecuada aquí, así que no puedo decirlo. Después subí ambos a verexif.com y volvieron idénticos entre sí pero no al original. Pero como dije, los comparo a mano i hexeditor, así que probablemente me perdí mucho. Windows 8.1
james snell
cretina oscilante
cretina oscilante
scottbb
scottbb
Carl Witthoft
CodesInChaos
james snell
0xFF
CoffeDesarrollador
Giacomo Catenazzi
Agente_L
Josué