2009-07-01 37 views
35

¿Puede alguien ayudarme con algún código para crear una miniatura para un JPEG en Java.¿Cómo se crea una imagen en miniatura de un JPEG en Java?

soy nuevo en esto, por lo que una explicación paso a paso sería apreciada.

+3

http://www.google.com/search?hl=es&q=java+thumbnail+jpg –

+1

Utilice una biblioteca como ImageMagick - muchos ejemplos en la web – mfloryan

+0

Vaya, gracias por corregir mis errores tipográficos. Prolly no debería introducir más errores tipográficos después de la edición ... – jjnguy

Respuesta

59
Image img = ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, BufferedImage.SCALE_SMOOTH); 

Esto creará una miniatura de 100x100 píxeles como un objeto de imagen. Si desea escribir de nuevo al disco simplemente convertir el código para esto:

BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); 
img.createGraphics().drawImage(ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, Image.SCALE_SMOOTH),0,0,null); 
ImageIO.write(img, "jpg", new File("test_thumb.jpg")); 

Además, si usted está preocupado por los problemas de velocidad (el método descrito anteriormente es bastante lento si se quiere escalar muchas imágenes) utilizar estos métodos y la siguiente declaración:

private BufferedImage scale(BufferedImage source,double ratio) { 
    int w = (int) (source.getWidth() * ratio); 
    int h = (int) (source.getHeight() * ratio); 
    BufferedImage bi = getCompatibleImage(w, h); 
    Graphics2D g2d = bi.createGraphics(); 
    double xScale = (double) w/source.getWidth(); 
    double yScale = (double) h/source.getHeight(); 
    AffineTransform at = AffineTransform.getScaleInstance(xScale,yScale); 
    g2d.drawRenderedImage(source, at); 
    g2d.dispose(); 
    return bi; 
} 

private BufferedImage getCompatibleImage(int w, int h) { 
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
    GraphicsDevice gd = ge.getDefaultScreenDevice(); 
    GraphicsConfiguration gc = gd.getDefaultConfiguration(); 
    BufferedImage image = gc.createCompatibleImage(w, h); 
    return image; 
} 

y luego llamar:

BufferedImage scaled = scale(img,0.5); 

donde 0,5 es la relación de escala y img es un BufferedImage que contiene la imagen de tamaño normal.

+0

gracias ayudó. Preciso y correcto. – Ayusman

+0

¿Cambiaría este código con el paquete java.nio? (escribiendo nuevamente en el disco) – jacktrades

+1

@jacktrades no, no lo haría. Puede usar el método 'ImageIO.write()' para volver a escribirlo en el disco. Lo sé, el comentario es muy antiguo, pero para aquellos que están teniendo la misma pregunta que Jack. – kevto

4

La biblioteca JMagick (y la implementación de ImageMagick en Java) tendrá lo que necesita.

+0

+1 y ofrece resultados de salida mucho mejores –

+1

Esta es solo una interfaz nativa de ImageMagick. Problema 1 .: Dependencia externa Problem2: llamando a funciones nativas desde Java. Esto hace que JMagick sea subóptimo. – gyorgyabraham

3

el código Java anterior (con los métodos scale/getCompatibleImage) funcionó muy bien para mí, pero cuando implementé en un servidor, dejó de funcionar, porque el servidor no tenía pantalla asociada; cualquier otra persona con este problema puede arréglalo usando: BufferedImage bi = new BufferedImage (w, h, BufferedImage.TYPE_INT_RGB);

en lugar de BufferedImage bi = getCompatibleImage (w, h);

y borrar el método getCompatibleImage

(nota posterior - resulta que esto funciona muy bien para la mayoría de las imágenes, pero tengo un montón de mi departamento de marketing Companys que son imágenes JPEG profundidad de color de 32 bits, y la biblioteca arroja una excepción de formato de imagen no admitida para todos aquellos :(- imagemagick/jmagick están empezando a verse más atractivos)

30

Como podría haber descubierto "fácil" y "buen aspecto resultado" son dos cosas muy diferentes. han encapsulado estos dos requisitos en una muy simple (licencia Apache 2) java image scaling library que simplemente hace todo bien para usted.

Código de ejemplo para crear una imagen en miniatura se ve así:

BufferedImage img = ImageIO.read(...); // load image 
BufferedImage scaledImg = Scalr.resize(img, 150); 

Sus proporciones de la imagen son honrados, la biblioteca hace un mejor conjetura en el método que debe utilizar en función de la cantidad de cambio en la imagen debido a escalado (MÁS RÁPIDO, EQUILIBRADO o CALIDAD) y los mejores tipos de imágenes compatibles con Java2D siempre se utilizan para escalar para evitar el problema de resultados "negros" o resultados realmente terribles (p. ej. imágenes GIF demasiado difuminadas).

Además, si desea forzar a la salida la mejor miniatura mirando posible en Java, la llamada a la API se vería así:

BufferedImage img = ImageIO.read(...); // load image 
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
             150, 100, Scalr.OP_ANTIALIAS); 

