Solución:
Phil, no sé con qué solución finalmente te decantaste, pero escalar imágenes en Java puede verse bastante bien si:
- Evite los tipos de imágenes con búfer que no son compatibles con el JDK.
- Usar escalamiento incremental
- Apéguese a bicúbico cuando use escala incremental
Hice una buena cantidad de pruebas con estos métodos y la escala incremental junto con el apego a tipos de imágenes bien compatibles es la clave; veo que Alexander mencionó que todavía no tuvo buena suerte con eso, lo cual es un fastidio.
Lancé la biblioteca imgscalr (Apache 2) hace unos 6 meses para abordar el problema de “Quiero copias a escala de buena apariencia de esta imagen, ¡HAZLO AHORA!” después de leer algo así como 10 preguntas como esta en SO.
El uso estándar se ve así:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 640);
El segundo argumento es el ancho y alto delimitadores que usará imgscalr para escalar la imagen, manteniendo sus proporciones correctas incluso si pasó en dimensiones no válidas, hay muchos métodos más detallados, pero ese es el uso más simple.
El caso de uso que le gustaría, por ejemplo, si Facebook limita las imágenes a 800×600 píxeles, se vería así:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 800, 600);
Eso asegurará que la imagen permanezca en el mejor tipo de imagen admitida y escalada con el método de mayor calidad que Java puede reunir.
En mis propias pruebas de alta resolución, no he notado ninguna discrepancia enorme con las imágenes escaladas al usar esta biblioteca / estos métodos EXCEPTO cuando el cargador ImageIO coloca su imagen en un tipo de imagen poco compatible; por ejemplo, esto sucede mucho con los GIF . Si los dejas así y no los sacas de esos tipos mal soportados, terminará luciendo realmente vacilante y terrible.
La razón de esto es que el equipo de Java2D en realidad tiene diferentes pipelines acelerados por hardware para todos los diferentes tipos de BufferedImages que el JDK puede procesar – un subconjunto de esos tipos de imágenes que son menos comunes todos recurren al uso de la misma canalización de renderización de software bajo el cubre en Java2D, lo que resulta en imágenes de aspecto pobre y, a veces, totalmente incorrecto. Este fue un PIA para explicar y tratar de descubrir que acabo de escribir esa lógica directamente en la biblioteca.
Los dos mejores tipos admitidos son BufferedImage.TYPE_INT_RGB y _ARGB si tiene curiosidad.
Lo he probado todo, incluidos los trucos aquí, y todo lo que puedo decir es que es mejor usar ImageMagick con cualquier interfaz. Las bibliotecas de imágenes de Javas simplemente no están a la altura cuando se trata de esto. Necesita admitir tantos formatos y algoritmos para hacerlo bien.
Las dos bibliotecas de código abierto más populares que se especializan en el cambio de tamaño de imágenes en Java actualmente son:
- Thumbnailator
- imgscalr
Además, existe el método JDK con Java Graphics2D
(vea esta pregunta sobre cómo hacerlo) que es notorio por crear malos resultados, especialmente con la reducción de escala. También hay una interfaz Java para ImageMagick que se omitirá aquí porque requiere una herramienta externa.
Calidad visual
Aquí hay una comparación de los resultados de cambiar el tamaño / reducir la escala de un 580x852
png para 145x213
. Como referencia, se utiliza el cambio de tamaño de Photoshop CS5 “guardar para web”. Nota: los resultados son 1: 1 lo que las librerías creadas acaban de copiar juntas. El zoom no utiliza ningún filtrado, solo un simple algoritmo de vecino más cercano. Aquí puedes encontrar la imagen original.
- Thumbnailator 0.4.8 con configuración predeterminada, sin ajustes de dimensión
- Photoshop CS5 con algoritmo bicúbico
- imgscalr 4.2 con configuración ULTRA_QUALITY, sin ajustes de dimensión
- Graphics2D (Java 8) con sugerencias de renderizado VALUE_INTERPOLATION_BICUBIC, VALUE_RENDER_QUALITY, VALUE_ANTIALIAS_ON
Dejo que el lector seleccione el mejor resultado ya que es subjetivo. Generalmente, todos tienen un buen rendimiento excepto Graphics2D
. Thumbnailator genera imágenes más nítidas muy similares a la salida de Photoshop, mientras que la salida de imgscalr es considerablemente más suave. Para iconos / texto, etc., desea una salida más nítida, para imágenes puede querer una salida más suave.
Tiempo computacional
Aquí hay un punto de referencia no científico que utiliza esta herramienta y 114 imágenes con una dimensión de aproximadamente 96x96
hasta 2560x1440
tratándolo como imágenes al 425% creando: 100%, 150%, 200%, 300% y 400% de versiones escaladas (por lo tanto, 114 * 5 operaciones de escalado). Todas las bibliotecas utilizan la misma configuración que en la comparación de calidad (por lo que la calidad más alta posible). Los tiempos solo están escalando, no todo el proceso. Realizado en un i5-2520M con 8 GB de RAM y 5 carreras.
- Thumbnailator: 7003.0ms | 6581.3ms | 6019.1ms | 6375.3ms | 8700,3 ms
- imgscalr: 25218.5ms | 25786.6ms | 25095.7ms | 25790.4ms | 29296.3ms
- Gráficos2D: 7387,6ms | 7177.0ms | 7048.2ms | 7132.3ms | 7510,3 ms
Aquí está el código utilizado en este punto de referencia.
Curiosamente Thumbnailator también es el más rápido con un tiempo promedio de 6,9 segundos seguido por Java2D con 7.2 segundos dejando imgscalr detrás con un pobre 26.2 seg. Probablemente esto no sea justo ya que imgscalr está configurado para ULTRA_QUALITY
que parece ser extremadamente caro; con el QUALITY
estableciendo un promedio de 11,1 seg. más competitivo.