2008-10-28 27 views
112

Necesito cambiar el tamaño de los archivos PNG, JPEG y GIF. ¿Cómo puedo hacer esto usando Java?¿Cómo puedo cambiar el tamaño de una imagen usando Java?

+13

ya que solicitó una biblioteca, la verdadera respuesta está aquí: http://stackoverflow.com/questions/244164/resize-an-image-in-java-any-open-source-library/4528136#4528136. Es mucho más fácil de usar que el código en la respuesta aceptada;) –

+0

No estoy de acuerdo en 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? – Burkhard

Respuesta

81

Después de cargar la imagen que puede probar:

BufferedImage createResizedCopy(Image originalImage, 
      int scaledWidth, int scaledHeight, 
      boolean preserveAlpha) 
    { 
     System.out.println("resizing..."); 
     int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; 
     BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType); 
     Graphics2D g = scaledBI.createGraphics(); 
     if (preserveAlpha) { 
      g.setComposite(AlphaComposite.Src); 
     } 
     g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); 
     g.dispose(); 
     return scaledBI; 
    } 
+9

Encontré que esta técnica crea una imagen que no es lo suficientemente alta para mis necesidades. – morgancodes

+1

también lo hará Image.getScaledInstance (ancho, alto, sugerencias)? – codeplay

+0

es el preserveAlpha comprobar el camino equivocado (para el tipo de imagen)? – Thilo

10

Java Advanced Imaging es ahora de código abierto, y proporciona las operaciones que necesita.

+1

