src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java

Print this page




  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.imageio.plugins.gif;
  27 
  28 import java.awt.Point;
  29 import java.awt.Rectangle;
  30 import java.awt.image.BufferedImage;
  31 import java.awt.image.DataBuffer;
  32 import java.awt.image.WritableRaster;
  33 import java.io.BufferedInputStream;
  34 import java.io.DataInputStream;
  35 import java.io.EOFException;
  36 import java.io.InputStream;
  37 import java.io.IOException;
  38 import java.nio.ByteOrder;
  39 import java.util.ArrayList;
  40 import java.util.Arrays;
  41 import java.util.Iterator;
  42 import java.util.List;
  43 import javax.imageio.IIOException;
  44 import javax.imageio.ImageReader;
  45 import javax.imageio.ImageReadParam;
  46 import javax.imageio.ImageTypeSpecifier;
  47 import javax.imageio.metadata.IIOMetadata;
  48 import javax.imageio.spi.ImageReaderSpi;
  49 import javax.imageio.stream.ImageInputStream;
  50 import com.sun.imageio.plugins.common.ReaderUtil;





  51 
  52 public class GIFImageReader extends ImageReader {
  53 
  54     // The current ImageInputStream source.
  55     ImageInputStream stream = null;
  56 
  57     // Per-stream settings
  58 
  59     // True if the file header including stream metadata has been read.
  60     boolean gotHeader = false;
  61 
  62     // Global metadata, read once per input setting.
  63     GIFStreamMetadata streamMetadata = null;
  64 
  65     // The current image index
  66     int currIndex = -1;
  67 
  68     // Metadata for image at 'currIndex', or null.
  69     GIFImageMetadata imageMetadata = null;
  70 


 177 
 178         int index = locateImage(imageIndex);
 179         if (index != imageIndex) {
 180             throw new IndexOutOfBoundsException();
 181         }
 182         readMetadata();
 183         return imageMetadata.imageWidth;
 184     }
 185 
 186     public int getHeight(int imageIndex) throws IIOException {
 187         checkIndex(imageIndex);
 188 
 189         int index = locateImage(imageIndex);
 190         if (index != imageIndex) {
 191             throw new IndexOutOfBoundsException();
 192         }
 193         readMetadata();
 194         return imageMetadata.imageHeight;
 195     }
 196 






























 197     public Iterator getImageTypes(int imageIndex) throws IIOException {
 198         checkIndex(imageIndex);
 199 
 200         int index = locateImage(imageIndex);
 201         if (index != imageIndex) {
 202             throw new IndexOutOfBoundsException();
 203         }
 204         readMetadata();
 205 
 206         List l = new ArrayList(1);
 207 
 208         byte[] colorTable;
 209         if (imageMetadata.localColorTable != null) {
 210             colorTable = imageMetadata.localColorTable;
 211         } else {
 212             colorTable = streamMetadata.globalColorTable;
 213         }
 214 
 215         // Normalize color table length to 2^1, 2^2, 2^4, or 2^8
 216         int length = colorTable.length/3;


 222         } else if (length == 8 || length == 16) {
 223             // Bump from 3 to 4 bits
 224             bits = 4;
 225         } else {
 226             // Bump to 8 bits
 227             bits = 8;
 228         }
 229         int lutLength = 1 << bits;
 230         byte[] r = new byte[lutLength];
 231         byte[] g = new byte[lutLength];
 232         byte[] b = new byte[lutLength];
 233 
 234         // Entries from length + 1 to lutLength - 1 will be 0
 235         int rgbIndex = 0;
 236         for (int i = 0; i < length; i++) {
 237             r[i] = colorTable[rgbIndex++];
 238             g[i] = colorTable[rgbIndex++];
 239             b[i] = colorTable[rgbIndex++];
 240         }
 241 
 242         byte[] a = null;
 243         if (imageMetadata.transparentColorFlag) {
 244             a = new byte[lutLength];
 245             Arrays.fill(a, (byte)255);
 246 
 247             // Some files erroneously have a transparent color index
 248             // of 255 even though there are fewer than 256 colors.
 249             int idx = Math.min(imageMetadata.transparentColorIndex,
 250                                lutLength - 1);
 251             a[idx] = (byte)0;
 252         }
 253 
 254         int[] bitsPerSample = new int[1];
 255         bitsPerSample[0] = bits;
 256         l.add(ImageTypeSpecifier.createIndexed(r, g, b, a, bits,
 257                                                DataBuffer.TYPE_BYTE));
 258         return l.iterator();
 259     }
 260 
 261     public ImageReadParam getDefaultReadParam() {
 262         return new ImageReadParam();
 263     }
 264 
 265     public IIOMetadata getStreamMetadata() throws IIOException {
 266         readHeader();
 267         return streamMetadata;
 268     }
 269 
 270     public IIOMetadata getImageMetadata(int imageIndex) throws IIOException {
 271         checkIndex(imageIndex);
 272 
 273         int index = locateImage(imageIndex);
 274         if (index != imageIndex) {
 275             throw new IndexOutOfBoundsException("Bad image index!");
 276         }
 277         readMetadata();




  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.imageio.plugins.gif;
  27 
  28 import java.awt.Point;
  29 import java.awt.Rectangle;
  30 import java.awt.image.BufferedImage;
  31 import java.awt.image.DataBuffer;
  32 import java.awt.image.WritableRaster;


  33 import java.io.EOFException;

  34 import java.io.IOException;
  35 import java.nio.ByteOrder;
  36 import java.util.ArrayList;

  37 import java.util.Iterator;
  38 import java.util.List;
  39 import javax.imageio.IIOException;
  40 import javax.imageio.ImageReader;
  41 import javax.imageio.ImageReadParam;
  42 import javax.imageio.ImageTypeSpecifier;
  43 import javax.imageio.metadata.IIOMetadata;
  44 import javax.imageio.spi.ImageReaderSpi;
  45 import javax.imageio.stream.ImageInputStream;
  46 import com.sun.imageio.plugins.common.ReaderUtil;
  47 import java.awt.image.ColorModel;
  48 import java.awt.image.IndexColorModel;
  49 import java.awt.image.MultiPixelPackedSampleModel;
  50 import java.awt.image.PixelInterleavedSampleModel;
  51 import java.awt.image.SampleModel;
  52 
  53 public class GIFImageReader extends ImageReader {
  54 
  55     // The current ImageInputStream source.
  56     ImageInputStream stream = null;
  57 
  58     // Per-stream settings
  59 
  60     // True if the file header including stream metadata has been read.
  61     boolean gotHeader = false;
  62 
  63     // Global metadata, read once per input setting.
  64     GIFStreamMetadata streamMetadata = null;
  65 
  66     // The current image index
  67     int currIndex = -1;
  68 
  69     // Metadata for image at 'currIndex', or null.
  70     GIFImageMetadata imageMetadata = null;
  71 


 178 
 179         int index = locateImage(imageIndex);
 180         if (index != imageIndex) {
 181             throw new IndexOutOfBoundsException();
 182         }
 183         readMetadata();
 184         return imageMetadata.imageWidth;
 185     }
 186 
 187     public int getHeight(int imageIndex) throws IIOException {
 188         checkIndex(imageIndex);
 189 
 190         int index = locateImage(imageIndex);
 191         if (index != imageIndex) {
 192             throw new IndexOutOfBoundsException();
 193         }
 194         readMetadata();
 195         return imageMetadata.imageHeight;
 196     }
 197 
 198     // We don't check all parameters as ImageTypeSpecifier.createIndexed do
 199     // since this method is private and we pass consistent data here
 200     private ImageTypeSpecifier createIndexed(byte[] r, byte[] g, byte[] b,
 201                                              int bits) {
 202         ColorModel colorModel;
 203         if (imageMetadata.transparentColorFlag) {
 204             // Some files erroneously have a transparent color index
 205             // of 255 even though there are fewer than 256 colors.
 206             int idx = Math.min(imageMetadata.transparentColorIndex,
 207                     r.length - 1);
 208             colorModel = new IndexColorModel(bits, r.length, r, g, b, idx);
 209         } else {
 210             colorModel = new IndexColorModel(bits, r.length, r, g, b);
 211         }
 212         
 213         SampleModel sampleModel;
 214         if (bits == 8) {
 215             int[] bandOffsets = {0};
 216             sampleModel =
 217                     new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
 218                     1, 1, 1, 1,
 219                     bandOffsets);
 220         } else {
 221             sampleModel =
 222                     new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
 223                     1, 1, bits);
 224         }
 225         return new ImageTypeSpecifier(colorModel, sampleModel);
 226     }
 227     
 228     public Iterator getImageTypes(int imageIndex) throws IIOException {
 229         checkIndex(imageIndex);
 230 
 231         int index = locateImage(imageIndex);
 232         if (index != imageIndex) {
 233             throw new IndexOutOfBoundsException();
 234         }
 235         readMetadata();
 236 
 237         List l = new ArrayList(1);
 238 
 239         byte[] colorTable;
 240         if (imageMetadata.localColorTable != null) {
 241             colorTable = imageMetadata.localColorTable;
 242         } else {
 243             colorTable = streamMetadata.globalColorTable;
 244         }
 245 
 246         // Normalize color table length to 2^1, 2^2, 2^4, or 2^8
 247         int length = colorTable.length/3;


 253         } else if (length == 8 || length == 16) {
 254             // Bump from 3 to 4 bits
 255             bits = 4;
 256         } else {
 257             // Bump to 8 bits
 258             bits = 8;
 259         }
 260         int lutLength = 1 << bits;
 261         byte[] r = new byte[lutLength];
 262         byte[] g = new byte[lutLength];
 263         byte[] b = new byte[lutLength];
 264 
 265         // Entries from length + 1 to lutLength - 1 will be 0
 266         int rgbIndex = 0;
 267         for (int i = 0; i < length; i++) {
 268             r[i] = colorTable[rgbIndex++];
 269             g[i] = colorTable[rgbIndex++];
 270             b[i] = colorTable[rgbIndex++];
 271         }
 272 
 273         l.add(createIndexed(r, g, b, bits));















 274         return l.iterator();
 275     }
 276 
 277     public ImageReadParam getDefaultReadParam() {
 278         return new ImageReadParam();
 279     }
 280 
 281     public IIOMetadata getStreamMetadata() throws IIOException {
 282         readHeader();
 283         return streamMetadata;
 284     }
 285 
 286     public IIOMetadata getImageMetadata(int imageIndex) throws IIOException {
 287         checkIndex(imageIndex);
 288 
 289         int index = locateImage(imageIndex);
 290         if (index != imageIndex) {
 291             throw new IndexOutOfBoundsException("Bad image index!");
 292         }
 293         readMetadata();