/* * Copyright (C) 2013 Jonathan * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package tumblrviewer; import com.sun.imageio.plugins.gif.GIFImageMetadata; import com.sun.imageio.plugins.gif.GIFImageReader; import java.awt.Image; import java.awt.image.ImageObserver; import static java.awt.image.ImageObserver.FRAMEBITS; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; import javax.imageio.stream.ImageInputStream; import javax.swing.JLabel; /** * A couple of classes used to ensure GIF's which have their time delay set to * zero can still be displayed and animated correctly without using 100% CPU. * * @author jonathan */ public class GIFzeroTimedWorkaround { private static final long FRAME_DELAY_MS = 100; /** * Checks if a GIF's delay time between frames is set to zero or not (which * causes problems) * @param url the URL of the GIF to check * @return true if the GIF is zero timed, false if not a GIF or GIF is okay */ @SuppressWarnings( { "BroadCatchBlock", "TooBroadCatch" }) public static boolean isZeroTimedGif(URL url) { if (!url.getFile().toLowerCase().endsWith("gif")) { //Immediately exclude non-GIFs return false; } try { // Read the delay time for the first frame in the animated gif GIFImageReader reader = (GIFImageReader) ImageIO.getImageReadersByFormatName("GIF").next(); ImageInputStream iis = ImageIO.createImageInputStream(url.openStream()); reader.setInput(iis); GIFImageMetadata md = (GIFImageMetadata) reader.getImageMetadata(0); reader.dispose(); iis.close(); if (md.delayTime == 0) { return true; } } catch (Exception e) { return true; //Play it safe - something went wrong } return false; } /** * Set this as the ImageObserver to workaround zero time delayed GIFs. * It will make them play back at a sensible speed again by pausing for a * set delay time between updates. */ public static class ImageObserverWorkaround implements ImageObserver { private final JLabel imageLabel; public ImageObserverWorkaround(JLabel imageLabel) { this.imageLabel = imageLabel; } @Override public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { imageLabel.repaint(); if ((infoflags & FRAMEBITS) == 0) { return true; } else { try { //Make the frame wait 100ms like browsers by do in this situation by sleeping the thread //TODO: Sometimes thread's seem to join when the image is viewed in two different JFrame's simultaneously and then this get's applied twice slowing the image down twice as much - not a major issue but needs looking into why it's happening (inconsistent sometimes it's fine and this doesn't happen at all) Thread.sleep(FRAME_DELAY_MS); } catch (InterruptedException ex) { } } return true; } } }