9

i am using Graphics2D in java to resize images, it works perfect with jpg,png and other formats. my problem is the animated GIF images, after re-sizing the animation is gone!

here is the method am using:

    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;
}

so, any clues how can i keep on the animated gif after re-sizing? Thanks.

G.Ahmed
  • 146
  • 1
  • 1
  • 7

4 Answers4

12

So I know this is old but I found a solution, I am using Java 8 not sure if it will work with other versions.

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

you can change SCALE_DEFAULT to the ones listed here except for SCALE_SMOOTH and SCALE_AREA_AVREAGING didn't work for me, it was blank https://docs.oracle.com/javase/7/docs/api/java/awt/Image.html

Jonny March
  • 121
  • 1
  • 3
  • 1
    This is the method I use. SCALE_SMOOTH and SCALE_AREA_AVERAGING are the same algorithm under the covers, and I can confirm that I get a blank image output if I feed it an animated GIF. Best results from SCALE_DEFAULT in that case. For other images, SCALE_SMOOTH produces somewhat nicer results. – JakeRobb May 10 '17 at 18:08
  • Excellent advice, this really works. Of course smoothing would be even more desirable but this is ok to get some results quickly. – Stefan Reich Jan 09 '22 at 18:38
8

I found two sources which when combined can be used to resize the image while keeping the animation.

On this question ( Convert each animated GIF frame to a separate BufferedImage ) look for the answer by Alex Orzechowski. His code takes a gif file and converts it to an array of ImageFrames (which is a class he made which wraps a BufferedImage). Then look at this code which converts a sequence of BufferedImages to a gif file ( http://elliot.kroo.net/software/java/GifSequenceWriter/ ).

As you could probably guess, all you need to do is upload the gif, use Alex's code to convert it to an array of ImageFiles/BufferedImages, use your Graphics2D code to resize each frame (you'll need to add a setImage method to Alex's ImageFrame class), then use Elliot's code to convert the array to a gif! Here is what mine looks like:

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" );
  }
}

This code, however, does not account for gif images with different amount of time elapsing between frames.

Community
  • 1
  • 1
Ian B.
  • 81
  • 1
  • 3
  • 2
    Awesome, thanks so much. Totally solved it and I can resize gifs and keep the animation now. Only note is you should multiply frames[0].getDelay() by 10 because inside GifSequenceWriter it divides by 10 (to adjust from milliseconds) – Erich Dec 29 '14 at 15:57
  • 1
    It work well but takes around 200MB for gif of size 1MB and 222 frames. is there any why to reduce memory usage?? – Vipul Apr 18 '16 at 15:02
  • Thank yout for the Hint with the Sequence! – drdrej Apr 04 '19 at 11:08
  • elliot site is down. `GifSequenceWriter` code could be found here: https://github.com/Deep-Symmetry/wayang/blob/main/src/main/java/org/deepsymmetry/GifSequenceWriter.java (or use web archive) – chill appreciator Jun 06 '23 at 10:45
1

Jonny March's solution did not work for me because it processes and outputs only the first image of GIF file.

Here is my solution, it keeps the animation while resizing.

File f = new File("path of your animated gif");
URL img = f.toURL();
ImageIcon icon = new ImageIcon(img);
//You have to convert it to URL because ImageIO just ruins the animation

int width = 100;
int height = 100;
icon.setImage(icon.getImage().getScaledInstance(width, height,Image.SCALE_DEFAULT));
count_campeador
  • 161
  • 1
  • 10
0

BufferedImage origBuffImg = ImageIO.read(orignalImage); int type = origBuffImg.getType() == 0? BufferedImage.TYPE_INT_ARGB : origBuffImg.getType();

          BufferedImage resizedBuffImg = new BufferedImage(width, height, type);
          Graphics2D g = resizedBuffImg.createGraphics();
          g.drawImage(origBuffImg, 0, 0, width, height, null);
          g.dispose();
         
          String newFile = orignalImage.getAbsolutePath().substring(0,orignalImage.getAbsolutePath().lastIndexOf("."))+"_"+width+"x"+height+"."+extension;
          ImageIO.write(resizedBuffImg, extension, new File(newFile));
         
          System.out.println("File created : "+newFile);