/**
 * FrameReader.java - Retrieves all frames from an image
 * Copyright (c) 2007 Alexander Hristov .
 *
 * Licensed under the LGPL License - http://www.gnu.org/licenses/lgpl.txt
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA  
 */

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageInputStreamSpi;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.spi.ServiceRegistry;
import javax.imageio.stream.ImageInputStream;

public class FrameReader {
  public static BufferedImage[] getAllFrames(InputStream in) throws IOException {
    IIORegistry providers = IIORegistry.getDefaultInstance();
    Iterator it = providers.getServiceProviders(ImageInputStreamSpi.class,true);
    ImageInputStream imgStream = null;
    
    // Create an ImageInputStream with the first appropriate SPI
    while (it.hasNext()) {
      ImageInputStreamSpi spi = (ImageInputStreamSpi)it.next();
      if (spi.getInputClass().isInstance(in)) {
        imgStream = spi.createInputStreamInstance(in);
        break;
      }
    }
    if (imgStream == null)
      throw new IOException("No appropriate SPI for this input stream ");
    
    it = providers.getServiceProviders(
        ImageReaderSpi.class, new CanDecodeFilter(imgStream),true);
    if (!it.hasNext())
      throw new IOException("No class can read this image format");
    
    ImageReaderSpi readerSpi = (ImageReaderSpi)it.next();
    ImageReader reader = readerSpi.createReaderInstance();
    ImageReadParam param = reader.getDefaultReadParam();
    
    reader.setInput(imgStream, false, true);
    int numFrames = reader.getNumImages(true);
    BufferedImage[] frames = new BufferedImage[numFrames];
    for (int i = 0; i < numFrames; i++) {
      frames[i] = reader.read(i,param);
    }
    
    imgStream.close();
    reader.dispose();
    return frames;
  }
  
  static class CanDecodeFilter implements ServiceRegistry.Filter {
    ImageInputStream stream;
    public CanDecodeFilter(ImageInputStream stream) {
      this.stream = stream;
    }
    public boolean filter(Object element) {
      try {
          ImageReaderSpi spi = (ImageReaderSpi)element;
          boolean canDecode = false;
          stream.mark();
          canDecode = spi.canDecodeInput(stream);
          stream.reset();
          return canDecode;
      } catch (IOException e) {
          return false;
      }
    }
  }
}

