Como solicitó una biblioteca, la respuesta real está aquí: stackoverflow.com/questions/244164/… . Es mucho más fácil de usar que el código en la respuesta aceptada;)
Artur Gajowy
No estoy de acuerdo con la parte de la biblioteca: Graphics2D es parte de la biblioteca awt y es de código abierto. Para la última parte (código abierto) no estoy 100% seguro, pero ¿quién miraría el código awt de todos modos?
Encontré que esta técnica crea una imagen que no tiene la calidad suficiente para mis necesidades.
morgancodes
1
¿Image.getScaledInstance (ancho, alto, sugerencias) también lo hará?
codeplay
1
¿Es el check de preserveAlpha al revés (para imageType)?
Thilo
Estoy de acuerdo con @morgancodes. La calidad de imagen es mucho peor que la que se obtiene, por ejemplo, con OS X Preview al cambiar el tamaño a las mismas dimensiones. Probaré algunas bibliotecas de código abierto para ver si les va mejor.
Thilo el
1
"Probaré algunas bibliotecas de código abierto para ver si les va mejor". +1 para imgscalr de la respuesta de @ RiyadKalla.
Thilo
182
FWIW Acabo de lanzar (Apache 2, alojado en GitHub) una biblioteca simple de escalado de imágenes para Java llamada imgscalr (disponible en Maven central ).
La biblioteca implementa algunos enfoques diferentes para el escalado de imágenes (incluido el enfoque incremental de Chris Campbell con algunas mejoras menores) y elegirá el enfoque más óptimo para usted si así lo solicita, o le dará el aspecto más rápido o mejor (si usted pide eso).
El uso es muy simple, solo un montón de métodos estáticos. El caso de uso más simple es:
Todas las operaciones mantienen las proporciones originales de la imagen, por lo que en este caso le está pidiendo a imgscalr que cambie el tamaño de su imagen dentro de los límites de 200 píxeles de ancho y 200 píxeles de alto y, de forma predeterminada, seleccionará automáticamente el enfoque más atractivo y más rápido para eso, ya que no era No especificado.
Al principio me doy cuenta de que esto parece autopromoción (lo es), pero pasé mi parte de tiempo buscando en Google exactamente el mismo tema y seguí sacando diferentes resultados / enfoques / pensamientos / sugerencias y decidí sentarme y escribir un Implementación simple que abordaría esos 80-85% de casos de uso en los que tiene una imagen y probablemente desee una miniatura para ella, ya sea lo más rápido posible o lo más atractivo posible (para aquellos que lo han intentado, notará haciendo una Graphics.drawImage incluso con interpolación BICUBIC a una imagen lo suficientemente pequeña, todavía parece basura).
Riad, me gustó usar Scalr. Tengo curiosidad por saber, ¿cómo terminaste eligiendo una API con todos los métodos estáticos? Había escrito una API similar que estaba más cerca de un constructor. Al igual new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer(). También me gusta tu forma y creo que es más simple.
Amir Raminfar
44
Amir, el Builder funciona de maravilla para estos tipos de bibliotecas, así, me acaba de pasar para ir con el enfoque de métodos estáticos porque pensé que era un pelo más fácil de seguir para los nuevos usuarios y el uso de patrones que esperaba de imgscalr (originalmente solo métodos de cambio de tamaño individuales) no se beneficiaron de tener un estado de retención de instancia (la instancia del generador). Así que guardé en la instanciación de objetos y seguí con los métodos estáticos. He tomado una postura firme contra la creación de objetos dentro de imgscalr en todos los lugares donde puedo evitarlo. Sin embargo, ambos enfoques funcionan muy bien.
Riyad Kalla
55
¡+1 por hacer que esté disponible en el repositorio central de Maven!
Grilse
¿Qué es esta clase BufferedImage? ¿Por qué Android Studio no la encuentra? @Riyad Kalla
Milad
3
@ xe4me BufferedImage es una clase en J2SE JDK (parte del marco Java2D) utilizada para representar datos de píxeles sin comprimir sin procesar. No está disponible en Android, Android proporciona sus propias clases para trabajar con datos de imágenes.
Riyad Kalla
54
Thumbnailator es una biblioteca de redimensionamiento de imágenes de código abierto para Java con una interfaz fluida, distribuida bajo la licencia MIT.
Escribí esta biblioteca porque hacer miniaturas de alta calidad en Java puede ser sorprendentemente difícil, y el código resultante podría ser bastante complicado. Con Thumbnailator, es posible expresar tareas bastante complicadas utilizando una API fluida simple.
Un simple ejemplo
Para un ejemplo simple, tomar una imagen y cambiar su tamaño a 100 x 100 (preservando la relación de aspecto de la imagen original), y guardarla en un archivo se puede lograr en una sola declaración:
Una nota sobre la calidad y la velocidad de la imagen.
Esta biblioteca también utiliza el método de escala progresiva bilineal resaltado en Filthy Rich Clients por Chet Haase y Romain Guy para generar miniaturas de alta calidad y garantizar un rendimiento de tiempo de ejecución aceptable.
El artículo de Chris es exactamente lo que me motivó a escribir imgscalr en primer lugar; y preguntas como esta (y respuestas como la tuya). Mucha gente pregunta una y otra vez cómo obtener una buena imagen en miniatura de una imagen. Hay varias formas de hacerlo, Chris no siempre es la mejor manera, depende de lo que intentes hacer y de cuán grande sea la reducción. imgscalr aborda todo eso y es 1 clase.
Riyad Kalla
2
+1, estoy de acuerdo, los clientes Filthy Rich son uno de los mejores libros de Java a la par con "Java efectivo", pero ImgScalr es lo que uso porque soy flojo.
Shawn Vader
10
Java Advanced Imaging ahora es de código abierto y proporciona las operaciones que necesita.
Si se trata de imágenes grandes o quiere un resultado atractivo, no es una tarea trivial en Java. Simplemente hacerlo a través de una operación de reescalado a través de Graphics2D no creará una miniatura de alta calidad. Puede hacerlo usando JAI, pero requiere más trabajo del que imagina para obtener algo que se vea bien y JAI tiene la desagradable costumbre de volar nuestra JVM con errores de OutOfMemory.
Sugiero usar ImageMagick como un ejecutable externo si puede salirse con la suya. Es simple de usar y hace el trabajo correctamente para que no tenga que hacerlo.
Si tener una imagen instalada en su máquina es una opción, le recomiendo im4java . Es una capa de abstracción muy delgada sobre la interfaz de línea de comando, pero hace su trabajo muy bien.
También está disponible en GitHub ( github.com/mortennobel/java-image-scaling.git ) y tiene la versión 8.7 por ahora. Necesitaba una pequeña solución en pom.xml, tú (cambiar la fuente y el destino a al menos 1.6 ya que Maven más nuevo ya no admite 1.5).
Image Magick ha sido mencionado. Hay un proyecto front-end JNI llamado JMagick. No es un proyecto particularmente estable (y se sabe que Image Magick en sí misma cambia mucho e incluso rompe la compatibilidad). Dicho esto, hemos tenido una buena experiencia usando JMagick y una versión compatible de Image Magick en un entorno de producción para realizar escalado a un alto rendimiento y baja tasa de latencia. La velocidad fue sustancialmente mejor que con una biblioteca de gráficos de Java que probamos anteriormente.
También puede establecer el valor en BICUBIC, producirá una imagen de mejor calidad pero es una operación más costosa. Hay otras sugerencias de representación que puede establecer, pero he descubierto que la interpolación produce el efecto más notable. Tenga en cuenta que si desea acercarse mucho, el código Java probablemente será muy lento. Encuentro que las imágenes más grandes comienzan a producir un retraso de alrededor del 300% de zoom, incluso con todas las sugerencias de representación configuradas para optimizar la velocidad sobre la calidad.
Resulta que escribir un escalador de rendimiento no es trivial. Lo hice una vez para un proyecto de código abierto: ImageScaler .
En principio, 'java.awt.Image # getScaledInstance (int, int, int)' también haría el trabajo, pero hay un error desagradable con esto: consulte mi enlace para obtener más información.
He desarrollado una solución con las clases disponibles gratuitamente (AnimatedGifEncoder, GifDecoder y LWZEncoder) disponibles para manejar la animación GIF.
Puede descargar el jgifcode jar y ejecutar la clase GifImageUtil. Enlace: http://www.jgifcode.com
Si no desea importar imgScalr como @Riyad Kalla, la respuesta anterior que probé también funciona bien, puede hacer esto tomado de Peter Walser, responda @Peter Walser en otro tema:
/**
* utility method to get an icon from the resources of this class
* @param name the name of the icon
* @return the icon, or null if the icon wasn't found.
*/publicIcon getIcon(String name){Icon icon =null;
URL url =null;ImageIcon imgicon =null;BufferedImage scaledImage =null;try{
url = getClass().getResource(name);
icon =newImageIcon(url);if(icon ==null){System.out.println("Couldn't find "+ url);}BufferedImage bi =newBufferedImage(
icon.getIconWidth(),
icon.getIconHeight(),BufferedImage.TYPE_INT_RGB);Graphics g = bi.createGraphics();// paint the Icon to the BufferedImage.
icon.paintIcon(null, g,0,0);
g.dispose();
bi = resizeImage(bi,30,30);
scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
imgicon =newImageIcon(scaledImage);}catch(Exception e){System.out.println("Couldn't find "+ getClass().getName()+"/"+ name);
e.printStackTrace();}return imgicon;}publicstaticBufferedImage resizeImage (BufferedImage image,int areaWidth,int areaHeight){float scaleX =(float) areaWidth / image.getWidth();float scaleY =(float) areaHeight / image.getHeight();float scale =Math.min(scaleX, scaleY);int w =Math.round(image.getWidth()* scale);int h =Math.round(image.getHeight()* scale);int type = image.getTransparency()==Transparency.OPAQUE ?BufferedImage.TYPE_INT_RGB :BufferedImage.TYPE_INT_ARGB;boolean scaleDown = scale <1;if(scaleDown){// multi-pass bilinear div 2int currentW = image.getWidth();int currentH = image.getHeight();BufferedImage resized = image;while(currentW > w || currentH > h){
currentW =Math.max(w, currentW /2);
currentH =Math.max(h, currentH /2);BufferedImage temp =newBufferedImage(currentW, currentH, type);Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(resized,0,0, currentW, currentH,null);
g2.dispose();
resized = temp;}return resized;}else{Object hint = scale >2?RenderingHints.VALUE_INTERPOLATION_BICUBIC :RenderingHints.VALUE_INTERPOLATION_BILINEAR;BufferedImage resized =newBufferedImage(w, h,BufferedImage.TYPE_INT_ARGB);Graphics2D g2 = resized.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(image,0,0, w, h,null);
g2.dispose();return resized;}}
Respuestas:
Después de cargar la imagen puedes probar:
fuente
FWIW Acabo de lanzar (Apache 2, alojado en GitHub) una biblioteca simple de escalado de imágenes para Java llamada imgscalr (disponible en Maven central ).
La biblioteca implementa algunos enfoques diferentes para el escalado de imágenes (incluido el enfoque incremental de Chris Campbell con algunas mejoras menores) y elegirá el enfoque más óptimo para usted si así lo solicita, o le dará el aspecto más rápido o mejor (si usted pide eso).
El uso es muy simple, solo un montón de métodos estáticos. El caso de uso más simple es:
Todas las operaciones mantienen las proporciones originales de la imagen, por lo que en este caso le está pidiendo a imgscalr que cambie el tamaño de su imagen dentro de los límites de 200 píxeles de ancho y 200 píxeles de alto y, de forma predeterminada, seleccionará automáticamente el enfoque más atractivo y más rápido para eso, ya que no era No especificado.
Al principio me doy cuenta de que esto parece autopromoción (lo es), pero pasé mi parte de tiempo buscando en Google exactamente el mismo tema y seguí sacando diferentes resultados / enfoques / pensamientos / sugerencias y decidí sentarme y escribir un Implementación simple que abordaría esos 80-85% de casos de uso en los que tiene una imagen y probablemente desee una miniatura para ella, ya sea lo más rápido posible o lo más atractivo posible (para aquellos que lo han intentado, notará haciendo una Graphics.drawImage incluso con interpolación BICUBIC a una imagen lo suficientemente pequeña, todavía parece basura).
fuente
new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer()
. También me gusta tu forma y creo que es más simple.Thumbnailator es una biblioteca de redimensionamiento de imágenes de código abierto para Java con una interfaz fluida, distribuida bajo la licencia MIT.
Escribí esta biblioteca porque hacer miniaturas de alta calidad en Java puede ser sorprendentemente difícil, y el código resultante podría ser bastante complicado. Con Thumbnailator, es posible expresar tareas bastante complicadas utilizando una API fluida simple.
Un simple ejemplo
Para un ejemplo simple, tomar una imagen y cambiar su tamaño a 100 x 100 (preservando la relación de aspecto de la imagen original), y guardarla en un archivo se puede lograr en una sola declaración:
Un ejemplo avanzado
La realización de tareas complejas de cambio de tamaño se simplifica con la interfaz fluida de Thumbnailator.
Supongamos que queremos hacer lo siguiente:
0.85
,thumbnail.
adjuntos al principioTraducido al Thumbnailator, podríamos realizar lo anterior con lo siguiente:
Una nota sobre la calidad y la velocidad de la imagen.
Esta biblioteca también utiliza el método de escala progresiva bilineal resaltado en Filthy Rich Clients por Chet Haase y Romain Guy para generar miniaturas de alta calidad y garantizar un rendimiento de tiempo de ejecución aceptable.
fuente
No necesitas una biblioteca para hacer esto. Puedes hacerlo con el propio Java.
Chris Campbell tiene una excelente y detallada reseña sobre escalar imágenes: vea este artículo .
Chet Haase y Romain Guy también tienen una reseña detallada y muy informativa sobre el escalado de imágenes en su libro, Filthy Rich Clients .
fuente
Java Advanced Imaging ahora es de código abierto y proporciona las operaciones que necesita.
fuente
Si se trata de imágenes grandes o quiere un resultado atractivo, no es una tarea trivial en Java. Simplemente hacerlo a través de una operación de reescalado a través de Graphics2D no creará una miniatura de alta calidad. Puede hacerlo usando JAI, pero requiere más trabajo del que imagina para obtener algo que se vea bien y JAI tiene la desagradable costumbre de volar nuestra JVM con errores de OutOfMemory.
Sugiero usar ImageMagick como un ejecutable externo si puede salirse con la suya. Es simple de usar y hace el trabajo correctamente para que no tenga que hacerlo.
fuente
Si tener una imagen instalada en su máquina es una opción, le recomiendo im4java . Es una capa de abstracción muy delgada sobre la interfaz de línea de comando, pero hace su trabajo muy bien.
fuente
La API de Java no proporciona una función de escala estándar para imágenes y degrada la calidad de la imagen.
Debido a esto, traté de usar cvResize de JavaCV pero parece causar problemas.
Encontré una buena biblioteca para escalar imágenes: simplemente agregue la dependencia para "java-image-scaling" en su pom.xml.
En el repositorio de Maven obtendrá la versión más reciente para esto.
Ex. En su programa java
fuente
Puede intentar utilizar el sistema de procesamiento de imágenes GraphicsMagick con im4java como interfaz de línea de comando para Java.
GraphicsMagick ofrece muchas ventajas, pero una para todos:
fuente
Image Magick ha sido mencionado. Hay un proyecto front-end JNI llamado JMagick. No es un proyecto particularmente estable (y se sabe que Image Magick en sí misma cambia mucho e incluso rompe la compatibilidad). Dicho esto, hemos tenido una buena experiencia usando JMagick y una versión compatible de Image Magick en un entorno de producción para realizar escalado a un alto rendimiento y baja tasa de latencia. La velocidad fue sustancialmente mejor que con una biblioteca de gráficos de Java que probamos anteriormente.
http://www.jmagick.org/index.html
fuente
Simplemente use la respuesta de Burkhard pero agregue esta línea después de crear los gráficos:
También puede establecer el valor en BICUBIC, producirá una imagen de mejor calidad pero es una operación más costosa. Hay otras sugerencias de representación que puede establecer, pero he descubierto que la interpolación produce el efecto más notable. Tenga en cuenta que si desea acercarse mucho, el código Java probablemente será muy lento. Encuentro que las imágenes más grandes comienzan a producir un retraso de alrededor del 300% de zoom, incluso con todas las sugerencias de representación configuradas para optimizar la velocidad sobre la calidad.
fuente
Puede usar Marvin (marco de procesamiento de imágenes Java puro) para este tipo de operación: http://marvinproject.sourceforge.net
Complemento de escala: http://marvinproject.sourceforge.net/en/plugins/scale.html
fuente
Resulta que escribir un escalador de rendimiento no es trivial. Lo hice una vez para un proyecto de código abierto: ImageScaler .
En principio, 'java.awt.Image # getScaledInstance (int, int, int)' también haría el trabajo, pero hay un error desagradable con esto: consulte mi enlace para obtener más información.
fuente
He desarrollado una solución con las clases disponibles gratuitamente (AnimatedGifEncoder, GifDecoder y LWZEncoder) disponibles para manejar la animación GIF.
Puede descargar el jgifcode jar y ejecutar la clase GifImageUtil. Enlace: http://www.jgifcode.com
fuente
puedes usar el siguiente producto popular: thumbnailator
fuente
Si no desea importar imgScalr como @Riyad Kalla, la respuesta anterior que probé también funciona bien, puede hacer esto tomado de Peter Walser, responda @Peter Walser en otro tema:
fuente
Pruebe este siguiente método:
fuente