Source for gnu.javax.imageio.gif.GIFImageReader

   1: /* GIFImageReader.java --
   2:    Copyright (C)  2006  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.javax.imageio.gif;
  39: 
  40: import gnu.javax.imageio.IIOInputStream;
  41: 
  42: import java.io.IOException;
  43: import java.io.InputStream;
  44: import javax.imageio.*;
  45: import javax.imageio.spi.*;
  46: import javax.imageio.metadata.*;
  47: import javax.imageio.stream.ImageInputStream;
  48: import java.util.Iterator;
  49: import java.awt.image.BufferedImage;
  50: import java.awt.image.IndexColorModel;
  51: import java.awt.image.SampleModel;
  52: import java.awt.image.MultiPixelPackedSampleModel;
  53: import java.awt.image.SinglePixelPackedSampleModel;
  54: import java.awt.image.DataBuffer;
  55: import java.awt.image.DataBufferByte;
  56: import java.awt.image.Raster;
  57: import java.awt.image.WritableRaster;
  58: 
  59: public class GIFImageReader extends ImageReader
  60: {
  61:   private GIFFile file;
  62: 
  63:   protected GIFImageReader(ImageReaderSpi originatingProvider)
  64:   {
  65:     super( originatingProvider );
  66:     file = null;
  67:   }
  68: 
  69:   private void readImage() throws IOException
  70:   {
  71:     if( file != null )
  72:       return;
  73: 
  74:     try
  75:       {
  76:         if( input instanceof InputStream )
  77:           file = new GIFFile( (InputStream)input );
  78:         else
  79:           file = new GIFFile( new IIOInputStream((ImageInputStream)input) );
  80:       }
  81:     catch(GIFFile.GIFException ge)
  82:       {
  83:         throw new IIOException(ge.getMessage());
  84:       }
  85:   }
  86: 
  87:   /**
  88:    * Returns the Global/Local palette as an IndexColorModel
  89:    */
  90:   private IndexColorModel getPalette(int index)
  91:   {
  92:     GIFFile f = file.getImage( index );
  93:     byte[] data = f.getRawPalette();
  94:     int nc = f.getNColors();
  95:     byte[] r = new byte[nc];
  96:     byte[] g = new byte[nc];
  97:     byte[] b = new byte[nc];
  98: 
  99:     for(int i = 0; i < nc; i ++ )
 100:       {
 101:         r[i] = data[ i * 3 ];
 102:         g[i] = data[ i * 3 + 1 ];
 103:         b[i] = data[ i * 3 + 2 ];
 104:       }
 105: 
 106:     if( f.hasTransparency() )
 107:       {
 108:         byte[] a = new byte[nc];
 109:         for(int i = 0; i < nc; i ++ )
 110:           a[i] = (byte)0xFF;
 111:         a[f.getTransparentIndex()] = 0;
 112:         return new IndexColorModel(8, nc, r, g, b, a);
 113:       }
 114: 
 115:     return new IndexColorModel(8, nc, r, g, b);
 116:   }
 117: 
 118:   private void validateIndex(int imageIndex)
 119:     throws IndexOutOfBoundsException
 120:   {
 121:     if( imageIndex < 0 || imageIndex >= getNumImages(false) )
 122:       throw new IndexOutOfBoundsException("Invalid image index.");
 123:   }
 124: 
 125:   public void setInput(Object input)
 126:   {
 127:     super.setInput(input);
 128:   }
 129: 
 130:   public void setInput(Object input,
 131:                        boolean seekForwardOnly,
 132:                        boolean ignoreMetadata)
 133:   {
 134:     super.setInput(input, seekForwardOnly, ignoreMetadata);
 135:   }
 136: 
 137:   public void setInput(Object input, boolean isStreamable)
 138:   {
 139:     super.setInput(input, isStreamable);
 140: 
 141:     if (!(input instanceof ImageInputStream) &&
 142:         !(input instanceof InputStream))
 143:       throw new IllegalArgumentException("Input not an ImageInputStream.");
 144:   }
 145: 
 146:   private void checkStream() throws IOException
 147:   {
 148:     if (!(input instanceof ImageInputStream) &&
 149:         !(input instanceof InputStream))
 150:       throw new IllegalStateException("Input not an ImageInputStream or InputStream.");
 151: 
 152:     if(input == null)
 153:       throw new IllegalStateException("No input stream.");
 154:   }
 155: 
 156:   public int getWidth(int imageIndex) throws IOException
 157:   {
 158:     validateIndex( imageIndex );
 159:     return file.getImage( imageIndex ).getWidth();
 160:   }
 161: 
 162:   public int getHeight(int imageIndex) throws IOException
 163:   {
 164:     validateIndex( imageIndex );
 165:     return file.getImage( imageIndex ).getHeight();
 166:   }
 167: 
 168:   public Iterator getImageTypes(int imageIndex)
 169:   {
 170:     validateIndex( imageIndex );
 171:     return null;
 172:   }
 173: 
 174:   /**
 175:    * Returns the number of images.
 176:    */
 177:   public int getNumImages(boolean allowSearch)
 178:   {
 179:     try // Image should be loaded here already. But just in case:
 180:       {
 181:         readImage();
 182:       }
 183:     catch(IOException ioe)
 184:       {
 185:         return 0; // Well, now we're in trouble. But return something anyway.
 186:       }
 187:     return file.nImages();
 188:   }
 189: 
 190: 
 191:   // FIXME: Support metadata
 192:   public IIOMetadata getImageMetadata(int imageIndex)
 193:   {
 194:     validateIndex( imageIndex );
 195:     return null;
 196:   }
 197: 
 198:   // FIXME: Support metadata
 199:   public IIOMetadata getStreamMetadata()
 200:   {
 201:     return null;
 202:   }
 203: 
 204:   /**
 205:    * Reads the image indexed by imageIndex and returns it as
 206:    * a complete BufferedImage, using a supplied ImageReadParam.
 207:    */
 208:   public BufferedImage read(int imageIndex, ImageReadParam param)
 209:     throws IOException, IIOException
 210:   {
 211:     validateIndex( imageIndex );
 212:     GIFFile f = file.getImage( imageIndex );
 213:     int width = f.getWidth();
 214:     int height = f.getHeight();
 215:     SampleModel sm;
 216:     switch( f.getNColors() )
 217:       {
 218:       case 16:
 219:         sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
 220:                                              width, height, 4);
 221:         break;
 222:       case 4:
 223:         sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
 224:                                              width, height, 2);
 225:         break;
 226:       case 2:
 227:         sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
 228:                                              width, height, 1);
 229:         break;
 230:       default:
 231:         sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE,
 232:                                               width, height,
 233:                                               new int[] {0xFF});
 234:         break;
 235:       }
 236:     DataBuffer db = new DataBufferByte(f.getRawImage(), width * height, 0);
 237:     WritableRaster raster = Raster.createWritableRaster(sm, db, null);
 238: 
 239:     return new BufferedImage(getPalette( imageIndex ), raster, false, null);
 240:   }
 241: }