Wyodrębnianie klatek z pliku GIF

0

Jest w Javie jakaś klasa, dzięki której mógłbym rozebrać gifa, pobrać wszystkie klatki i co ważniejsze czas trwania każdej klatki. Często w gifach klatki nie są wyświetlane taki sam czas. Rozebrać i podejrzeć czas mogę w PSie, ale potrzebuję napisać program w Javie, który będzie zawierał taką funkcjonalność.

3

Sam ostatnio potrzebowałem obsługi gifów Javie. Okazuje się, że jest takie coś.

    public void paint(Graphics g) {
            }
            if (img != null) {
                g2.drawImage(img, (this.getWidth() - img.getWidth(null)) / 2, (this.getHeight() - img.getHeight(null)) / 2, this); // Tutaj Ci się rysuje każda klatka po kolei
            }
            g2.dispose();
        }
    }

img jest oczywiście gifem. Nadpisujesz do tego metode z interfejsu Observer (który implementują komponenty). Ja mam to w ten sposób.

    public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) { 
        if ((flags & ImageObserver.ALLBITS) != 0) {
            this.repaint();
        }
        if ((flags & ImageObserver.FRAMEBITS) != 0) {
            this.repaint();
        }
        /*  if((flags & ImageObserver.ERROR)!=0)
        {
        System.out.println("ERROR");
        }
        if((flags & ImageObserver.ABORT)!=0)
        {
        System.out.println("ABORT");
        }
        if((flags & ImageObserver.SOMEBITS)!=0)
        {
        System.out.println("SOMEBITS");
        } */
        return true;
    }

Metoda ta jest wywoływana przez demona odpowiedzialnego za ładowanie brazu i animacje (odpowiednio ImageFetcher i ImageAnimator - systemowe demony) za każdym razem kiedy będzie gotowa kolejna klatka.
Warunkiem aby to działało jest załadowanie obrazu przez Toolkit nie ImageIO (w drugim przypadku zaciągnie Ci tylko jedną klatę). Obrazek jest klasy Image;
Poniżej input stream tworzysz z URL tzn new URL("file:/ściezka/łamana/w/prawo.gif).getInputStream(). Można też wywołać sobie URL ze klasy Class#getResource - URL. Możliwe, że AsStream też zadziała nie sprawdzałem.

    public void setImage(InputStream is) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = ByteBuffer.allocate(1024).array();
        int i = 0;
        while ((i = is.read(buffer)) > 0) {
            baos.write(buffer, 0, i);
        }
        baos.close();
        buffer = null;
        img = Toolkit.getDefaultToolkit().createImage(baos.toByteArray());
    }

W taki sposób możesz sobie wyrysować każdą klatę z osobna (a rysować przecież można do innego obrazu).
Nie mam pojęcia jednak jak wyciągnąć czas.
Najlepiej byłoby tak naprawdę sprawdzić dokumentacje formatu GIF. Tam opisana byłaby budowa pliku, i wiedziałbyś gdzie szukać interesujących Cię danych.

1

Najlepiej byłoby tak naprawdę sprawdzić dokumentacje formatu GIF. Tam opisana byłaby budowa pliku, i wiedziałbyś gdzie szukać interesujących Cię danych.

Ja coś podobnego robiłem (tylko że w C), jeśli Cię to interesuje to można by pokombinować (ale gotowca Ci siłą rzeczy nie napiszę bo nie używam Javy :>)

Aktualny format GIF jest tutaj:
http://www.w3.org/Graphics/GIF/spec-gif89a.txt

Ale tak naprawdę prawdopodobnie wystarczy Ci skorzystanie z jakiejś gotowej biblioteki... Np. http://www.hotscripts.com/listing/gif4j-pro-java-gif-imaging-library/ .
Albo z kodu powyżej, ładny pomysł trzeba przyznać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1