enlace roto ... :( – Asaph

+4

Enlace roto ... a una horrible biblioteca de Dios .... –

+0

Y todavía no hay una versión de 64b JRE ... – Cromax

8

Si se trata de imágenes de gran tamaño o desea un buen resultado, no es una tarea trivial en Java. Simplemente hacerlo a través de una operación de cambio de escala a través de Graphics2D no creará una miniatura de alta calidad. Puedes hacerlo utilizando JAI, pero requiere más trabajo de lo que imaginas para obtener algo que se vea bien y JAI tiene la mala costumbre de explotar nuestra JVM con errores OutOfMemory.

Sugiero usar ImageMagick como un ejecutable externo si puede salirse con la suya. Es fácil de usar y hace bien el trabajo para que no sea necesario.

11

No necesita una biblioteca para hacer esto. Puedes hacerlo con Java.

Chris Campbell tiene una reseña excelente y detallada sobre escalar imágenes - ver this article.

Chet Haase y Romain Guy también tienen una descripción detallada y muy informativa de la escala de la imagen en su libro, Filthy Rich Clients.

+2

+1 para clientes ricos impolutos – Chris

+6

El artículo de Chris es exactamente lo que me motivó para escribir imgscalr en primer lugar, y preguntas como esta (y respuestas como la suya). Mucha gente pregunta una y otra vez cómo obtener miniaturas de una imagen con buen aspecto. Hay varias maneras de hacerlo, El de Chris no es * siempre * la mejor manera, depende de lo que estés tratando de hacer y cuán grande es la reducción. Imgscalr soluciona todo eso y es de 1 clase. –

+2

+1, estoy de acuerdo, los clientes de Filthy Rich es uno de los mejores libros de Java que hay a la par con "Effective Java", pero ImgScalr es lo que uso porque soy flojo. –

4

Si, teniendo imagemagick instalado en su maschine es una opción, recomiendo im4java. Es una capa de abstracción muy delgada sobre la interfaz de línea de comando, pero cumple su función muy bien.

171

FWIW Acabo de lanzar (Apache 2, alojado en GitHub) una biblioteca de escala de imágenes simple para Java llamada imgscalr (disponible en Maven central).

La biblioteca implementa algunos enfoques diferentes para la escala de la imagen (incluido el enfoque incremental de Chris Campbell con algunas mejoras menores) y seleccionará el enfoque más óptimo para usted si se lo solicita o le ofrece el mejor o el más rápido mirando (si lo pide).

El uso es muy simple, solo un montón de métodos estáticos. El más simple de casos de uso es:

BufferedImage scaledImage = Scalr.resize(myImage, 200); 

Todas las operaciones mantienen las proporciones de la imagen original, por lo que en este caso está pidiendo imgscalr cambiar el tamaño de la imagen dentro de unos límites de 200 píxeles de ancho y 200 píxeles de alto y de forma predeterminada, seleccione automáticamente el mejor y más rápido enfoque para eso ya que no fue especificado.

Me doy cuenta desde el principio que esto se parece a la autopromoción (lo es), pero pasé bastante tiempo buscando en Google este mismo tema y seguí buscando diferentes resultados/enfoques/pensamientos/sugerencias y decidí sentarme y escriba una implementación simple que aborde los casos de uso del 80-85% en los que tiene una imagen y probablemente quiera una miniatura para ella, ya sea lo más rápido posible o lo más apuestos posible (para los que lo han intentado, Notarás que al hacer una Graphics.drawImage incluso con la interpolación BICUBIC a una imagen lo suficientemente pequeña, todavía se ve como basura.

+1

Riyad, me gustó usar Scalr. Tengo curiosidad por saber, ¿cómo terminaste eligiendo una API con todos s métodos táticos? Yo había escrito una API similar que estaba más cerca de un constructor. Como 'nuevo ImageScaler (img) .resizeTo (...). Rotate (...). CropTo (...). ToOutputBuffer()'. Me gusta tu camino también y creo que es más simple. –

+4

Amir, el patrón de compilador también funciona maravillosamente para este tipo de bibliotecas, simplemente fui con el método de método estático porque pensé que era un * cabello * más fácil de seguir para los nuevos usuarios y el patrón de uso que esperaba de imgscalr (originalmente solo métodos de cambio de tamaño único) no se benefició de tener un estado de retención de instancia (instancia de generador). Así que guardé en la instanciación del objeto y fui con los métodos estáticos. He adoptado una postura firme contra la creación de objetos dentro de imgscalr en todos los lugares donde puedo evitarlo. Sin embargo, ambos enfoques funcionan bien. –

+4

+1 para poner esto a disposición en el repositorio central de Maven. – Grilse

45

Thumbnailator es una imagen de código abierto cambiar el tamaño de la biblioteca de Java con una interfaz fluida, distribuido bajo la MIT license.

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 desordenado Con Thumbnailator, es posible expresar tareas bastante complicadas usando una simple API fluida.

Un ejemplo sencillo

Para un simple ejemplo, tomar una imagen y cambiar el tamaño a 100 x 100 (la preservación de la relación de aspecto de la imagen original), y guardar en un archivo puede lograrse en un solo declaración:

Thumbnails.of("path/to/image") 
    .size(100, 100) 
    .toFile("path/to/thumbnail"); 

Un ejemplo avanzado

Realizar tareas complejas de cambio de tamaño se simplifica con interfaz fluida de Thumbnailator .

Supongamos que queremos hacer lo siguiente:

  1. tomar las imágenes en un directorio y,
  2. ellos cambiar el tamaño de 100 x 100, con la relación de aspecto de la imagen original,
  3. Guardar todos ellos a JPEG con los ajustes de calidad de 0.85,
  4. donde se toman los nombres de archivo de la original con thumbnail. anexado al comienzo

Traducido al Thumbnailator, nos gustaría poder llevar a cabo lo anterior con lo siguiente:

Thumbnails.of(new File("path/to/directory").listFiles()) 
    .size(100, 100) 
    .outputFormat("JPEG") 
    .outputQuality(0.85) 
    .toFiles(Rename.PREFIX_DOT_THUMBNAIL); 

Una nota acerca de la calidad de imagen y velocidad

Esta biblioteca también utiliza la bilineal progresiva ampliación método destacado en Filthy Rich Clients por Chet Haase y Romain Guy con el fin de generar miniaturas de alta calidad y garantizar un rendimiento de tiempo de ejecución aceptable.

+1

coobird, realmente buen trabajo con la API. Muy sencillo y fácil de usar. –

+0

@Riyad: ¡Gracias! :) – coobird

+0

¡realmente fácil de usar! gracias por esto – LordT

2

Puede intentar usar GraphicsMagick Image Processing System con im4java como una interfaz de línea de comando para Java.

Hay un montón de ventajas de GraphicsMagick, pero uno para todos:

  • GM se utiliza para procesar mil millones de archivos más grandes en la foto sitios del mundo (por ejemplo Flickr y Etsy).
1

Image Magick ha sido mencionado. Hay un proyecto de interfaz JNI llamado JMagick. No es un proyecto particularmente estable (y se ha sabido que Image Magick en sí mismo cambia mucho e incluso rompe la compatibilidad). Dicho esto, hemos tenido una buena experiencia al utilizar JMagick y una versión compatible de Image Magick en un entorno de producción para realizar escalas a un alto rendimiento y baja tasa de latencia. La velocidad fue sustancialmente mejor que con una biblioteca gráfica de Java que probamos anteriormente.

http://www.jmagick.org/index.html

0

he desarrollado una solución con las clases libremente disponibles (AnimatedGifEncoder, GifDecoder, y LWZEncoder) disponibles para el manejo de animación GIF.
Puede descargar el jar jgifcode y ejecutar la clase GifImageUtil. Enlace: http://www.jgifcode.com

+1

Por favor, mencione en la respuesta si está afiliado con el producto que recomienda. –

+0

waw ... ¿es eso para cambiar el tamaño de la imagen animada GIF? y es gratis? Wwaww ... debería probarlo ahora ... – gumuruh

+0

Sí, esto es desarrollado por mí. Aquí está el código fuente para él https://github.com/rt29/jgifcode - Esto ahora está aquí. No lo apoyo más. –

2

El API Java no proporciona una norma función de escalado para imágenes y degradación de la calidad de imagen.

Debido a esto traté de usar cvResize de JavaCV pero parece causar problemas.

Encontré una buena biblioteca para el escalado de imágenes: simplemente agregue la dependencia de "java-image-scaling" en su pom.xml.

<dependency> 
    <groupId>com.mortennobel</groupId> 
    <artifactId>java-image-scaling</artifactId> 
    <version>0.8.6</version> 
</dependency> 

En el repositorio de maven obtendrá la versión más reciente para esto.

Ej. En el programa Java

ResampleOp resamOp = new ResampleOp(50, 40); 
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null); 
+0