No sólo va a utilizar la biblioteca de la Java2D recomendada escala incremental para el usuario para darle el mejor resultado, también aplicará un efecto antialiasing opcional a la miniatura (ConvolveOp con un kernel muy afinado) para suavizar ligeramente las transiciones entre los valores de píxel para que la miniatura se vea más uniforme y no nítidas o amapolas como podría haber visto al pasar de imágenes muy grandes a pequeñas.

Puede leer todos los comentarios en la biblioteca (el código en sí está muy codificado) para ver los diferentes errores de JDK que se trabajan o las optimizaciones que se realizan para mejorar el rendimiento o el uso de la memoria. Pasé MUCHO tiempo ajustando esta implementación y he tenido muchos buenos comentarios de personas que lo implementan en aplicaciones web y otros proyectos de Java.

+0

Esto se ve muy bien, ¡muchas gracias! –

+0

Gracias esta lib es realmente increíble. Ninguno de los métodos mencionados anteriormente funcionó en mi imagen de prueba, pero funcionó como un amuleto. Me encantan las diversas opciones de cambio de tamaño que has dado. –

+0

@cracked_all gracias por las amables palabras; ¡Me alegra saber que te hizo la vida más fácil! –

12

Esta es una manera simple de crear una miniatura de 100 X 100 sin ningún estiramiento o sesgo en la imagen.

private void saveScaledImage(String filePath,String outputFile){ 
    try { 

     BufferedImage sourceImage = ImageIO.read(new File(filePath)); 
     int width = sourceImage.getWidth(); 
     int height = sourceImage.getHeight(); 

     if(width>height){ 
      float extraSize= height-100; 
      float percentHight = (extraSize/height)*100; 
      float percentWidth = width - ((width/100)*percentHight); 
      BufferedImage img = new BufferedImage((int)percentWidth, 100, BufferedImage.TYPE_INT_RGB); 
      Image scaledImage = sourceImage.getScaledInstance((int)percentWidth, 100, Image.SCALE_SMOOTH); 
      img.createGraphics().drawImage(scaledImage, 0, 0, null); 
      BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB); 
      img2 = img.getSubimage((int)((percentWidth-100)/2), 0, 100, 100); 

      ImageIO.write(img2, "jpg", new File(outputFile));  
     }else{ 
      float extraSize= width-100; 
      float percentWidth = (extraSize/width)*100; 
      float percentHight = height - ((height/100)*percentWidth); 
      BufferedImage img = new BufferedImage(100, (int)percentHight, BufferedImage.TYPE_INT_RGB); 
      Image scaledImage = sourceImage.getScaledInstance(100,(int)percentHight, Image.SCALE_SMOOTH); 
      img.createGraphics().drawImage(scaledImage, 0, 0, null); 
      BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB); 
      img2 = img.getSubimage(0, (int)((percentHight-100)/2), 100, 100); 

      ImageIO.write(img2, "jpg", new File(outputFile)); 
     } 

    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 
+0

muchas gracias hermano ... eso ha resuelto mi problema. De nuevo, gracias :-) – Farhan

+0

Funciona muy bien – webcoder

+0

BufferedImage img2 = new BufferedImage (100, 100, BufferedImage.TYPE_INT_RGB); img2 = img.getSubimage ((int) ((percentWidth-100)/2), 0, 100, 100); más correcto es BufferedImage img2 = img.getSubimage ((int) ((percentWidth-100)/2), 0, 100, 100); – Oleg

1

He pasado por un blog de acuerdo a los que haya siguientes opciones -

  1. Para los archivos RGB uso simple ImageScalr. La clase ImageIO se usa para leer archivos e ImageScalr para crear miniaturas
  2. Para admitir RGB + CYMK, use la API ImageIO y JAI (Java Advanced Imaging) para leer archivos e ImageScalr para crear miniaturas.
  3. En caso de que no sepa qué formatos de archivo, modo de color va a tratar, la opción más segura es usar ImageMagick.

Aquí está link que da una respuesta completa con fragmentos de código.

1

Hay muchos marcos de procesamiento de imágenes disponibles que puede hacer esto con sólo unas pocas líneas. El siguiente ejemplo genera las miniaturas en diferentes resoluciones (dado el ancho como referencia) usando Marvin Framework. Las tres miniaturas se generaron en 92 ms.

