2012-02-22 22 views
5

estoy usando Graphics2D en java para cambiar el tamaño de las imágenes, funciona perfectamente con jpg, png y otros formatos. mi problema son las imágenes animadas GIF, después de cambiar el tamaño de la animación se ha ido!cambio de tamaño de GIF animado manteniendo su animación usando java

aquí está el método estoy usando:

private BufferedImage doResize(int newWidth, int newHeight, double scaleX, 
     double scaleY, BufferedImage source) { 

    GraphicsConfiguration gc = getDefaultConfiguration(); 
    BufferedImage result = gc.createCompatibleImage(newWidth, newHeight, source.getColorModel().getTransparency()); 
    Graphics2D g2d = null; 

    try { 
     g2d = result.createGraphics(); 
     g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); 
     g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
     g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
     g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2d.scale(scaleX, scaleY); 
     g2d.drawImage(source, 0, 0, null); 
    } finally { 
     if (g2d != null) { 
      g2d.dispose(); 
     } 
    } 

    return result; 
} 

así, ninguna pista de cómo puedo guardar en el gif animado después de la re-dimensionamiento? Gracias.

Respuesta

4

Encontré dos fuentes que cuando se combinan se pueden usar para cambiar el tamaño de la imagen mientras se mantiene la animación.

En esta pregunta ( Convert each animated GIF frame to a separate BufferedImage) busque la respuesta de Alex Orzechowski. Su código toma un archivo gif y lo convierte en una matriz de ImageFrames (que es una clase que creó y que envuelve una Imagen Buffered). Luego mire este código que convierte una secuencia de imágenes almacenadas en un archivo gif (http://elliot.kroo.net/software/java/GifSequenceWriter/).

Como probablemente puedas adivinar, todo lo que tienes que hacer es cargar el gif, usar el código de Alex para convertirlo en una matriz de ImageFiles/BufferedImages, usar tu código Graphics2D para cambiar el tamaño de cada fotograma (deberás agregar un método setImage a la clase ImageFrame de Alex), luego use el código de Elliot para convertir la matriz a un gif! Esto es lo que se parece a la mía:

public static void main(String[] args) 
{ 
    try { 
    File imageFile = new File("InputFile"); 
    FileInputStream fiStream = new FileInputStream(imageFile); 

    ImageFrame[] frames = readGif(fiStream); 
    for(int i = 0; i < frames.length; i++){ 
     //code to resize the image 
     BufferedImage image = ImageUtilities.resizeImage(frames[ i ].getImage(), newWidth, newHeight); 
     frames[ i ].setImage(image); 
    } 

    ImageOutputStream output = 
     new FileImageOutputStream(new File("OutputFile")); 

    GifSequenceWriter writer = 
     new GifSequenceWriter(output, frames[0].getImage().getType(), frames[0].getDelay(), true); 

    writer.writeToSequence(frames[0].getImage()); 
    for (int i = 1; i < frames.length; i++) { 
     BufferedImage nextImage = frames[i].getImage(); 
     writer.writeToSequence(nextImage); 
    } 

    writer.close(); 
    output.close(); 
    } 
    catch (FileNotFoundException e) { 
    System.out.println("File not found"); 
    } 
    catch (IOException e) { 
    System.out.println("IO Exception"); 
    } 
} 

Este código, sin embargo, no tiene en cuenta las imágenes GIF con diferente cantidad de tiempo que transcurre entre bastidores.

+1

impresionante, muchas gracias. Totalmente resuelto y puedo cambiar el tamaño de los gifs y mantener la animación ahora. La única nota es que debe multiplicar las tramas [0] .getDelay() por 10 porque dentro de GifSequenceWriter se divide por 10 (para ajustar desde milisegundos) – Erich

+0

Funciona bien pero toma alrededor de 200MB para gif de tamaño 1MB y 222 cuadros. ¿Hay alguna razón para reducir el uso de memoria? – Vipul

1

Así que sé que esto es viejo, pero encontré una solución, estoy usando Java 8 no estoy seguro si funcionará con otras versiones.

ImageIcon image = ? (whatever/wherever your gif is) 
    int width = 100; 
    int height = 100; 
    image.setImage(image.getImage().getScaledInstance(width, height, Image.SCALE_DEFAULT)); 

puede cambiar SCALE_DEFAULT a los que se muestran aquí a excepción de SCALE_SMOOTH y SCALE_AREA_AVREAGING no funcionó para mí, fue blanco https://docs.oracle.com/javase/7/docs/api/java/awt/Image.html

+0

Este es el método que uso. SCALE_SMOOTH y SCALE_AREA_AVERAGING son el mismo algoritmo bajo las carátulas, y puedo confirmar que obtendré una imagen en blanco si le doy un GIF animado. Los mejores resultados de SCALE_DEFAULT en ese caso. Para otras imágenes, SCALE_SMOOTH produce resultados algo mejores. – JakeRobb