También está disponible en GitHub (https://github.com/mortennobel/java-image-scaling.git) y tiene la versión 8.7 por el momento. Necesitaba la corrección de li en pom.xml, tú (cambiando la fuente y el objetivo a por lo menos 1.6 como el Maven más nuevo ya no es compatible con 1.5). – Cromax

0

permite utilizar las siguientes producto popular: thumbnailator

+0

Gracias por mencionar Thumbnailator. Sin embargo, ** Thumbnailator NO es un producto de Google **, solo se aloja con el servicio de alojamiento de Google Project para proyectos de código abierto. (Soy el mantenedor de Thumbnailator.) – coobird

+0

@coobird thx. Corregí la respuesta – gstackoverflow

0

Si no desea importar imgScalr como @Riyad Kalla respuesta anterior, que he probado también funciona bien, puede hacer esto tomado de Peter Walser answer @Peter Walser en otro tema sin embargo:

/** 
    * 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. 
    */ 
    public Icon getIcon(String name) { 
     Icon icon = null; 
     URL url = null; 
     ImageIcon imgicon = null; 
     BufferedImage scaledImage = null; 
     try { 
      url = getClass().getResource(name); 

      icon = new ImageIcon(url); 
      if (icon == null) { 
       System.out.println("Couldn't find " + url); 
      } 

      BufferedImage bi = new BufferedImage(
        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 = new ImageIcon(scaledImage); 

     } catch (Exception e) { 
      System.out.println("Couldn't find " + getClass().getName() + "/" + name); 
      e.printStackTrace(); 
     } 
     return imgicon; 
    } 

public static BufferedImage 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 2 
      int 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 = new BufferedImage(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 = new BufferedImage(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; 
     } 
    } 
0

utilice simplemente la respuesta de Burkhard además de añadir esta línea después de crear los gráficos:

g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 

También podría establecer el valor en BICUBIC, producirá una imagen de mejor calidad pero es una operación más costosa. Hay otras sugerencias de renderización que puede establecer pero he encontrado que la interpolación produce el efecto más notable. Tenga en cuenta que si quiere acercarse mucho, es probable que el código Java sea 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 pistas de renderización configuradas para optimizar la velocidad sobre la calidad.

1

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)' haría el trabajo también, pero hay un desagradable error con esto - consulte mi enlace para más detalles.

Cuestiones relacionadas