entrada:

enter image description here

salida:

enter image description here

enter image description here

enter image description here

import static marvin.MarvinPluginCollection.*; 

MarvinImage image = MarvinImageIO.loadImage("./res/input.jpg"); 
MarvinImage scaledImage = new MarvinImage(1,1); 

scale(image, scaledImage, 250); 
MarvinImageIO.saveImage(scaledImage, "./res/output_x250.jpg"); 

scale(image, scaledImage, 150); 
MarvinImageIO.saveImage(scaledImage, "./res/output_x150.jpg"); 

scale(image, scaledImage, 50); 
MarvinImageIO.saveImage(scaledImage, "./res/output_x50.jpg"); 
1

Forma simple de crear una miniatura sin estirar o una biblioteca. Funciona con transparencia en pngs, también.

public File createThumbnail(String imageUrl, String targetPath) { 
    final int imageSize = 100; 
    File thumbnail = new File(targetPath); 

    try { 
     thumbnail.getParentFile().mkdirs(); 
     thumbnail.createNewFile(); 
     BufferedImage sourceImage = ImageIO.read(new File(imageUrl)); 
     float width = sourceImage.getWidth(); 
     float height = sourceImage.getHeight(); 

     BufferedImage img2; 
     if (width > height) { 
      float scaledWidth = (width/height) * (float) imageSize; 
      float scaledHeight = imageSize; 

      BufferedImage img = new BufferedImage((int) scaledWidth, (int) scaledHeight, sourceImage.getType()); 
      Image scaledImage = sourceImage.getScaledInstance((int) scaledWidth, (int) scaledHeight, Image.SCALE_SMOOTH); 
      img.createGraphics().drawImage(scaledImage, 0, 0, null); 

      int offset = (int) ((scaledWidth - scaledHeight)/2f); 
      img2 = img.getSubimage(offset, 0, imageSize, imageSize); 
     } 
     else if (width < height) { 
      float scaledWidth = imageSize; 
      float scaledHeight = (height/width) * (float) imageSize; 

      BufferedImage img = new BufferedImage((int) scaledWidth, (int) scaledHeight, sourceImage.getType()); 
      Image scaledImage = sourceImage.getScaledInstance((int) scaledWidth, (int) scaledHeight, Image.SCALE_SMOOTH); 
      img.createGraphics().drawImage(scaledImage, 0, 0, null); 

      int offset = (int) ((scaledHeight - scaledWidth)/2f); 
      img2 = img.getSubimage(0, offset, imageSize, imageSize); 
     } 
     else { 
      img2 = new BufferedImage(imageSize, imageSize, sourceImage.getType()); 
      Image scaledImage = sourceImage.getScaledInstance(imageSize, imageSize, Image.SCALE_SMOOTH); 
      img2.createGraphics().drawImage(scaledImage, 0, 0, null); 
     } 
     ImageIO.write(img2, "png", thumbnail); 
    } 
    catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    return thumbnail; 
} 
1

He escrito la clase util con métodos estáticos hace años usando JAI. Java Advanced Imaging API es la API más confiable en Java para manejar imágenes. La interpolación de vectores es lo más parecido a Photoshop en el mundo de Java. Aquí está uno de ellos:

public static ByteArrayOutputStream resize(InputStream inputStream , int IMG_WIDTH, 
     int IMG_HEIGHT) throws Exception { 
    BufferedImage originalImage = ImageIO.read(inputStream); 
    int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB 
      : originalImage.getType(); 
    BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, 
      type); 
    { 
     Graphics2D g = resizedImage.createGraphics(); 
     g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null); 
     g.dispose(); 
     g.setComposite(AlphaComposite.Src); 

     g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
       RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
     g.setRenderingHint(RenderingHints.KEY_RENDERING, 
       RenderingHints.VALUE_RENDER_QUALITY); 
     g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
       RenderingHints.VALUE_ANTIALIAS_ON); 
    } 
    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    ImageIO.write(resizedImage, "png", bos); 
    return bos; 

} 
1

Sé que esta es una publicación bastante antigua. He estado buscando una solución para generar la miniatura de modo terminar con esta

Thumbnails.of(originalImage).scale(0.25).asBufferedImage(); 

si está utilizando para móviles sugeriría para establecer la escala de 0,45

Thumbnails.of(originalImage).scale(0.45).asBufferedImage(); 

https://github.com/coobird/thumbnailator

Este es ciertamente mucho más rápido usando Graphics2D ya que he probado las dos opciones.

Cuestiones relacionadas