You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java代码调整animated GIF(动态GIF)文件的尺寸?

Java 调整动图GIF尺寸实现方案

核心实现思路

动图GIF是由多帧静态图片+帧控制元数据组成的,不能直接按照单张静态图的方式缩放,需要先拆分提取所有帧和对应元数据(帧时长、循环次数、透明属性、渲染策略等),逐帧缩放完成后再按照原参数重新拼接为动图即可。

基础实现(仅用JDK内置API)

不需要引入第三方依赖,直接用JDK自带的javax.imageio相关类实现:

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class GifResizer {
    // 按目标宽高缩放GIF
    public void resizeGif(File sourceGif, File targetGif, int targetWidth, int targetHeight) throws IOException {
        // 读取原GIF的所有帧和元数据
        List<IIOImage> frames = new ArrayList<>();
        List<IIOMetadata> frameMetadatas = new ArrayList<>();
        IIOMetadata streamMetadata = null;
        ImageReader gifReader = getGifReader();
        try (ImageInputStream iis = ImageIO.createImageInputStream(sourceGif)) {
            gifReader.setInput(iis);
            int frameCount = gifReader.getNumImages(true);
            streamMetadata = gifReader.getStreamMetadata();
            for (int i = 0; i < frameCount; i++) {
                IIOMetadata frameMeta = gifReader.getImageMetadata(i);
                BufferedImage originalFrame = gifReader.read(i);
                // 缩放单帧
                BufferedImage resizedFrame = resizeSingleFrame(originalFrame, targetWidth, targetHeight);
                frames.add(new IIOImage(resizedFrame, null, frameMeta));
                frameMetadatas.add(frameMeta);
            }
        } finally {
            gifReader.dispose();
        }
        // 写入新的GIF
        ImageWriter gifWriter = getGifWriter();
        try (ImageOutputStream ios = ImageIO.createImageOutputStream(targetGif)) {
            gifWriter.setOutput(ios);
            ImageWriteParam writeParam = gifWriter.getDefaultWriteParam();
            gifWriter.write(streamMetadata, frames.iterator(), writeParam);
        } finally {
            gifWriter.dispose();
        }
    }

    // 缩放单帧图片,保留透明通道
    private BufferedImage resizeSingleFrame(BufferedImage original, int targetWidth, int targetHeight) {
        BufferedImage resized = new BufferedImage(targetWidth, targetHeight, original.getType());
        Graphics2D g2d = resized.createGraphics();
        // 双三次插值保证缩放清晰度
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.drawImage(original, 0, 0, targetWidth, targetHeight, null);
        g2d.dispose();
        return resized;
    }

    // 获取GIF读取器
    private ImageReader getGifReader() {
        Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("gif");
        if (readers.hasNext()) {
            return readers.next();
        }
        throw new RuntimeException("No GIF reader found");
    }

    // 获取GIF写入器
    private ImageWriter getGifWriter() {
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("gif");
        if (writers.hasNext()) {
            return writers.next();
        }
        throw new RuntimeException("No GIF writer found");
    }
}

JetBrains插件适配优化

如果是在JetBrains平台插件中使用,可以直接调用平台内置工具类减少重复代码:

  • 单帧缩放可以直接用com.intellij.util.ImageUtil#scaleImage方法,不需要自己实现缩放逻辑
  • 图片读取可以用com.intellij.util.ImageLoader类,兼容平台内的各类资源加载场景

注意事项

  • 如果需要修改GIF的播放速度、循环次数,可以在读取元数据的时候修改对应参数再写入
  • 透明GIF缩放时不要修改BufferedImage的类型,避免丢失透明通道出现异常背景色
  • 对于大尺寸GIF逐帧处理会占用一定内存,建议根据实际场景增加内存限制或者异步处理逻辑

内容的提问来源于stack exchange,提问作者Nikita

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 20:54:00