让swing正确显示gif图片

来源:互联网 发布:网络管理工程师招聘 编辑:程序博客网 时间:2024/04/30 02:04
  今天美工做了一幅gif的图片,我放到JLabel里面去,gif图片闪动得特别厉害。以为美工提供的图片有问题,又双击用IE打开,却显示正常。心想应该是java组建对gif图片显示的问题。网上查了下swing对gif的显示。果不其然,是swing对gif的显示问题。下面整理下处理swing正确显示gif图片的问题。

首先需要对Gif这种图片格式有一些基本认识。
第一:Gif由一系列Image组成,也就是桢,Gif动画就是连续地显示这些桢,但是这还不够。
第二:无论某一时刻轮循到哪一桢,第1桢,总是要当作背景画出来,而且第1桢也是所有桢当中最长最高的,它的尺寸也是整个Gif图象的尺寸,位置从(0, 0)开始,其余各桢可能只是描述与相临各桢变化的部分,所以长和高要小且不完整,起始位置是该桢相对整体背景的位置。(这点SWT也是这样做的)
第三:Gif动画连续显示不一定是各个桢轮循单独显示,而是不仅仅显示当前该显示的桢,还要向前追溯到"第一桢",从"第一桢"开始到当前应该显示的桢组成的连续一系列"桢簇",所以某一时刻单单显示背景和当前桢是不够的,而是显示背景和当前"桢簇"。""桢簇""是我自己取的名字,而且我看SWT轮循的例子中并没有用到"桢簇",而是传统的单桢轮循。但是同样的方法对Swing不奏效,现在我对此还不得其解。关于"第一桢",是和com.sun.imageio.plugins.gif.GIFImageMetadata类的disposalMethod属性有关,在SWT中这个属性是org.eclipse.swt.graphics.ImageData.disposalMethod。disposalMethod据我的研究是描述处理桢的方法,常见的disposalMethod取值有none(取值0,不处理)、Background(取值2,背景)两种,所谓的当前桢的"第一桢"就是向前追溯到最近的disposalMethod取值为2的那一桢的下一桢,也就是说或者"第一桢"的前一桢的disposalMethod取值为2,或者"第一桢"就是Gif索引为2的桢,因为Gif的第1桢总要当背景显示。
第四:桢的元数据在SWT中用org.eclipse.swt.graphics.ImageData类封装,在Swing中对应的是com.sun.imageio.plugins.gif.GIFImageMetadata(可是截止到JDK6.0 u11,这个类的版本号还是0.5,有些另人失望:(),可以通过次类获取到delayTime这个属性,也就是下一桢的间隔时间,但是有很多Gif,这个值总是0,所以Swing显示频率相当的快。

下面为处理代码:

public class GifComponent extends JComponent {    private static final long serialVersionUID = 1L;    private GifBean[] gifBeans;    private Map<Integer, Integer[]> gifBeanMap = new HashMap<Integer, Integer[]>();    private int index = 0;    private int delayFactor;    private Timer timer;    /**     *      * @param gifFile     * @param delayFactor     *            显示gif每帧图片的时间因子     */    public GifComponent(File gifFile, int delayFactor) {setDelayFactor(delayFactor);setGifFile(gifFile);    }    /**     * 设置Gif文件     *      * @param gifFile     */    public void setGifFile(File gifFile) {ImageReader reader = null;try {    ImageInputStream imageIn = ImageIO.createImageInputStream(gifFile);    Iterator<ImageReader> iter = ImageIO    .getImageReadersByFormatName("gif");    if (iter.hasNext()) {reader = iter.next();    }    reader.setInput(imageIn, false);    gifBeanMap.clear();    gifBeans = new GifBean[reader.getNumImages(true)];    GIFImageMetadata meta = null;    for (int i = 0; i < gifBeans.length; i++) {meta = (GIFImageMetadata) reader.getImageMetadata(i);gifBeans[i] = new GifBean();gifBeans[i].image = reader.read(i);gifBeans[i].x = meta.imageLeftPosition;gifBeans[i].y = meta.imageTopPosition;gifBeans[i].width = meta.imageWidth;gifBeans[i].height = meta.imageHeight;gifBeans[i].disposalMethod = meta.disposalMethod;gifBeans[i].delayTime = meta.delayTime == 0 ? 1: meta.delayTime;    }    for (int i = 1; i < gifBeans.length; i++) {if (gifBeans[i].disposalMethod == 2) {    gifBeanMap.put(new Integer(i), new Integer[] { i });    continue;}int firstIndex = getFirstIndex(i);List<Integer> list = new ArrayList<Integer>();for (int j = firstIndex; j <= i; j++) {    list.add(j);}gifBeanMap.put(new Integer(i), list.toArray(new Integer[] {}));    }} catch (IOException e) {    e.printStackTrace();}setTimer();    }    private synchronized void setTimer() {if (timer != null) {    timer.cancel();}timer = new Timer("show gif");timer.schedule(new TimerTask() {    @Override    public void run() {repaint();try {    Thread.sleep(gifBeans[index].delayTime * delayFactor);} catch (InterruptedException e) {}index++;if (index >= gifBeans.length) {    index = 0;}    }}, 0, 1);    }    /**     * 设置时间因子     *      * @param delayFactor     */    public void setDelayFactor(int delayFactor) {this.delayFactor = delayFactor;    }    @Override    protected void paintComponent(Graphics g) {g.drawImage(gifBeans[0].image, gifBeans[0].x, gifBeans[0].y, this);if (index > 0) {    Integer[] array = gifBeanMap.get(index);    for (Integer i : array) {g.drawImage(gifBeans[i].image, gifBeans[i].x, gifBeans[i].y,this);    }}    }    private int getFirstIndex(int index) {int tempIndex = index;while (tempIndex > 1) {    if (tempIndex - 1 > 0    && gifBeans[tempIndex - 1].disposalMethod == 2) {return index;    }    tempIndex--;}return tempIndex;    }    /**     * 用于保持gif每帧图片的信息     */    public class GifBean {public BufferedImage image;public int x;public int y;public int width;public int height;public int disposalMethod;public int delayTime;    }}


 

原文参考:http://space.itpub.net/13685345/viewspace-514315 

 

原创粉丝点击