TIFFImage.java
上传用户:btjssb159
上传日期:2018-01-04
资源大小:241k
文件大小:68k
源码类别:

DNA

开发平台:

Java

  1. /*
  2.  * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without 
  5.  * modification, are permitted provided that the following conditions are met:
  6.  * 
  7.  * -Redistributions of source code must retain the above copyright notice, this 
  8.  * list of conditions and the following disclaimer.
  9.  *
  10.  * -Redistribution in binary form must reproduct the above copyright notice,
  11.  * this list of conditions and the following disclaimer in the documentation
  12.  * and/or other materials provided with the distribution.
  13.  * 
  14.  * Neither the name of Sun Microsystems, Inc. or the names of contributors may
  15.  * be used to endorse or promote products derived from this software without
  16.  * specific prior written permission.
  17.  * 
  18.  * This software is provided "AS IS," without a warranty of any kind. ALL
  19.  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
  20.  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  21.  * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
  22.  * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  23.  * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
  24.  * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
  25.  * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
  26.  * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
  27.  * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
  28.  * POSSIBILITY OF SUCH DAMAGES.
  29.  * 
  30.  * You acknowledge that Software is not designed,licensed or intended for use in 
  31.  * the design, construction, operation or maintenance of any nuclear facility.
  32.  */
  33. import java.awt.Point;
  34. import java.awt.Rectangle;
  35. import java.awt.Transparency;
  36. import java.awt.color.ColorSpace;
  37. import java.awt.image.ColorModel;
  38. import java.awt.image.DataBuffer;
  39. import java.awt.image.DataBufferByte;
  40. import java.awt.image.DataBufferShort;
  41. import java.awt.image.DataBufferUShort;
  42. import java.awt.image.DataBufferInt;
  43. import java.awt.image.Raster;
  44. import java.awt.image.WritableRaster;
  45. import java.awt.image.RenderedImage;
  46. import java.awt.image.SampleModel;
  47. import java.awt.image.IndexColorModel;
  48. import java.awt.image.MultiPixelPackedSampleModel;
  49. import java.awt.image.PixelInterleavedSampleModel;
  50. import java.awt.image.ComponentColorModel;
  51. import java.io.ByteArrayInputStream;
  52. import java.io.File;
  53. import java.io.InputStream;
  54. import java.io.IOException;
  55. import java.lang.reflect.Constructor;
  56. import java.lang.reflect.Method;
  57. import java.util.zip.DataFormatException;
  58. import java.util.zip.Inflater;
  59. import com.sun.image.codec.jpeg.JPEGCodec;
  60. import com.sun.image.codec.jpeg.JPEGDecodeParam;
  61. import com.sun.image.codec.jpeg.JPEGImageDecoder;
  62. public class TIFFImage extends SimpleRenderedImage {
  63.     // Compression types
  64.     public static final int COMP_NONE      = 1;
  65.     public static final int COMP_FAX_G3_1D = 2;
  66.     public static final int COMP_FAX_G3_2D = 3;
  67.     public static final int COMP_FAX_G4_2D = 4;
  68.     public static final int COMP_LZW       = 5;
  69.     public static final int COMP_JPEG_OLD  = 6;
  70.     public static final int COMP_JPEG_TTN2 = 7;
  71.     public static final int COMP_PACKBITS  = 32773;
  72.     public static final int COMP_DEFLATE   = 32946;
  73.     // Image types
  74.     private static final int TYPE_UNSUPPORTED = -1;
  75.     private static final int TYPE_BILEVEL      = 0;
  76.     private static final int TYPE_GRAY_4BIT    = 1;
  77.     private static final int TYPE_GRAY         = 2;
  78.     private static final int TYPE_GRAY_ALPHA   = 3;
  79.     private static final int TYPE_PALETTE      = 4;
  80.     private static final int TYPE_RGB          = 5;
  81.     private static final int TYPE_RGB_ALPHA    = 6;
  82.     private static final int TYPE_YCBCR_SUB    = 7;
  83.     private static final int TYPE_GENERIC      = 8;
  84.     // Incidental tags
  85.     private static final int TIFF_JPEG_TABLES       = 347;
  86.     private static final int TIFF_YCBCR_SUBSAMPLING = 530;
  87.     SeekableStream stream;
  88.     int tileSize;
  89.     int tilesX, tilesY;
  90.     long[] tileOffsets;
  91.     long[] tileByteCounts;
  92.     char[] colormap;
  93.     int sampleSize;
  94.     int compression;
  95.     byte[] palette;
  96.     int numBands;
  97.     int chromaSubH;
  98.     int chromaSubV;
  99.     // Fax compression related variables
  100.     long tiffT4Options;
  101.     long tiffT6Options;
  102.     int fillOrder;
  103.     // LZW compression related variable
  104.     int predictor;
  105.     // TTN2 JPEG related variables
  106.     JPEGDecodeParam decodeParam = null;
  107.     boolean colorConvertJPEG = false;
  108.     // DEFLATE variables
  109.     Inflater inflater = null;
  110.     // Endian-ness indicator
  111.     boolean isBigEndian;
  112.     
  113.     int imageType;
  114.     boolean isWhiteZero = false;
  115.     int dataType;
  116.     boolean decodePaletteAsShorts;
  117.     // Decoders
  118.     private TIFFFaxDecoder decoder = null;
  119.     private TIFFLZWDecoder lzwDecoder = null;
  120.     /**
  121.      * Decode a buffer of data into a Raster with the specified location.
  122.      *
  123.      * @param data buffer contain an interchange or abbreviated datastream.
  124.      * @param decodeParam decoding parameters; may be null unless the
  125.      *        data buffer contains an abbreviated datastream in which case
  126.      *        it may not be null or an error will occur.
  127.      * @param colorConvert whether to perform color conversion; in this
  128.      *        case that would be limited to YCbCr-to-RGB.
  129.      * @param minX the X position of the returned Raster.
  130.      * @param minY the Y position of the returned Raster.
  131.      */
  132.     private static final Raster decodeJPEG(byte[] data,
  133.                                            JPEGDecodeParam decodeParam,
  134.                                            boolean colorConvert,
  135.                                            int minX,
  136.                                            int minY) {
  137.         // Create an InputStream from the compressed data array.
  138.         ByteArrayInputStream jpegStream = new ByteArrayInputStream(data);
  139.         // Create a decoder.
  140.         JPEGImageDecoder decoder = decodeParam == null ?
  141.             JPEGCodec.createJPEGDecoder(jpegStream) :
  142.             JPEGCodec.createJPEGDecoder(jpegStream,
  143.                                         decodeParam);
  144.         // Decode the compressed data into a Raster.
  145.         Raster jpegRaster;
  146.         try {
  147.             jpegRaster = colorConvert ?
  148.                 decoder.decodeAsBufferedImage().getWritableTile(0, 0) :
  149.                 decoder.decodeAsRaster();
  150.         } catch (IOException ioe) {
  151.             throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
  152.         }
  153.         // Translate the decoded Raster to the specified location and return.
  154.         return jpegRaster.createTranslatedChild(minX, minY);
  155.     }
  156.     /**
  157.      * Inflates <code>deflated</code> into <code>inflated</code> using the
  158.      * <code>Inflater</code> constructed during class instantiation.
  159.      */
  160.     private final void inflate(byte[] deflated, byte[] inflated) {
  161.         inflater.setInput(deflated);
  162.         try {
  163.             inflater.inflate(inflated);
  164.         } catch(DataFormatException dfe) {
  165.             throw new RuntimeException(JaiI18N.getString("TIFFImage17")+": "+
  166.                                        dfe.getMessage());
  167.         }
  168.         inflater.reset();
  169.     }
  170.     /**
  171.      * Creates a pixel-interleaved <code>SampleModel</code>. This is a hack
  172.      * to work around a cast exception when using JAI with float data.
  173.      */
  174.     private final static SampleModel
  175.         createPixelInterleavedSampleModel(int dataType,
  176.                                           int tileWidth,
  177.                                           int tileHeight,
  178.                                           int pixelStride,
  179.                                           int scanlineStride,
  180.                                           int bandOffsets[]) {
  181.         SampleModel sampleModel = null;
  182.         if(dataType == DataBuffer.TYPE_FLOAT) {
  183.             // This is a hack to make this work with JAI which in some
  184.             // cases downcasts the DataBuffer to a type-specific class.
  185.             // In the case of float data this current means the JAI class
  186.             // javax.media.jai.DataBufferFloat.
  187.             try {
  188.                 Class rfClass =
  189.                     Class.forName("javax.media.jai.RasterFactory");
  190.                 Class[] paramTypes = new Class[] {int.class, int.class, 
  191.                                                   int.class, int.class,
  192.                                                   int.class, int[].class};
  193.                 Method rfMthd =
  194.                     rfClass.getMethod("createPixelInterleavedSampleModel",
  195.                                       paramTypes);
  196.                 Object[] params =
  197.                     new Object[] {new Integer(dataType),
  198.                                   new Integer(tileWidth),
  199.                                   new Integer(tileHeight),
  200.                                   new Integer(pixelStride),
  201.                                   new Integer(scanlineStride),
  202.                                   bandOffsets};
  203.                 sampleModel = (SampleModel)rfMthd.invoke(null, params);
  204.             } catch(Exception e) {
  205.                 // Deliberately ignore the Exception.
  206.             }
  207.         }
  208.         // Create a SampleModel for non-float data or, in the case of
  209.         // float data, if it is still null. This latter case should occur
  210.         // if and only if the decoder is being used without JAI.
  211.         if(dataType != DataBuffer.TYPE_FLOAT || sampleModel == null) {
  212.             sampleModel =
  213.                 RasterFactory.createPixelInterleavedSampleModel(dataType,
  214.                                                                 tileWidth,
  215.                                                                 tileHeight,
  216.                                                                 pixelStride,
  217.                                                                 scanlineStride,
  218.                                                                 bandOffsets);
  219.         }
  220.         return sampleModel;
  221.     }
  222.     /**
  223.      * Return as a long[] the value of a TIFF_LONG or TIFF_SHORT field.
  224.      */
  225.     private final long[] getFieldAsLongs(TIFFField field) {
  226.         long[] value = null;
  227.         if(field.getType() == TIFFField.TIFF_SHORT) {
  228.             char[] charValue = field.getAsChars();
  229.             value = new long[charValue.length];
  230.             for(int i = 0; i < charValue.length; i++) {
  231.                 value[i] = charValue[i]  & 0xffff;
  232.             }
  233.         } else if(field.getType() == TIFFField.TIFF_LONG) {
  234.             value = field.getAsLongs();
  235.         } else {
  236.             throw new RuntimeException();
  237.         }
  238.         return value;
  239.     }
  240.     /**
  241.      * Constructs a TIFFImage that acquires its data from a given
  242.      * SeekableStream and reads from a particular IFD of the stream.
  243.      * The index of the first IFD is 0.
  244.      *
  245.      * @param stream the SeekableStream to read from.
  246.      * @param param an instance of TIFFDecodeParam, or null.
  247.      * @param directory the index of the IFD to read from.
  248.      */
  249.     public TIFFImage(SeekableStream stream,
  250.                      TIFFDecodeParam param,
  251.                      int directory)
  252.         throws IOException {
  253.         this.stream = stream;
  254. if (param == null) {
  255.     param = new TIFFDecodeParam();
  256. decodePaletteAsShorts = param.getDecodePaletteAsShorts();
  257.         // Read the specified directory.
  258.         TIFFDirectory dir = param.getIFDOffset() == null ?
  259.             new TIFFDirectory(stream, directory) :
  260.             new TIFFDirectory(stream, param.getIFDOffset().longValue(),
  261.                               directory);
  262.         // Set a property "tiff_directory".
  263.         properties.put("tiff_directory", dir);
  264. // Get the number of samples per pixel
  265. TIFFField sfield = dir.getField(TIFFImageDecoder.TIFF_SAMPLES_PER_PIXEL);
  266.         int samplesPerPixel = sfield == null ? 1 : (int)sfield.getAsLong(0);
  267. // Read the TIFF_PLANAR_CONFIGURATION field
  268. TIFFField planarConfigurationField = 
  269.     dir.getField(TIFFImageDecoder.TIFF_PLANAR_CONFIGURATION);
  270. char[] planarConfiguration = planarConfigurationField == null ?
  271.             new char[] {1} :
  272.             planarConfigurationField.getAsChars();
  273.         // Support planar format (band sequential) only for 1 sample/pixel.
  274.         if (planarConfiguration[0] != 1 && samplesPerPixel != 1) {
  275.             throw new RuntimeException(JaiI18N.getString("TIFFImage0"));
  276.         }
  277. // Read the TIFF_BITS_PER_SAMPLE field
  278. TIFFField bitsField = 
  279.     dir.getField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE);
  280.         char[] bitsPerSample = null;
  281.         if(bitsField != null) {
  282.             bitsPerSample = bitsField.getAsChars();
  283.         } else {
  284.             bitsPerSample = new char[] {1};
  285.             // Ensure that all samples have the same bit depth.
  286.             for (int i = 1; i < bitsPerSample.length; i++) {
  287.                 if (bitsPerSample[i] != bitsPerSample[0]) {
  288.                     throw new RuntimeException(JaiI18N.getString("TIFFImage1"));
  289.                 }
  290.             }
  291.         }
  292.         sampleSize = (int)bitsPerSample[0];
  293. // Read the TIFF_SAMPLE_FORMAT tag to see whether the data might be
  294. // signed or floating point
  295. TIFFField sampleFormatField = 
  296.     dir.getField(TIFFImageDecoder.TIFF_SAMPLE_FORMAT);
  297.         char[] sampleFormat = null;
  298. if (sampleFormatField != null) {
  299.     sampleFormat = sampleFormatField.getAsChars();
  300.     // Check that all the samples have the same format
  301.     for (int l=1; l<sampleFormat.length; l++) {
  302. if (sampleFormat[l] != sampleFormat[0]) {
  303.     throw new RuntimeException(JaiI18N.getString("TIFFImage2"));
  304. }
  305.     }
  306. } else {
  307.     sampleFormat = new char[] {1};
  308. }
  309.         // Set the data type based on the sample size and format.
  310.         boolean isValidDataFormat = false;
  311.         switch(sampleSize) {
  312.         case 1:
  313.         case 4:
  314.         case 8:
  315.             if(sampleFormat[0] != 3) {
  316.                 // Ignore whether signed or unsigned: treat all as unsigned.
  317. dataType = DataBuffer.TYPE_BYTE;
  318.                 isValidDataFormat = true;
  319.             }
  320.             break;
  321.         case 16:
  322.             if(sampleFormat[0] != 3) {
  323.                 dataType = sampleFormat[0] == 2 ?
  324.                     DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT;
  325.                 isValidDataFormat = true;
  326.             }
  327.             break;
  328.         case 32:
  329.             dataType = sampleFormat[0] == 3 ?
  330.                 DataBuffer.TYPE_FLOAT : DataBuffer.TYPE_INT;
  331.             isValidDataFormat = true;
  332.             break;
  333.         }
  334.         if(!isValidDataFormat) {
  335.             throw new RuntimeException(JaiI18N.getString("TIFFImage3"));
  336.         }
  337. // Figure out what compression if any, is being used.
  338. TIFFField compField = dir.getField(TIFFImageDecoder.TIFF_COMPRESSION);
  339.         compression = compField == null ? COMP_NONE : compField.getAsInt(0);
  340.         // Get the photometric interpretation.
  341. int photometricType = (int)dir.getFieldAsLong(
  342.       TIFFImageDecoder.TIFF_PHOTOMETRIC_INTERPRETATION);
  343. // Determine which kind of image we are dealing with.
  344.         imageType = TYPE_UNSUPPORTED;
  345. switch(photometricType) {
  346.         case 0: // WhiteIsZero
  347.             isWhiteZero = true;
  348.         case 1: // BlackIsZero
  349.             if(sampleSize == 1 && samplesPerPixel == 1) {
  350.                 imageType = TYPE_BILEVEL;
  351.             } else if(sampleSize == 4 && samplesPerPixel == 1) {
  352.                 imageType = TYPE_GRAY_4BIT;
  353.             } else if(sampleSize % 8 == 0) {
  354.                 if(samplesPerPixel == 1) {
  355.                     imageType = TYPE_GRAY;
  356.                 } else if(samplesPerPixel == 2) {
  357.                     imageType = TYPE_GRAY_ALPHA;
  358.                 } else {
  359.                     imageType = TYPE_GENERIC;
  360.                 }
  361.             }
  362.             break;
  363.         case 2: // RGB
  364.             if(sampleSize % 8 == 0) {
  365.                 if(samplesPerPixel == 3) {
  366.                     imageType = TYPE_RGB;
  367.                 } else if(samplesPerPixel == 4) {
  368.                     imageType = TYPE_RGB_ALPHA;
  369.                 } else {
  370.                     imageType = TYPE_GENERIC;
  371.                 }
  372.             }
  373.             break;
  374.         case 3: // RGB Palette
  375.             if(samplesPerPixel == 1 &&
  376.                (sampleSize == 4 || sampleSize == 8 || sampleSize == 16)) {
  377.                 imageType = TYPE_PALETTE;
  378.             }
  379.             break;
  380.         case 4: // Transparency mask
  381.             if(sampleSize == 1 && samplesPerPixel == 1) {
  382.                 imageType = TYPE_BILEVEL;
  383.             }
  384.             break;
  385.         case 6: // YCbCr
  386.             if(compression == COMP_JPEG_TTN2 &&
  387.                sampleSize == 8 && samplesPerPixel == 3) {
  388.                 // Set color conversion flag.
  389.                 colorConvertJPEG = param.getJPEGDecompressYCbCrToRGB();
  390.                 // Set type to RGB if color converting.
  391.                 imageType = colorConvertJPEG ? TYPE_RGB : TYPE_GENERIC;
  392.             } else {
  393.                 TIFFField chromaField = dir.getField(TIFF_YCBCR_SUBSAMPLING);
  394.                 if(chromaField != null) {
  395.                     chromaSubH = chromaField.getAsInt(0);
  396.                     chromaSubV = chromaField.getAsInt(1);
  397.                 } else {
  398.                     chromaSubH = chromaSubV = 2;
  399.                 }
  400.                 if(chromaSubH*chromaSubV == 1) {
  401.                     imageType = TYPE_GENERIC;
  402.                 } else if(sampleSize == 8 && samplesPerPixel == 3) {
  403.                     imageType = TYPE_YCBCR_SUB;
  404.                 }
  405.             }
  406.             break;
  407.         default: // Other including CMYK, CIE L*a*b*, unknown.
  408.             if(sampleSize % 8 == 0) {
  409.                 imageType = TYPE_GENERIC;
  410.             }
  411.         }
  412.         // Bail out if not one of the supported types.
  413.         if(imageType == TYPE_UNSUPPORTED) {
  414.             throw new RuntimeException(JaiI18N.getString("TIFFImage4"));
  415.         }
  416. // Set basic image layout        
  417.         minX = minY = 0;
  418.         width = (int)dir.getFieldAsLong(TIFFImageDecoder.TIFF_IMAGE_WIDTH);
  419.         height = (int)dir.getFieldAsLong(TIFFImageDecoder.TIFF_IMAGE_LENGTH);
  420.         // Set a preliminary band count. This may be changed later as needed.
  421.         numBands = samplesPerPixel;
  422. // Figure out if any extra samples are present.
  423. TIFFField efield = dir.getField(TIFFImageDecoder.TIFF_EXTRA_SAMPLES);
  424.         int extraSamples = efield == null ? 0 : (int)efield.getAsLong(0);
  425. if (dir.getField(TIFFImageDecoder.TIFF_TILE_OFFSETS) != null) {
  426.     // Image is in tiled format
  427.             tileWidth = 
  428. (int)dir.getFieldAsLong(TIFFImageDecoder.TIFF_TILE_WIDTH);
  429.             tileHeight = 
  430. (int)dir.getFieldAsLong(TIFFImageDecoder.TIFF_TILE_LENGTH);
  431.     tileOffsets = 
  432. (dir.getField(TIFFImageDecoder.TIFF_TILE_OFFSETS)).getAsLongs();
  433.     tileByteCounts = 
  434.        getFieldAsLongs(dir.getField(TIFFImageDecoder.TIFF_TILE_BYTE_COUNTS));
  435.         } else {
  436.             // Image is in stripped format, looks like tiles to us
  437.             // Note: Some legacy files may have tile width and height
  438.             // written but use the strip offsets and byte counts fields
  439.             // instead of the tile offsets and byte counts. Therefore
  440.             // we default here to the tile dimensions if they are written.
  441.             tileWidth =
  442.                 dir.getField(TIFFImageDecoder.TIFF_TILE_WIDTH) != null ?
  443.                 (int)dir.getFieldAsLong(TIFFImageDecoder.TIFF_TILE_WIDTH) :
  444.                 width;
  445.     TIFFField field =
  446.                 dir.getField(TIFFImageDecoder.TIFF_ROWS_PER_STRIP);
  447.     if (field == null) {
  448. // Default is infinity (2^32 -1), basically the entire image
  449. tileHeight =
  450.                     dir.getField(TIFFImageDecoder.TIFF_TILE_LENGTH) != null ?
  451.                     (int)dir.getFieldAsLong(TIFFImageDecoder.TIFF_TILE_LENGTH):
  452.                     height;
  453.     } else {
  454. long l = field.getAsLong(0);
  455. long infinity = 1;
  456. infinity = (infinity << 32) - 1;
  457. if (l == infinity) {   
  458.     // 2^32 - 1 (effectively infinity, entire image is 1 strip)
  459.     tileHeight = height;
  460. } else {
  461.     tileHeight = (int)l;
  462. }
  463.     }
  464.     TIFFField tileOffsetsField = 
  465. dir.getField(TIFFImageDecoder.TIFF_STRIP_OFFSETS);
  466.     if (tileOffsetsField == null) {
  467. throw new RuntimeException(JaiI18N.getString("TIFFImage5"));
  468.     } else {
  469. tileOffsets = getFieldAsLongs(tileOffsetsField);
  470.     }
  471.     TIFFField tileByteCountsField = 
  472. dir.getField(TIFFImageDecoder.TIFF_STRIP_BYTE_COUNTS);
  473.     if (tileByteCountsField == null) {
  474. throw new RuntimeException(JaiI18N.getString("TIFFImage6"));
  475.     } else {
  476. tileByteCounts = getFieldAsLongs(tileByteCountsField);
  477.     }
  478. }
  479. // Calculate number of tiles and the tileSize in bytes
  480.         tilesX = (width + tileWidth - 1)/tileWidth;
  481.         tilesY = (height + tileHeight - 1)/tileHeight;
  482.         tileSize = tileWidth * tileHeight * numBands;
  483. // Check whether big endian or little endian format is used.
  484. isBigEndian = dir.isBigEndian();
  485. TIFFField fillOrderField = 
  486.     dir.getField(TIFFImageDecoder.TIFF_FILL_ORDER);
  487. if (fillOrderField != null) {
  488.     fillOrder = fillOrderField.getAsInt(0);
  489. } else {
  490.     // Default Fill Order
  491.     fillOrder = 1;
  492. }
  493. switch(compression) {
  494.         case COMP_NONE:
  495.         case COMP_PACKBITS:
  496.             // Do nothing.
  497.             break;
  498.         case COMP_DEFLATE:
  499.             inflater = new Inflater();
  500.             break;
  501.         case COMP_FAX_G3_1D:
  502.         case COMP_FAX_G3_2D:
  503.         case COMP_FAX_G4_2D:
  504.             if(sampleSize != 1) {
  505.                 throw new RuntimeException(JaiI18N.getString("TIFFImage7")); 
  506.             }
  507.             // Fax T.4 compression options
  508.             if (compression == 3) {
  509.                 TIFFField t4OptionsField = 
  510.                     dir.getField(TIFFImageDecoder.TIFF_T4_OPTIONS);
  511.                 if (t4OptionsField != null) {
  512.                     tiffT4Options = t4OptionsField.getAsLong(0);
  513.                 } else {
  514.                     // Use default value
  515.                     tiffT4Options = 0;
  516.                 }
  517.             }
  518.             // Fax T.6 compression options
  519.             if (compression == 4) {
  520.                 TIFFField t6OptionsField =
  521.                     dir.getField(TIFFImageDecoder.TIFF_T6_OPTIONS);
  522.                 if (t6OptionsField != null) {
  523.                     tiffT6Options = t6OptionsField.getAsLong(0);
  524.                 } else {
  525.                     // Use default value
  526.                     tiffT6Options = 0;
  527.                 }
  528.             }
  529.             // Fax encoding, need to create the Fax decoder.
  530.             decoder = new TIFFFaxDecoder(fillOrder,
  531.                                          tileWidth, tileHeight);
  532.             break;
  533.         case COMP_LZW:
  534.             // LZW compression used, need to create the LZW decoder.
  535.             TIFFField predictorField = 
  536.                 dir.getField(TIFFImageDecoder.TIFF_PREDICTOR);
  537.             if (predictorField == null) {
  538.                 predictor = 1;
  539.             } else {
  540.                 predictor = predictorField.getAsInt(0);
  541.     
  542.                 if (predictor != 1 && predictor != 2) {
  543.                     throw new RuntimeException(JaiI18N.getString("TIFFImage8")); 
  544.                 }
  545.     
  546.                 if (predictor == 2 && sampleSize != 8) {
  547.                     throw new RuntimeException(sampleSize + 
  548.                                                JaiI18N.getString("TIFFImage9"));
  549.                 }
  550.             }
  551.             lzwDecoder = new TIFFLZWDecoder(tileWidth, predictor, 
  552.                                             samplesPerPixel); 
  553.             break;
  554.         case COMP_JPEG_OLD:
  555.             throw new RuntimeException(JaiI18N.getString("TIFFImage15"));
  556.         case COMP_JPEG_TTN2:
  557.             if(!(sampleSize == 8 &&
  558.                  ((imageType == TYPE_GRAY && samplesPerPixel == 1) ||
  559.                   (imageType == TYPE_PALETTE && samplesPerPixel == 1) ||
  560.                   (imageType == TYPE_RGB && samplesPerPixel == 3)))) {
  561.                 throw new RuntimeException(JaiI18N.getString("TIFFImage16"));
  562.             }
  563.             // Create decodeParam from JPEGTables field if present.
  564.             if(dir.isTagPresent(TIFF_JPEG_TABLES)) {
  565.                 TIFFField jpegTableField = dir.getField(TIFF_JPEG_TABLES);
  566.                 byte[] jpegTable = jpegTableField.getAsBytes();
  567.                 ByteArrayInputStream tableStream =
  568.                     new ByteArrayInputStream(jpegTable);
  569.                 JPEGImageDecoder decoder =
  570.                     JPEGCodec.createJPEGDecoder(tableStream);
  571.                 decoder.decodeAsRaster();
  572.                 decodeParam = decoder.getJPEGDecodeParam();
  573.             }
  574.             break;
  575.         default:
  576.             throw new RuntimeException(JaiI18N.getString("TIFFImage10"));
  577. }
  578.         switch(imageType) {
  579.         case TYPE_BILEVEL:
  580.         case TYPE_GRAY_4BIT:
  581.             sampleModel = 
  582.                 new MultiPixelPackedSampleModel(dataType,
  583.                                                 tileWidth, 
  584.                                                 tileHeight,
  585.                                                 sampleSize);
  586.             if(imageType == TYPE_BILEVEL) {
  587.                 byte[] map = new byte[] {(byte)(isWhiteZero ? 255 : 0),
  588.                                          (byte)(isWhiteZero ? 0 : 255)};
  589. colorModel = new IndexColorModel(1, 2, map, map, map);
  590.             } else {
  591.                 colorModel = 
  592.                     ImageCodec.createGrayIndexColorModel(sampleModel,
  593.                                                          !isWhiteZero);
  594.             }
  595.             break;
  596.         case TYPE_GRAY:
  597.         case TYPE_GRAY_ALPHA:
  598.         case TYPE_RGB:
  599.         case TYPE_RGB_ALPHA:
  600.             // Create a pixel interleaved SampleModel with decreasing
  601.             // band offsets.
  602.             int[] reverseOffsets = new int[numBands];
  603.             for (int i=0; i<numBands; i++) {
  604.                 reverseOffsets[i] = numBands - 1 - i;
  605.             }
  606.             sampleModel = createPixelInterleavedSampleModel(dataType,
  607.                                                             tileWidth,
  608.                                                             tileHeight,
  609.                                                             numBands,
  610.                                                             numBands*tileWidth,
  611.                                                             reverseOffsets);
  612.             if(imageType == TYPE_GRAY || imageType == TYPE_RGB) {
  613.                 colorModel =
  614.                     ImageCodec.createComponentColorModel(sampleModel);
  615.             } else { // hasAlpha
  616.                 // Transparency.OPAQUE signifies image data that is 
  617.                 // completely opaque, meaning that all pixels have an alpha
  618.                 // value of 1.0. So the extra band gets ignored, which is
  619.                 // what we want.
  620.                 int transparency = Transparency.OPAQUE;
  621.                 if(extraSamples == 1) { // associated (premultiplied) alpha
  622.                     transparency = Transparency.TRANSLUCENT;
  623.                 } else if(extraSamples == 2) { // unassociated alpha
  624.                     transparency = Transparency.BITMASK;
  625.                 }
  626.                 colorModel =
  627.                     createAlphaComponentColorModel(dataType,
  628.                                                    numBands,
  629.                                                    extraSamples == 1,
  630.    transparency);
  631.             }
  632.             break;
  633.         case TYPE_GENERIC:
  634.         case TYPE_YCBCR_SUB:
  635.             // For this case we can't display the image, so we create a
  636.             // SampleModel with increasing bandOffsets, and keep the
  637.             // ColorModel as null, as there is no appropriate ColorModel.
  638.             int[] bandOffsets = new int[numBands];
  639.             for (int i=0; i<numBands; i++) {
  640.                 bandOffsets[i] = i;
  641.             }
  642.             sampleModel =
  643.                 createPixelInterleavedSampleModel(dataType,
  644.                                                   tileWidth, tileHeight,
  645.                                                   numBands, numBands * tileWidth,
  646.                                                   bandOffsets);
  647.             colorModel = null;
  648.             break;
  649.         case TYPE_PALETTE:
  650.     // Get the colormap
  651.     TIFFField cfield = dir.getField(TIFFImageDecoder.TIFF_COLORMAP);
  652.     if (cfield == null) {
  653. throw new RuntimeException(JaiI18N.getString("TIFFImage11"));
  654.     } else {
  655. colormap = cfield.getAsChars();
  656.     }
  657.     // Could be either 1 or 3 bands depending on whether we use
  658.     // IndexColorModel or not.
  659.     if (decodePaletteAsShorts) {
  660. numBands = 3;
  661. // If no SampleFormat tag was specified and if the 
  662. // sampleSize is less than or equal to 8, then the 
  663. // dataType was initially set to byte, but now we want to 
  664. // expand the palette as shorts, so the dataType should 
  665. // be ushort.
  666. if (dataType == DataBuffer.TYPE_BYTE) {
  667.     dataType = DataBuffer.TYPE_USHORT;
  668. }
  669. // Data will have to be unpacked into a 3 band short image
  670. // as we do not have a IndexColorModel that can deal with
  671. // a colormodel whose entries are of short data type.
  672. sampleModel = 
  673.     RasterFactory.createPixelInterleavedSampleModel(dataType,
  674.     tileWidth,
  675.     tileHeight, 
  676.     numBands);
  677. colorModel = ImageCodec.createComponentColorModel(sampleModel);
  678.     } else {
  679. numBands = 1;
  680. if (sampleSize == 4) {
  681.     // Pixel data will not be unpacked, will use MPPSM to store 
  682.     // packed data and IndexColorModel to do the unpacking.
  683.     sampleModel = 
  684. new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, 
  685. tileWidth, 
  686. tileHeight, 
  687. sampleSize);
  688. } else if (sampleSize == 8) {
  689.     sampleModel =
  690. RasterFactory.createPixelInterleavedSampleModel(
  691.     DataBuffer.TYPE_BYTE,
  692.     tileWidth,
  693.     tileHeight,
  694.     numBands);
  695. } else if (sampleSize == 16) {
  696.     // Here datatype has to be unsigned since we are storing
  697.     // indices into the IndexColorModel palette. Ofcourse
  698.     // the actual palette entries are allowed to be negative.
  699.                     dataType = DataBuffer.TYPE_USHORT;
  700.     sampleModel =
  701. RasterFactory.createPixelInterleavedSampleModel(
  702. DataBuffer.TYPE_USHORT,
  703. tileWidth,
  704. tileHeight,
  705. numBands);
  706. }
  707. int bandLength = colormap.length/3;
  708. byte r[] = new byte[bandLength];
  709. byte g[] = new byte[bandLength];
  710. byte b[] = new byte[bandLength];
  711. int gIndex = bandLength;
  712. int bIndex = bandLength * 2;
  713. if (dataType == DataBuffer.TYPE_SHORT) {
  714.     for (int i=0; i<bandLength; i++) {
  715. r[i] = param.decodeSigned16BitsTo8Bits(
  716.        (short)colormap[i]);
  717. g[i] = param.decodeSigned16BitsTo8Bits(
  718.      (short)colormap[gIndex+i]);
  719. b[i] = param.decodeSigned16BitsTo8Bits(
  720.      (short)colormap[bIndex+i]);
  721.     }
  722. } else {
  723.     for (int i=0; i<bandLength; i++) {
  724. r[i] = param.decode16BitsTo8Bits(colormap[i] & 0xffff);
  725. g[i] = param.decode16BitsTo8Bits(colormap[gIndex+i] & 
  726.  0xffff);
  727. b[i] = param.decode16BitsTo8Bits(colormap[bIndex+i] & 
  728.  0xffff);
  729.     }
  730.     
  731. }
  732. colorModel = new IndexColorModel(sampleSize, 
  733.  bandLength, r, g, b);
  734.     }
  735.             break;
  736.         default:
  737.             throw new RuntimeException("TIFFImage4");
  738.         }
  739.     }
  740.     /**
  741.      * Reads a private IFD from a given offset in the stream.  This
  742.      * method may be used to obtain IFDs that are referenced
  743.      * only by private tag values.
  744.      */
  745.     public TIFFDirectory getPrivateIFD(long offset) throws IOException {
  746.         return new TIFFDirectory(stream, offset, 0);
  747.     }
  748.     /**
  749.      * Returns tile (tileX, tileY) as a Raster.
  750.      */
  751.     public synchronized Raster getTile(int tileX, int tileY) {
  752.         if ((tileX < 0) || (tileX >= tilesX) ||
  753.             (tileY < 0) || (tileY >= tilesY)) {
  754.             throw new IllegalArgumentException(JaiI18N.getString("TIFFImage12"));
  755.         }
  756. // Get the data array out of the DataBuffer
  757. byte bdata[] = null;
  758. short sdata[] = null;
  759. int idata[] = null;
  760. float fdata[] = null;
  761. DataBuffer buffer = sampleModel.createDataBuffer();
  762. int dataType = sampleModel.getDataType();
  763. if (dataType == DataBuffer.TYPE_BYTE) {
  764.     bdata = ((DataBufferByte)buffer).getData();
  765. } else if (dataType == DataBuffer.TYPE_USHORT) {
  766.     sdata = ((DataBufferUShort)buffer).getData();
  767. } else if (dataType == DataBuffer.TYPE_SHORT) {
  768.     sdata = ((DataBufferShort)buffer).getData();
  769. } else if (dataType == DataBuffer.TYPE_INT) {
  770.     idata = ((DataBufferInt)buffer).getData();
  771. } else if (dataType == DataBuffer.TYPE_FLOAT) {
  772.             if(buffer instanceof DataBufferFloat) {
  773.                 fdata = ((DataBufferFloat)buffer).getData();
  774.             } else {
  775.                 // This is a hack to make this work with JAI which in some
  776.                 // cases downcasts the DataBuffer to a type-specific class.
  777.                 // In the case of float data this current means the JAI class
  778.                 // javax.media.jai.DataBufferFloat.
  779.                 try {
  780.                     Method getDataMethod =
  781.                         buffer.getClass().getMethod("getData", null);
  782.                     fdata = (float[])getDataMethod.invoke(buffer, null);
  783.                 } catch(Exception e) {
  784.                     throw new RuntimeException(JaiI18N.getString("TIFFImage18"));
  785.                 }
  786.             }
  787. }
  788.         WritableRaster tile = 
  789.     (WritableRaster)RasterFactory.createWritableRaster(sampleModel,
  790.                                                    buffer,
  791.                                                    new Point(tileXToX(tileX),
  792.                                                              tileYToY(tileY)));
  793. // Variables used for swapping when converting from RGB to BGR
  794. byte bswap;
  795. short sswap;
  796.         int iswap;
  797.         float fswap;
  798. // Save original file pointer position and seek to tile data location.
  799. long save_offset = 0;
  800. try {
  801.     save_offset = stream.getFilePointer();
  802.     stream.seek(tileOffsets[tileY*tilesX + tileX]);
  803. } catch (IOException ioe) {
  804.     throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
  805. }
  806. // Number of bytes in this tile (strip) after compression.
  807. int byteCount = (int)tileByteCounts[tileY*tilesX + tileX];
  808. // Find out the number of bytes in the current tile
  809. Rectangle tileRect = new Rectangle(tileXToX(tileX), tileYToY(tileY),
  810.    tileWidth, tileHeight);
  811. Rectangle newRect = tileRect.intersection(getBounds());
  812.         int unitsInThisTile = newRect.width * newRect.height * numBands;
  813.         // Allocate read buffer if needed.
  814. byte data[] = compression != COMP_NONE || imageType == TYPE_PALETTE ?
  815.             new byte[byteCount] : null;
  816.         // Read the data, uncompressing as needed. There are four cases:
  817.         // bilevel, palette-RGB, 4-bit grayscale, and everything else.
  818.         if(imageType == TYPE_BILEVEL) { // bilevel
  819.     try {
  820. if (compression == COMP_PACKBITS) {
  821.     stream.readFully(data, 0, byteCount);
  822.     // Since the decompressed data will still be packed 
  823.     // 8 pixels into 1 byte, calculate bytesInThisTile
  824.     int bytesInThisTile;
  825.     if ((newRect.width % 8) == 0) {
  826. bytesInThisTile = (newRect.width/8) * newRect.height;
  827.     } else {
  828. bytesInThisTile =
  829.                             (newRect.width/8 + 1) * newRect.height;
  830.     }
  831.     decodePackbits(data, bytesInThisTile, bdata);
  832. } else if (compression == COMP_LZW) {
  833.     stream.readFully(data, 0, byteCount);
  834.     lzwDecoder.decode(data, bdata, newRect.height);
  835. } else if (compression == COMP_FAX_G3_1D) {
  836.     stream.readFully(data, 0, byteCount);
  837.     decoder.decode1D(bdata, data, 0, newRect.height);
  838. } else if (compression == COMP_FAX_G3_2D) {
  839.     stream.readFully(data, 0, byteCount);
  840.     decoder.decode2D(bdata, data, 0, newRect.height,
  841.                                      tiffT4Options);
  842. } else if (compression == COMP_FAX_G4_2D) {
  843.     stream.readFully(data, 0, byteCount);
  844.                     decoder.decodeT6(bdata, data, 0, newRect.height,
  845.                                      tiffT6Options);
  846. } else if (compression == COMP_DEFLATE) {
  847.                     stream.readFully(data, 0, byteCount);
  848.                     inflate(data, bdata);
  849. } else if (compression == COMP_NONE) {
  850.     stream.readFully(bdata, 0, byteCount);
  851. }
  852. stream.seek(save_offset);
  853.     } catch (IOException ioe) {
  854. throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
  855.     }
  856.         } else if(imageType == TYPE_PALETTE) { // palette-RGB
  857.     if (sampleSize == 16) {
  858. if (decodePaletteAsShorts) {
  859.     
  860.     short tempData[]= null;
  861.          
  862.     // At this point the data is 1 banded and will
  863.     // become 3 banded only after we've done the palette
  864.     // lookup, since unitsInThisTile was calculated with
  865.     // 3 bands, we need to divide this by 3.
  866.     int unitsBeforeLookup = unitsInThisTile / 3;
  867.     
  868.     // Since unitsBeforeLookup is the number of shorts, 
  869.     // but we do our decompression in terms of bytes, we 
  870.     // need to multiply it by 2 in order to figure out
  871.     // how many bytes we'll get after decompression.
  872.     int entries = unitsBeforeLookup * 2;
  873.     
  874.     // Read the data, if compressed, decode it, reset the pointer
  875.     try {
  876. if (compression == COMP_PACKBITS) {
  877.     stream.readFully(data, 0, byteCount);
  878.     
  879.     byte byteArray[] = new byte[entries];
  880.     decodePackbits(data, entries, byteArray);
  881.     tempData = new short[unitsBeforeLookup];
  882.     interpretBytesAsShorts(byteArray, tempData,
  883.    unitsBeforeLookup);
  884.     
  885. }  else if (compression == COMP_LZW) {
  886.     // Read in all the compressed data for this tile
  887.     stream.readFully(data, 0, byteCount);
  888.     byte byteArray[] = new byte[entries];
  889.     lzwDecoder.decode(data, byteArray, newRect.height);
  890.     tempData = new short[unitsBeforeLookup];
  891.     interpretBytesAsShorts(byteArray, tempData,
  892.    unitsBeforeLookup);
  893. }  else if (compression == COMP_DEFLATE) {
  894.     stream.readFully(data, 0, byteCount);
  895.     byte byteArray[] = new byte[entries];
  896.     inflate(data, byteArray);
  897.     tempData = new short[unitsBeforeLookup];
  898.     interpretBytesAsShorts(byteArray, tempData,
  899.    unitsBeforeLookup);
  900. } else if (compression == COMP_NONE) {
  901.     // byteCount tells us how many bytes are there
  902.     // in this tile, but we need to read in shorts, 
  903.     // which will take half the space, so while
  904.     // allocating we divide byteCount by 2.
  905.     tempData = new short[byteCount/2];
  906.     readShorts(byteCount/2, tempData);
  907. }
  908. stream.seek(save_offset);
  909.     } catch (IOException ioe) {
  910. throw new RuntimeException(
  911. JaiI18N.getString("TIFFImage13"));
  912.     }
  913.     if (dataType == DataBuffer.TYPE_USHORT) {
  914. // Expand the palette image into an rgb image with ushort
  915. // data type.
  916. int cmapValue; 
  917. int count = 0, lookup, len = colormap.length/3;
  918. int len2 = len * 2;
  919. for (int i=0; i<unitsBeforeLookup; i++) {
  920.     // Get the index into the colormap
  921.     lookup = tempData[i] & 0xffff;
  922.     // Get the blue value 
  923.     cmapValue = colormap[lookup+len2];
  924.     sdata[count++] = (short)(cmapValue & 0xffff);
  925.     // Get the green value
  926.     cmapValue = colormap[lookup+len];
  927.     sdata[count++] = (short)(cmapValue & 0xffff);
  928.     // Get the red value
  929.     cmapValue = colormap[lookup];
  930.     sdata[count++] = (short)(cmapValue & 0xffff);
  931. }
  932.     } else if (dataType == DataBuffer.TYPE_SHORT) {
  933. // Expand the palette image into an rgb image with 
  934. // short data type.
  935. int cmapValue; 
  936. int count = 0, lookup, len = colormap.length/3;
  937. int len2 = len * 2;
  938. for (int i=0; i<unitsBeforeLookup; i++) {
  939.     // Get the index into the colormap
  940.     lookup = tempData[i] & 0xffff;
  941.     // Get the blue value 
  942.     cmapValue = colormap[lookup+len2];
  943.     sdata[count++] = (short)cmapValue;
  944.     // Get the green value
  945.     cmapValue = colormap[lookup+len];
  946.     sdata[count++] = (short)cmapValue;
  947.     // Get the red value
  948.     cmapValue = colormap[lookup];
  949.     sdata[count++] = (short)cmapValue;
  950. }
  951.     }
  952. } else {
  953.     
  954.     // No lookup being done here, when RGB values are needed,
  955.     // the associated IndexColorModel can be used to get them.
  956.     
  957.     try {
  958. if (compression == COMP_PACKBITS) {
  959.     stream.readFully(data, 0, byteCount);
  960.     // Since unitsInThisTile is the number of shorts, 
  961.     // but we do our decompression in terms of bytes, we 
  962.     // need to multiply unitsInThisTile by 2 in order to 
  963.     // figure out how many bytes we'll get after 
  964.     // decompression.
  965.     int bytesInThisTile = unitsInThisTile * 2;
  966.     byte byteArray[] = new byte[bytesInThisTile];
  967.     decodePackbits(data, bytesInThisTile, byteArray);
  968.     interpretBytesAsShorts(byteArray, sdata,
  969.    unitsInThisTile);
  970.     
  971. } else if (compression == COMP_LZW) {
  972.     
  973.     stream.readFully(data, 0, byteCount);
  974.     // Since unitsInThisTile is the number of shorts, 
  975.     // but we do our decompression in terms of bytes, we 
  976.     // need to multiply unitsInThisTile by 2 in order to 
  977.     // figure out how many bytes we'll get after 
  978.     // decompression.
  979.     byte byteArray[] = new byte[unitsInThisTile * 2];
  980.     lzwDecoder.decode(data, byteArray, newRect.height);
  981.     interpretBytesAsShorts(byteArray, sdata, 
  982.    unitsInThisTile);
  983. }  else if (compression == COMP_DEFLATE) {
  984.     stream.readFully(data, 0, byteCount);
  985.     byte byteArray[] = new byte[unitsInThisTile * 2];
  986.     inflate(data, byteArray);
  987.     interpretBytesAsShorts(byteArray, sdata, 
  988.    unitsInThisTile);
  989. } else if (compression == COMP_NONE) {
  990.     readShorts(byteCount/2, sdata);
  991. }
  992. stream.seek(save_offset);
  993.     } catch (IOException ioe) {
  994. throw new RuntimeException(
  995. JaiI18N.getString("TIFFImage13"));
  996.     }     
  997. }
  998.     } else if (sampleSize == 8) {
  999. if (decodePaletteAsShorts) {
  1000.     
  1001.     byte tempData[]= null;
  1002.     // At this point the data is 1 banded and will
  1003.     // become 3 banded only after we've done the palette
  1004.     // lookup, since unitsInThisTile was calculated with
  1005.     // 3 bands, we need to divide this by 3.
  1006.     int unitsBeforeLookup = unitsInThisTile / 3;
  1007.     
  1008.     // Read the data, if compressed, decode it, reset the pointer
  1009.     try {
  1010. if (compression == COMP_PACKBITS) {
  1011.     
  1012.     stream.readFully(data, 0, byteCount);
  1013.     tempData = new byte[unitsBeforeLookup];
  1014.     decodePackbits(data, unitsBeforeLookup, tempData);
  1015.     
  1016. }  else if (compression == COMP_LZW) {
  1017.     
  1018.     stream.readFully(data, 0, byteCount);
  1019.     tempData = new byte[unitsBeforeLookup];
  1020.     lzwDecoder.decode(data, tempData, newRect.height);
  1021.     
  1022.                         } else if (compression == COMP_JPEG_TTN2) {
  1023.                             stream.readFully(data, 0, byteCount);
  1024.                             Raster tempTile = decodeJPEG(data,
  1025.                                                          decodeParam,
  1026.                                                          colorConvertJPEG,
  1027.                                                          tile.getMinX(),
  1028.                                                          tile.getMinY());
  1029.                             int[] tempPixels = new int[unitsBeforeLookup];
  1030.                             tempTile.getPixels(tile.getMinX(),
  1031.                                                tile.getMinY(),
  1032.                                                tile.getWidth(),
  1033.                                                tile.getHeight(),
  1034.                                                tempPixels);
  1035.     tempData = new byte[unitsBeforeLookup];
  1036.                             for(int i = 0; i < unitsBeforeLookup; i++) {
  1037.                                 tempData[i] = (byte)tempPixels[i];
  1038.                             }
  1039. }  else if (compression == COMP_DEFLATE) {
  1040.     stream.readFully(data, 0, byteCount);
  1041.     tempData = new byte[unitsBeforeLookup];
  1042.     inflate(data, tempData);
  1043. } else if (compression == COMP_NONE) {
  1044.     tempData = new byte[byteCount];
  1045.     stream.readFully(tempData, 0, byteCount);
  1046. }
  1047. stream.seek(save_offset);
  1048.     } catch (IOException ioe) {
  1049. throw new RuntimeException(
  1050. JaiI18N.getString("TIFFImage13"));
  1051.     }
  1052.     // Expand the palette image into an rgb image with ushort
  1053.     // data type.
  1054.     int cmapValue; 
  1055.     int count = 0, lookup, len = colormap.length/3;
  1056.     int len2 = len * 2;
  1057.     for (int i=0; i<unitsBeforeLookup; i++) {
  1058. // Get the index into the colormap
  1059. lookup = tempData[i] & 0xff;
  1060. // Get the blue value 
  1061. cmapValue = colormap[lookup+len2];
  1062. sdata[count++] = (short)(cmapValue & 0xffff);
  1063. // Get the green value
  1064. cmapValue = colormap[lookup+len];
  1065. sdata[count++] = (short)(cmapValue & 0xffff);
  1066. // Get the red value
  1067. cmapValue = colormap[lookup];
  1068. sdata[count++] = (short)(cmapValue & 0xffff);
  1069.     }
  1070. } else {
  1071.     
  1072.     // No lookup being done here, when RGB values are needed,
  1073.     // the associated IndexColorModel can be used to get them.
  1074.     
  1075.     try {
  1076. if (compression == COMP_PACKBITS) {
  1077.     
  1078.     stream.readFully(data, 0, byteCount);
  1079.     decodePackbits(data, unitsInThisTile, bdata);
  1080.     
  1081. } else if (compression == COMP_LZW) {
  1082.     
  1083.     stream.readFully(data, 0, byteCount);
  1084.     lzwDecoder.decode(data, bdata, newRect.height);
  1085.     
  1086.                         } else if (compression == COMP_JPEG_TTN2) {
  1087.                             stream.readFully(data, 0, byteCount);
  1088.                             tile.setRect(decodeJPEG(data,
  1089.                                                     decodeParam,
  1090.                                                     colorConvertJPEG,
  1091.                                                     tile.getMinX(),
  1092.                                                     tile.getMinY()));
  1093. }  else if (compression == COMP_DEFLATE) {
  1094.                             
  1095.                             stream.readFully(data, 0, byteCount);
  1096.                             inflate(data, bdata);
  1097. } else if (compression == COMP_NONE) {
  1098.     stream.readFully(bdata, 0, byteCount);
  1099. }
  1100. stream.seek(save_offset);
  1101.     } catch (IOException ioe) {
  1102. throw new RuntimeException(
  1103. JaiI18N.getString("TIFFImage13"));
  1104.     }     
  1105. }
  1106.     } else if (sampleSize == 4) {
  1107. int padding = (newRect.width % 2 == 0) ? 0 : 1;
  1108. int bytesPostDecoding = ((newRect.width/2 + padding) *
  1109.  newRect.height);
  1110. // Output short images
  1111. if (decodePaletteAsShorts) {
  1112.     
  1113.     byte tempData[] = null;
  1114.     try {
  1115. stream.readFully(data, 0, byteCount);
  1116. stream.seek(save_offset);
  1117.     } catch (IOException ioe) {
  1118. throw new RuntimeException(
  1119. JaiI18N.getString("TIFFImage13"));
  1120.     }
  1121.     
  1122.     // If compressed, decode the data.
  1123.     if (compression == COMP_PACKBITS) {
  1124. tempData = new byte[bytesPostDecoding];
  1125. decodePackbits(data, bytesPostDecoding, tempData);
  1126.     }  else if (compression == COMP_LZW) {
  1127. tempData = new byte[bytesPostDecoding];
  1128. lzwDecoder.decode(data, tempData, newRect.height);
  1129.                     }  else if (compression == COMP_DEFLATE) {
  1130. tempData = new byte[bytesPostDecoding];
  1131. inflate(data, tempData);
  1132.     } else if (compression == COMP_NONE) {
  1133. tempData = data;
  1134.     } 
  1135.     
  1136.     int bytes = unitsInThisTile / 3;
  1137.     
  1138.     // Unpack the 2 pixels packed into each byte.    
  1139.     data = new byte[bytes];
  1140.     
  1141.     int srcCount = 0, dstCount = 0;
  1142.     for (int j=0; j<newRect.height; j++) {
  1143. for (int i=0; i<newRect.width/2; i++) {
  1144.     data[dstCount++] = 
  1145. (byte)((tempData[srcCount] & 0xf0) >> 4);
  1146.     data[dstCount++] = 
  1147. (byte)(tempData[srcCount++] & 0x0f);
  1148. }
  1149.        
  1150. if (padding == 1) {
  1151.     data[dstCount++] = 
  1152. (byte)((tempData[srcCount++] & 0xf0) >> 4);
  1153. }
  1154.     }
  1155.     
  1156.     int len = colormap.length/3;
  1157.     int len2 = len*2;
  1158.     int cmapValue, lookup;
  1159.     int count = 0;
  1160.     for (int i=0; i<bytes; i++) {
  1161. lookup = data[i] & 0xff;
  1162. cmapValue = colormap[lookup+len2];
  1163. sdata[count++] = (short)(cmapValue & 0xffff);
  1164. cmapValue = colormap[lookup+len];
  1165. sdata[count++] = (short)(cmapValue & 0xffff);
  1166. cmapValue = colormap[lookup];
  1167. sdata[count++] = (short)(cmapValue & 0xffff);
  1168.     }
  1169. } else {
  1170.     
  1171.     // Output byte values, use IndexColorModel for unpacking
  1172.     try {
  1173. // If compressed, decode the data.
  1174. if (compression == COMP_PACKBITS) {
  1175.     
  1176.     stream.readFully(data, 0, byteCount);
  1177.     decodePackbits(data, bytesPostDecoding, bdata);
  1178.     
  1179. }  else if (compression == COMP_LZW) {
  1180.     
  1181.     stream.readFully(data, 0, byteCount);
  1182.     lzwDecoder.decode(data, bdata, newRect.height);
  1183.     
  1184.                         }  else if (compression == COMP_DEFLATE) {
  1185.     stream.readFully(data, 0, byteCount);
  1186.     inflate(data, bdata);
  1187. } else if (compression == COMP_NONE) {
  1188.     
  1189.     stream.readFully(bdata, 0, byteCount);
  1190. stream.seek(save_offset);
  1191.     } catch (IOException ioe) {
  1192. throw new RuntimeException(
  1193. JaiI18N.getString("TIFFImage13"));
  1194.     }
  1195. }
  1196.     }
  1197.         } else if(imageType == TYPE_GRAY_4BIT) { // 4-bit gray
  1198.             try {
  1199.                 if (compression == COMP_PACKBITS) {
  1200.                     stream.readFully(data, 0, byteCount);
  1201.                     // Since the decompressed data will still be packed 
  1202.                     // 2 pixels into 1 byte, calculate bytesInThisTile
  1203.                     int bytesInThisTile;
  1204.                     if ((newRect.width % 8) == 0) {
  1205.                         bytesInThisTile = (newRect.width/2) * newRect.height;
  1206.                     } else {
  1207.                         bytesInThisTile = (newRect.width/2 + 1) * 
  1208.                             newRect.height;
  1209.                     }
  1210.                     decodePackbits(data, bytesInThisTile, bdata);
  1211.                 } else if (compression == COMP_LZW) {
  1212.                     stream.readFully(data, 0, byteCount);
  1213.                     lzwDecoder.decode(data, bdata, newRect.height);
  1214.                 }  else if (compression == COMP_DEFLATE) {
  1215.                     stream.readFully(data, 0, byteCount);
  1216.                     inflate(data, bdata);
  1217.                 } else {
  1218.                     stream.readFully(bdata, 0, byteCount);
  1219.                 }
  1220.                 stream.seek(save_offset);
  1221.     } catch (IOException ioe) {
  1222. throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
  1223.     }
  1224.         } else { // everything else
  1225.     try {
  1226. if (sampleSize == 8) {
  1227.     
  1228.     if (compression == COMP_NONE) {
  1229. stream.readFully(bdata, 0, byteCount);
  1230.     } else if (compression == COMP_LZW) {
  1231. stream.readFully(data, 0, byteCount);
  1232. lzwDecoder.decode(data, bdata, newRect.height);
  1233.     } else if (compression == COMP_PACKBITS) {
  1234. stream.readFully(data, 0, byteCount);
  1235. decodePackbits(data, unitsInThisTile, bdata);
  1236.     } else if (compression == COMP_JPEG_TTN2) {
  1237. stream.readFully(data, 0, byteCount);
  1238.                         tile.setRect(decodeJPEG(data,
  1239.                                                 decodeParam,
  1240.                                                 colorConvertJPEG,
  1241.                                                 tile.getMinX(),
  1242.                                                 tile.getMinY()));
  1243.     } else if (compression == COMP_DEFLATE) {
  1244. stream.readFully(data, 0, byteCount);
  1245.                         inflate(data, bdata);
  1246.                     }
  1247.     
  1248. } else if (sampleSize == 16) {
  1249.     
  1250.     if (compression == COMP_NONE) {
  1251. readShorts(byteCount/2, sdata);
  1252.     } else if (compression == COMP_LZW) {
  1253. stream.readFully(data, 0, byteCount);
  1254. // Since unitsInThisTile is the number of shorts, 
  1255. // but we do our decompression in terms of bytes, we 
  1256. // need to multiply unitsInThisTile by 2 in order to 
  1257. // figure out how many bytes we'll get after 
  1258. // decompression.
  1259. byte byteArray[] = new byte[unitsInThisTile * 2];
  1260. lzwDecoder.decode(data, byteArray, newRect.height);
  1261. interpretBytesAsShorts(byteArray, sdata, 
  1262.        unitsInThisTile);
  1263.     } else if (compression == COMP_PACKBITS) {
  1264. stream.readFully(data, 0, byteCount);
  1265. // Since unitsInThisTile is the number of shorts, 
  1266. // but we do our decompression in terms of bytes, we 
  1267. // need to multiply unitsInThisTile by 2 in order to 
  1268. // figure out how many bytes we'll get after 
  1269. // decompression.
  1270. int bytesInThisTile = unitsInThisTile * 2;
  1271. byte byteArray[] = new byte[bytesInThisTile];
  1272. decodePackbits(data, bytesInThisTile, byteArray);
  1273. interpretBytesAsShorts(byteArray, sdata, 
  1274.        unitsInThisTile);
  1275.     } else if (compression == COMP_DEFLATE) {
  1276. stream.readFully(data, 0, byteCount);
  1277. byte byteArray[] = new byte[unitsInThisTile * 2];
  1278. inflate(data, byteArray);
  1279. interpretBytesAsShorts(byteArray, sdata, 
  1280.        unitsInThisTile);
  1281.     }
  1282. } else if (sampleSize == 32 &&
  1283.                            dataType == DataBuffer.TYPE_INT) { // redundant
  1284.     if (compression == COMP_NONE) {
  1285. readInts(byteCount/4, idata);
  1286.     } else if (compression == COMP_LZW) {
  1287. stream.readFully(data, 0, byteCount);
  1288. // Since unitsInThisTile is the number of ints, 
  1289. // but we do our decompression in terms of bytes, we 
  1290. // need to multiply unitsInThisTile by 4 in order to 
  1291. // figure out how many bytes we'll get after 
  1292. // decompression.
  1293. byte byteArray[] = new byte[unitsInThisTile * 4];
  1294. lzwDecoder.decode(data, byteArray, newRect.height);
  1295. interpretBytesAsInts(byteArray, idata, 
  1296.                                              unitsInThisTile);
  1297.     } else if (compression == COMP_PACKBITS) {
  1298. stream.readFully(data, 0, byteCount);
  1299. // Since unitsInThisTile is the number of ints, 
  1300. // but we do our decompression in terms of bytes, we 
  1301. // need to multiply unitsInThisTile by 4 in order to 
  1302. // figure out how many bytes we'll get after 
  1303. // decompression.
  1304. int bytesInThisTile = unitsInThisTile * 4;
  1305. byte byteArray[] = new byte[bytesInThisTile];
  1306. decodePackbits(data, bytesInThisTile, byteArray);
  1307. interpretBytesAsInts(byteArray, idata, 
  1308.                                              unitsInThisTile);
  1309.     } else if (compression == COMP_DEFLATE) {
  1310. stream.readFully(data, 0, byteCount);
  1311. byte byteArray[] = new byte[unitsInThisTile * 4];
  1312. inflate(data, byteArray);
  1313. interpretBytesAsInts(byteArray, idata, 
  1314.                                              unitsInThisTile);
  1315.                     }
  1316. } else if (sampleSize == 32 &&
  1317.                            dataType == DataBuffer.TYPE_FLOAT) { // redundant
  1318.     if (compression == COMP_NONE) {
  1319. readFloats(byteCount/4, fdata);
  1320.     } else if (compression == COMP_LZW) {
  1321. stream.readFully(data, 0, byteCount);
  1322. // Since unitsInThisTile is the number of floats, 
  1323. // but we do our decompression in terms of bytes, we 
  1324. // need to multiply unitsInThisTile by 4 in order to 
  1325. // figure out how many bytes we'll get after 
  1326. // decompression.
  1327. byte byteArray[] = new byte[unitsInThisTile * 4];
  1328. lzwDecoder.decode(data, byteArray, newRect.height);
  1329. interpretBytesAsFloats(byteArray, fdata, 
  1330.                                                unitsInThisTile);
  1331.     } else if (compression == COMP_PACKBITS) {
  1332. stream.readFully(data, 0, byteCount);
  1333. // Since unitsInThisTile is the number of floats, 
  1334. // but we do our decompression in terms of bytes, we 
  1335. // need to multiply unitsInThisTile by 4 in order to 
  1336. // figure out how many bytes we'll get after 
  1337. // decompression.
  1338. int bytesInThisTile = unitsInThisTile * 4;
  1339. byte byteArray[] = new byte[bytesInThisTile];
  1340. decodePackbits(data, bytesInThisTile, byteArray);
  1341. interpretBytesAsFloats(byteArray, fdata, 
  1342.                                                unitsInThisTile);
  1343.     } else if (compression == COMP_DEFLATE) {
  1344. stream.readFully(data, 0, byteCount);
  1345. byte byteArray[] = new byte[unitsInThisTile * 4];
  1346.                         inflate(data, byteArray);
  1347. interpretBytesAsFloats(byteArray, fdata, 
  1348.                                                unitsInThisTile);
  1349.                     }
  1350. }
  1351. stream.seek(save_offset);
  1352.     } catch (IOException ioe) {
  1353. throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
  1354.     }
  1355.             // Modify the data for certain special cases.
  1356.             switch(imageType) {
  1357.             case TYPE_GRAY:
  1358.             case TYPE_GRAY_ALPHA:
  1359.                 if(isWhiteZero) {
  1360.                     // Since we are using a ComponentColorModel with this
  1361.                     // image, we need to change the WhiteIsZero data to
  1362.                     // BlackIsZero data so it will display properly.
  1363.                     if (dataType == DataBuffer.TYPE_BYTE &&
  1364.                         !(colorModel instanceof IndexColorModel)) {
  1365.                         for (int l = 0; l < bdata.length; l += numBands) {
  1366.                             bdata[l] = (byte)(255 - bdata[l]);
  1367.                         }
  1368.                     } else if (dataType == DataBuffer.TYPE_USHORT) {
  1369.                         int ushortMax = Short.MAX_VALUE - Short.MIN_VALUE;
  1370.                         for (int l = 0; l < sdata.length; l += numBands) {
  1371.                             sdata[l] = (short)(ushortMax - sdata[l]);
  1372.                         }
  1373.                     } else if (dataType == DataBuffer.TYPE_SHORT) {
  1374.                         for (int l = 0; l < sdata.length; l += numBands) {
  1375.                             sdata[l] = (short)(~sdata[l]);
  1376.                         }
  1377.                     } else if (dataType == DataBuffer.TYPE_INT) {
  1378.                         long uintMax = Integer.MAX_VALUE - Integer.MIN_VALUE;
  1379.                         for (int l = 0; l < idata.length; l += numBands) {
  1380.                             idata[l] = (int)(uintMax - (long)idata[l]);
  1381.                         }
  1382.                     }
  1383.                 }
  1384.                 break;
  1385.             case TYPE_RGB:
  1386.                 // Change RGB to BGR order, as Java2D displays that faster.
  1387.                 // Unnecessary for JPEG-in-TIFF as the decoder handles it.
  1388.                 if (sampleSize == 8 && compression != COMP_JPEG_TTN2) {
  1389.     for (int i=0; i<unitsInThisTile; i+=3) {
  1390. bswap = bdata[i];
  1391. bdata[i] = bdata[i+2];
  1392. bdata[i+2] = bswap;
  1393.     }
  1394. } else if (sampleSize == 16) {
  1395.     for (int i=0; i<unitsInThisTile; i+=3) {
  1396. sswap = sdata[i];
  1397. sdata[i] = sdata[i+2];
  1398. sdata[i+2] = sswap;
  1399.     }
  1400. } else if (sampleSize == 32) {
  1401.                     if(dataType == DataBuffer.TYPE_INT) {
  1402.                         for (int i=0; i<unitsInThisTile; i+=3) {
  1403.                             iswap = idata[i];
  1404.                             idata[i] = idata[i+2];
  1405.                             idata[i+2] = iswap;
  1406.                         }
  1407.                     } else if(dataType == DataBuffer.TYPE_FLOAT) {
  1408.                         for (int i=0; i<unitsInThisTile; i+=3) {
  1409.                             fswap = fdata[i];
  1410.                             fdata[i] = fdata[i+2];
  1411.                             fdata[i+2] = fswap;
  1412.                         }
  1413.                     }
  1414.                 }
  1415.                 break;
  1416.             case TYPE_RGB_ALPHA:
  1417.                 // Convert from RGBA to ABGR for Java2D
  1418.                 if (sampleSize == 8) {
  1419.     for (int i=0; i<unitsInThisTile; i+=4) {
  1420. // Swap R and A
  1421. bswap = bdata[i];
  1422. bdata[i] = bdata[i+3];
  1423. bdata[i+3] = bswap;
  1424. // Swap G and B
  1425. bswap = bdata[i+1];
  1426. bdata[i+1] = bdata[i+2];
  1427. bdata[i+2] = bswap;
  1428.     }
  1429. } else if (sampleSize == 16) {
  1430.     for (int i=0; i<unitsInThisTile; i+=4) {
  1431. // Swap R and A
  1432. sswap = sdata[i];
  1433. sdata[i] = sdata[i+3];
  1434. sdata[i+3] = sswap;
  1435. // Swap G and B
  1436. sswap = sdata[i+1];
  1437. sdata[i+1] = sdata[i+2];
  1438. sdata[i+2] = sswap;
  1439.     }
  1440. } else if (sampleSize == 32) {
  1441.                     if(dataType == DataBuffer.TYPE_INT) {
  1442.                         for (int i=0; i<unitsInThisTile; i+=4) {
  1443.                             // Swap R and A
  1444.                             iswap = idata[i];
  1445.                             idata[i] = idata[i+3];
  1446.                             idata[i+3] = iswap;
  1447.                             // Swap G and B
  1448.                             iswap = idata[i+1];
  1449.                             idata[i+1] = idata[i+2];
  1450.                             idata[i+2] = iswap;
  1451.                         }
  1452.                     } else if(dataType == DataBuffer.TYPE_FLOAT) {
  1453.                         for (int i=0; i<unitsInThisTile; i+=4) {
  1454.                             // Swap R and A
  1455.                             fswap = fdata[i];
  1456.                             fdata[i] = fdata[i+3];
  1457.                             fdata[i+3] = fswap;
  1458.                             // Swap G and B
  1459.                             fswap = fdata[i+1];
  1460.                             fdata[i+1] = fdata[i+2];
  1461.                             fdata[i+2] = fswap;
  1462.                         }
  1463.                     }
  1464.                 }
  1465.                 break;
  1466.             case TYPE_YCBCR_SUB:
  1467.                 // Post-processing for YCbCr with subsampled chrominance:
  1468.                 // simply replicate the chroma channels for displayability.
  1469.                 int pixelsPerDataUnit = chromaSubH*chromaSubV;
  1470.                 int numH = newRect.width/chromaSubH;
  1471.                 int numV = newRect.height/chromaSubV;
  1472.                 byte[] tempData = new byte[numH*numV*(pixelsPerDataUnit + 2)];
  1473.                 System.arraycopy(bdata, 0, tempData, 0, tempData.length);
  1474.                 int samplesPerDataUnit = pixelsPerDataUnit*3;
  1475.                 int[] pixels = new int[samplesPerDataUnit];
  1476.                 int bOffset = 0;
  1477.                 int offsetCb = pixelsPerDataUnit;
  1478.                 int offsetCr = offsetCb + 1;
  1479.                 int y = newRect.y;
  1480.                 for(int j = 0; j < numV; j++) {
  1481.                     int x = newRect.x;
  1482.                     for(int i = 0; i < numH; i++) {
  1483.                         int Cb = tempData[bOffset + offsetCb];
  1484.                         int Cr = tempData[bOffset + offsetCr];
  1485.                         int k = 0;
  1486.                         while(k < samplesPerDataUnit) {
  1487.                             pixels[k++] = tempData[bOffset++];
  1488.                             pixels[k++] = Cb;
  1489.                             pixels[k++] = Cr;
  1490.                         }
  1491.                         bOffset += 2;
  1492.                         tile.setPixels(x, y, chromaSubH, chromaSubV, pixels);
  1493.                         x += chromaSubH;
  1494.                     }
  1495.                     y += chromaSubV;
  1496.                 }
  1497.                 break;
  1498.             }
  1499.         }
  1500.         
  1501.         return tile;
  1502.     }
  1503.     private void readShorts(int shortCount, short shortArray[]) {
  1504. // Since each short consists of 2 bytes, we need a 
  1505. // byte array of double size
  1506. int byteCount = 2 * shortCount;
  1507. byte byteArray[] = new byte[byteCount];
  1508. try {     
  1509.     stream.readFully(byteArray, 0, byteCount);
  1510. } catch (IOException ioe) {
  1511.    throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
  1512. }
  1513. interpretBytesAsShorts(byteArray, shortArray, shortCount);
  1514.     }
  1515.     private void readInts(int intCount, int intArray[]) {
  1516. // Since each int consists of 4 bytes, we need a 
  1517. // byte array of quadruple size
  1518. int byteCount = 4 * intCount;
  1519. byte byteArray[] = new byte[byteCount];
  1520. try {     
  1521.     stream.readFully(byteArray, 0, byteCount);
  1522. } catch (IOException ioe) {
  1523.    throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
  1524. }
  1525. interpretBytesAsInts(byteArray, intArray, intCount);
  1526.     }
  1527.     private void readFloats(int floatCount, float floatArray[]) {
  1528. // Since each float consists of 4 bytes, we need a 
  1529. // byte array of quadruple size
  1530. int byteCount = 4 * floatCount;
  1531. byte byteArray[] = new byte[byteCount];
  1532. try {     
  1533.     stream.readFully(byteArray, 0, byteCount);
  1534. } catch (IOException ioe) {
  1535.    throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
  1536. }
  1537. interpretBytesAsFloats(byteArray, floatArray, floatCount);
  1538.     }
  1539.     // Method to interpret a byte array to a short array, depending on 
  1540.     // whether the bytes are stored in a big endian or little endian format.
  1541.     private void interpretBytesAsShorts(byte byteArray[], 
  1542. short shortArray[], 
  1543. int shortCount) {
  1544. int j = 0;
  1545. int firstByte, secondByte;
  1546. if (isBigEndian) {
  1547.     for (int i=0; i<shortCount; i++) {
  1548. firstByte = byteArray[j++] & 0xff;
  1549. secondByte = byteArray[j++] & 0xff;
  1550. shortArray[i] = (short)((firstByte << 8) + secondByte);
  1551.     }
  1552.     
  1553. } else {
  1554.     
  1555.     for (int i=0; i<shortCount; i++) {
  1556. firstByte = byteArray[j++] & 0xff;
  1557. secondByte = byteArray[j++] & 0xff;
  1558. shortArray[i] = (short)((secondByte << 8) + firstByte);
  1559.     }
  1560. }
  1561.     }
  1562.     // Method to interpret a byte array to a int array, depending on 
  1563.     // whether the bytes are stored in a big endian or little endian format.
  1564.     private void interpretBytesAsInts(byte byteArray[],
  1565.                                       int intArray[], 
  1566.                                       int intCount) {
  1567. int j = 0;
  1568. if (isBigEndian) {
  1569.     
  1570.     for (int i=0; i<intCount; i++) {
  1571. intArray[i] =
  1572.                     (int)(((byteArray[j++] & 0xff) << 24) |
  1573.                           ((byteArray[j++] & 0xff) << 16) |
  1574.                           ((byteArray[j++] & 0xff) << 8) |
  1575.                           (byteArray[j++] & 0xff));
  1576.     }
  1577.     
  1578. } else {
  1579.     
  1580.     for (int i=0; i<intCount; i++) {
  1581. intArray[i] =
  1582.                     (int)((byteArray[j++] & 0xff) |
  1583.                           ((byteArray[j++] & 0xff) << 8) |
  1584.                           ((byteArray[j++] & 0xff) << 16) |
  1585.                           ((byteArray[j++] & 0xff) << 24));
  1586.     }
  1587. }
  1588.     }
  1589.     // Method to interpret a byte array to a float array, depending on 
  1590.     // whether the bytes are stored in a big endian or little endian format.
  1591.     private void interpretBytesAsFloats(byte byteArray[],
  1592.                                         float floatArray[], 
  1593.                                         int floatCount) {
  1594. int j = 0;
  1595. if (isBigEndian) {
  1596.     
  1597.     for (int i=0; i<floatCount; i++) {
  1598.                 int value = (int)(((byteArray[j++] & 0xff) << 24) |
  1599.                                   ((byteArray[j++] & 0xff) << 16) |
  1600.                                   ((byteArray[j++] & 0xff) << 8) |
  1601.                                   (byteArray[j++] & 0xff));
  1602. floatArray[i] = Float.intBitsToFloat(value);
  1603.     }
  1604.     
  1605. } else {
  1606.     
  1607.     for (int i=0; i<floatCount; i++) {
  1608. int value = (int)((byteArray[j++] & 0xff) |
  1609.                                   ((byteArray[j++] & 0xff) << 8) |
  1610.                                   ((byteArray[j++] & 0xff) << 16) |
  1611.                                   ((byteArray[j++] & 0xff) << 24));
  1612. floatArray[i] = Float.intBitsToFloat(value);
  1613.     }
  1614. }
  1615.     }
  1616.     // Uncompress packbits compressed image data.
  1617.     private byte[] decodePackbits(byte data[], int arraySize, byte[] dst) {
  1618. if (dst == null) {
  1619.     dst = new byte[arraySize];
  1620. }
  1621. int srcCount = 0, dstCount = 0;
  1622. byte repeat, b;
  1623. try {
  1624.     
  1625.     while (dstCount < arraySize) {
  1626. b = data[srcCount++];
  1627. if (b >= 0 && b <= 127) {
  1628.     
  1629.     // literal run packet
  1630.     for (int i=0; i<(b + 1); i++) {
  1631. dst[dstCount++] = data[srcCount++];
  1632.     }
  1633.          
  1634. } else if (b <= -1 && b >= -127) {
  1635.     
  1636.     // 2 byte encoded run packet
  1637.     repeat = data[srcCount++];
  1638.     for (int i=0; i<(-b + 1); i++) {
  1639. dst[dstCount++] = repeat;
  1640.     }
  1641.     
  1642. } else {
  1643.     // no-op packet. Do nothing
  1644.     srcCount++;
  1645. }
  1646.     }
  1647. } catch (java.lang.ArrayIndexOutOfBoundsException ae) {
  1648.     throw new RuntimeException(JaiI18N.getString("TIFFImage14"));
  1649. }
  1650. return dst;
  1651.     }
  1652.     // Need a createColorModel().
  1653.     // Create ComponentColorModel for TYPE_RGB images
  1654.     private ComponentColorModel createAlphaComponentColorModel(
  1655.   int dataType,
  1656.                                                   int numBands,
  1657.   boolean isAlphaPremultiplied,
  1658.   int transparency) {
  1659. ComponentColorModel ccm = null;
  1660.         int RGBBits[] = null;
  1661.         ColorSpace cs = null;
  1662.         switch(numBands) {
  1663.         case 2: // gray+alpha
  1664.             cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
  1665.             break;
  1666.         case 4: // RGB+alpha
  1667.             cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  1668.             break;
  1669.         default:
  1670.             throw new IllegalArgumentException();
  1671.         }
  1672.         if(dataType == DataBuffer.TYPE_FLOAT) {
  1673.             ccm = new FloatDoubleColorModel(cs,
  1674.                                             true,
  1675.                                             isAlphaPremultiplied,
  1676.                                             transparency,
  1677.                                             dataType);
  1678.         } else { // all other types
  1679.             int componentSize = 0;
  1680.             switch(dataType) {
  1681.             case DataBuffer.TYPE_BYTE:
  1682.                 componentSize = 8;
  1683.                 break;
  1684.             case DataBuffer.TYPE_USHORT:
  1685.             case DataBuffer.TYPE_SHORT:
  1686.                 componentSize = 16;
  1687.                 break;
  1688.             case DataBuffer.TYPE_INT:
  1689.                 componentSize = 32;
  1690.                 break;
  1691.             default:
  1692.                 throw new IllegalArgumentException();
  1693.             }
  1694.             RGBBits = new int[numBands];
  1695.             for(int i = 0; i < numBands; i++) {
  1696.                 RGBBits[i] = componentSize;
  1697.             }
  1698.             ccm = new ComponentColorModel(cs,
  1699.                                           RGBBits,
  1700.                                           true,
  1701.                                           isAlphaPremultiplied,
  1702.                                           transparency,
  1703.                                           dataType);
  1704.         }
  1705. return ccm;
  1706.     }
  1707. }