【问题标题】:resizing animated GIF while keeping it's animation using java调整动画 GIF 的大小,同时使用 java 保持动画
【发布时间】:2012-03-12 15:06:06
【问题描述】:

我在 java 中使用 Graphics2D 来调整图像大小,它适用于 jpg、png 和其他格式。 我的问题是动画 GIF 图像,重新调整大小后动画消失了!

这是我使用的方法:

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

所以,有什么线索可以在重新调整大小后保留动画 gif 吗? 谢谢。

【问题讨论】:

    标签: java animation gif


    【解决方案1】:

    所以我知道这是旧的,但我找到了一个解决方案,我正在使用 Java 8,不确定它是否适用于其他版本。

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

    您可以将 SCALE_DEFAULT 更改为此处列出的值,除了 SCALE_SMOOTH 和 SCALE_AREA_AVREAGING 对我不起作用,它是空白的 https://docs.oracle.com/javase/7/docs/api/java/awt/Image.html

    【讨论】:

    • 这是我使用的方法。 SCALE_SMOOTH 和 SCALE_AREA_AVERAGING 在幕后是相同的算法,如果我给它提供一个动画 GIF,我可以确认我得到一个空白图像输出。在这种情况下,SCALE_DEFAULT 的最佳结果。对于其他图像,SCALE_SMOOTH 会产生更好的结果。
    • 很好的建议,这确实有效。当然平滑会更理想,但这可以快速获得一些结果。
    【解决方案2】:

    我找到了两个来源,当它们组合在一起时,可以在保持动画的同时调整图像大小。

    关于这个问题( Convert each animated GIF frame to a separate BufferedImage ) 寻找 Alex Orzechowski 的答案。他的代码获取一个 gif 文件并将其转换为一个 ImageFrames 数组(这是他创建的一个包含 BufferedImage 的类)。然后看看这段代码,它将一系列 BufferedImages 转换为 gif 文件 (http://elliot.kroo.net/software/java/GifSequenceWriter/)。

    您可能已经猜到了,您需要做的就是上传 gif,使用 Alex 的代码将其转换为 ImageFiles/BufferedImages 数组,使用您的 Graphics2D 代码调整每个帧的大小(您需要添加一个 setImage方法到 Alex 的 ImageFrame 类),然后使用 Elliot 的代码将数组转换为 gif!这是我的样子:

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

    但是,此代码不考虑帧之间经过的时间量不同的 gif 图像。

    【讨论】:

    • 太棒了,非常感谢。完全解决了它,我现在可以调整 gif 的大小并保留动画。唯一需要注意的是你应该将 frames[0].getDelay() 乘以 10,因为在 GifSequenceWriter 中它除以 10(从毫秒开始调整)
    • 它工作得很好,但对于大小为 1MB 和 222 帧的 gif 大约需要 200MB。为什么要减少内存使用??
    • 感谢您对序列的提示!
    【解决方案3】:

    Jonny March 的解决方案对我不起作用,因为它只处理和输出 GIF 文件的第一张图像。

    这是我的解决方案,它在调整大小时保留动画。

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

    【讨论】:

      【解决方案4】:

      BufferedImage origBuffImg = ImageIO.read(orignalImage); int 类型 = 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);
      

      【讨论】:

      • 请用你的代码写一些解释,并正确地确定你的代码。
      猜你喜欢
      • 2013-08-28
      • 2011-11-01
      • 2018-04-18
      • 2011-08-09
      • 2011-08-31
      • 1970-01-01
      • 2012-09-07
      • 2011-06-10
      • 1970-01-01
      相关资源
      最近更新 更多