001/*
002 * $RCSfile: TIFFDecompressor.java,v $
003 *
004 * 
005 * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
006 * 
007 * Redistribution and use in source and binary forms, with or without
008 * modification, are permitted provided that the following conditions
009 * are met: 
010 * 
011 * - Redistribution of source code must retain the above copyright 
012 *   notice, this  list of conditions and the following disclaimer.
013 * 
014 * - Redistribution in binary form must reproduce the above copyright
015 *   notice, this list of conditions and the following disclaimer in 
016 *   the documentation and/or other materials provided with the
017 *   distribution.
018 * 
019 * Neither the name of Sun Microsystems, Inc. or the names of 
020 * contributors may be used to endorse or promote products derived 
021 * from this software without specific prior written permission.
022 * 
023 * This software is provided "AS IS," without a warranty of any 
024 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
025 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
026 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
028 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
029 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
031 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035 * POSSIBILITY OF SUCH DAMAGES. 
036 * 
037 * You acknowledge that this software is not designed or intended for 
038 * use in the design, construction, operation or maintenance of any 
039 * nuclear facility. 
040 *
041 * $Revision: 1.3 $
042 * $Date: 2007/03/09 20:14:40 $
043 * $State: Exp $
044 */
045package com.github.jaiimageio.plugins.tiff;
046
047import java.awt.Rectangle;
048import java.awt.Transparency;
049import java.awt.color.ColorSpace;
050import java.awt.image.BufferedImage;
051import java.awt.image.ColorModel;
052import java.awt.image.ComponentColorModel;
053import java.awt.image.ComponentSampleModel;
054import java.awt.image.DataBuffer;
055import java.awt.image.DataBufferByte;
056import java.awt.image.DataBufferFloat;
057import java.awt.image.DataBufferInt;
058import java.awt.image.DataBufferShort;
059import java.awt.image.DataBufferUShort;
060import java.awt.image.IndexColorModel;
061import java.awt.image.MultiPixelPackedSampleModel;
062import java.awt.image.PixelInterleavedSampleModel;
063import java.awt.image.Raster;
064import java.awt.image.SampleModel;
065import java.awt.image.SinglePixelPackedSampleModel;
066import java.awt.image.WritableRaster;
067import java.io.ByteArrayInputStream;
068import java.io.IOException;
069import java.nio.ByteOrder;
070
071import javax.imageio.IIOException;
072import javax.imageio.ImageReader;
073import javax.imageio.ImageTypeSpecifier;
074import javax.imageio.metadata.IIOMetadata;
075import javax.imageio.stream.ImageInputStream;
076import javax.imageio.stream.MemoryCacheImageInputStream;
077
078import com.github.jaiimageio.impl.common.BogusColorSpace;
079import com.github.jaiimageio.impl.common.ImageUtil;
080import com.github.jaiimageio.impl.common.SimpleCMYKColorSpace;
081
082/**
083 * A class defining a pluggable TIFF decompressor.
084 *
085 * <p> The mapping between source and destination Y coordinates is
086 * given by the equations:
087 *
088 * <pre>
089 * dx = (sx - sourceXOffset)/subsampleX + dstXOffset;
090 * dy = (sy - sourceYOffset)/subsampleY + dstYOffset;
091 * </pre>
092 *
093 * Note that the mapping from source coordinates to destination
094 * coordinates is not one-to-one if subsampling is being used, since
095 * only certain source pixels are to be copied to the
096 * destination. However, * the inverse mapping is always one-to-one:
097 *
098 * <pre>
099 * sx = (dx - dstXOffset)*subsampleX + sourceXOffset;
100 * sy = (dy - dstYOffset)*subsampleY + sourceYOffset;
101 * </pre>
102 *
103 * <p> Decompressors may be written with various levels of complexity.
104 * The most complex decompressors will override the
105 * <code>decode</code> method, and will perform all the work of
106 * decoding, subsampling, offsetting, clipping, and format conversion.
107 * This approach may be the most efficient, since it is possible to
108 * avoid the use of extra image buffers, and it may be possible to
109 * avoid decoding portions of the image that will not be copied into
110 * the destination.
111 *
112 * <p> Less ambitious decompressors may override the
113 * <code>decodeRaw</code> method, which is responsible for
114 * decompressing the entire tile or strip into a byte array (or other
115 * appropriate datatype).  The default implementation of
116 * <code>decode</code> will perform all necessary setup of buffers,
117 * call <code>decodeRaw</code> to perform the actual decoding, perform
118 * subsampling, and copy the results into the final destination image.
119 * Where possible, it will pass the real image buffer to
120 * <code>decodeRaw</code> in order to avoid making an extra copy.
121 *
122 * <p> Slightly more ambitious decompressors may override
123 * <code>decodeRaw</code>, but avoid writing pixels that will be
124 * discarded in the subsampling phase.
125 */
126public abstract class TIFFDecompressor {
127
128    private static final boolean DEBUG = false; // XXX false for release!
129
130    /**
131     * The <code>ImageReader</code> calling this
132     * <code>TIFFDecompressor</code>.
133     */
134    protected ImageReader reader;
135
136    /**
137     * The <code>IIOMetadata</code> object containing metadata for the
138     * current image.
139     */
140    protected IIOMetadata metadata;
141
142    /**
143     * The value of the <code>PhotometricInterpretation</code> tag.
144     * Legal values are {@link
145     * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO },
146     * {@link
147     * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO},
148     * {@link BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_RGB},
149     * {@link
150     * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR},
151     * {@link
152     * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_TRANSPARENCY_MASK},
153     * {@link BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_Y_CB_CR},
154     * {@link BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_CIELAB},
155     * {@link BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_ICCLAB},
156     * or other value defined by a TIFF extension.
157     */
158    protected int photometricInterpretation;
159
160    /**
161     * The value of the <code>Compression</code> tag. Legal values are
162     * {@link BaselineTIFFTagSet#COMPRESSION_NONE}, {@link
163     * BaselineTIFFTagSet#COMPRESSION_CCITT_RLE}, {@link
164     * BaselineTIFFTagSet#COMPRESSION_CCITT_T_4}, {@link
165     * BaselineTIFFTagSet#COMPRESSION_CCITT_T_6}, {@link
166     * BaselineTIFFTagSet#COMPRESSION_LZW}, {@link
167     * BaselineTIFFTagSet#COMPRESSION_OLD_JPEG}, {@link
168     * BaselineTIFFTagSet#COMPRESSION_JPEG}, {@link
169     * BaselineTIFFTagSet#COMPRESSION_ZLIB}, {@link
170     * BaselineTIFFTagSet#COMPRESSION_PACKBITS}, {@link
171     * BaselineTIFFTagSet#COMPRESSION_DEFLATE}, or other value
172     * defined by a TIFF extension.
173     */
174    protected int compression;
175
176    /**
177     * <code>true</code> if the image is encoded using separate planes.
178     */
179    protected boolean planar;
180
181    /**
182     * The value of the <code>SamplesPerPixel</code> tag.
183     */
184    protected int samplesPerPixel;
185
186    /**
187     * The value of the <code>BitsPerSample</code> tag.
188     *
189     */
190    protected int[] bitsPerSample;
191
192    /**
193     * The value of the <code>SampleFormat</code> tag.  Legal values
194     * are {@link BaselineTIFFTagSet#SAMPLE_FORMAT_UNSIGNED_INTEGER},
195     * {@link BaselineTIFFTagSet#SAMPLE_FORMAT_SIGNED_INTEGER}, {@link
196     * BaselineTIFFTagSet#SAMPLE_FORMAT_FLOATING_POINT}, {@link
197     * BaselineTIFFTagSet#SAMPLE_FORMAT_UNDEFINED}, or other value
198     * defined by a TIFF extension.
199     */
200    protected int[] sampleFormat =
201        new int[] {BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER};
202
203    /**
204     * The value of the <code>ExtraSamples</code> tag.  Legal values
205     * are {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNSPECIFIED},
206     * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_ASSOCIATED_ALPHA},
207     * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNASSOCIATED_ALPHA},
208     * or other value defined by a TIFF extension.
209     */
210    protected int[] extraSamples;
211
212    /**
213     * The value of the <code>ColorMap</code> tag.
214     *
215     */
216    protected char[] colorMap;        
217
218    // Region of input stream containing the data
219
220    /**
221     * The <code>ImageInputStream</code> containing the TIFF source
222     * data.
223     */
224    protected ImageInputStream stream;
225
226    /**
227     * The offset in the source <code>ImageInputStream</code> of the
228     * start of the data to be decompressed.
229     */
230    protected long offset;
231
232    /**
233     * The number of bytes of data from the source
234     * <code>ImageInputStream</code> to be decompressed.
235     */
236    protected int byteCount;
237
238    // Region of the file image represented in the stream
239    // This is unaffected by subsampling
240
241    /**
242     * The X coordinate of the upper-left pixel of the source region
243     * being decoded from the source stream.  This value is not affected
244     * by source subsampling.
245     */
246    protected int srcMinX;
247
248    /**
249     * The Y coordinate of the upper-left pixel of the source region
250     * being decoded from the source stream.  This value is not affected
251     * by source subsampling.
252     */
253    protected int srcMinY;
254
255    /** 
256     * The width of the source region being decoded from the source
257     * stream.  This value is not affected by source subsampling.
258     */
259    protected int srcWidth;
260
261    /**
262     * The height of the source region being decoded from the source
263     * stream.  This value is not affected by source subsampling.
264     */
265    protected int srcHeight;
266
267    // Subsampling to be performed
268
269    /**
270     * The source X offset used, along with <code>dstXOffset</code>
271     * and <code>subsampleX</code>, to map between horizontal source
272     * and destination pixel coordinates.
273     */
274    protected int sourceXOffset;
275
276    /**
277     * The horizontal destination offset used, along with
278     * <code>sourceXOffset</code> and <code>subsampleX</code>, to map
279     * between horizontal source and destination pixel coordinates.
280     * See the comment for {@link #sourceXOffset
281     * <code>sourceXOffset</code>} for the mapping equations.
282     */
283    protected int dstXOffset;
284
285    /**
286     * The source Y offset used, along with <code>dstYOffset</code>
287     * and <code>subsampleY</code>, to map between vertical source and
288     * destination pixel coordinates.
289     */
290    protected int sourceYOffset;
291
292    /**
293     * The vertical destination offset used, along with
294     * <code>sourceYOffset</code> and <code>subsampleY</code>, to map
295     * between horizontal source and destination pixel coordinates.
296     * See the comment for {@link #sourceYOffset
297     * <code>sourceYOffset</code>} for the mapping equations.
298     */
299    protected int dstYOffset;
300    
301    /**
302     * The horizontal subsampling factor.  A factor of 1 means that
303     * every column is copied to the destination; a factor of 2 means
304     * that every second column is copied, etc.
305     */
306    protected int subsampleX;
307
308    /**
309     * The vertical subsampling factor.  A factor of 1 means that
310     * every row is copied to the destination; a factor of 2 means
311     * that every second row is copied, etc.
312     */
313    protected int subsampleY;
314
315    // Band subsetting/rearrangement
316
317    /**
318     * The sequence of source bands that are to be copied into the
319     * destination.
320     */
321    protected int[] sourceBands;
322
323    /**
324     * The sequence of destination bands to receive the source data.
325     */
326    protected int[] destinationBands;
327
328    // Destination for decodeRaw
329
330    /**
331     * A <code>BufferedImage</code> for the <code>decodeRaw</code>
332     * method to write into.
333     */
334    protected BufferedImage rawImage;
335
336    // Destination
337
338    /**
339     * The final destination image.
340     */
341    protected BufferedImage image;
342
343    /**
344     * The X coordinate of the upper left pixel to be written in the
345     * destination image.
346     */
347    protected int dstMinX;
348
349    /**
350     * The Y coordinate of the upper left pixel to be written in the
351     * destination image.
352     */
353    protected int dstMinY;
354
355    /**
356     * The width of the region of the destination image to be written.
357     */
358    protected int dstWidth;
359
360    /**
361     * The height of the region of the destination image to be written.
362     */
363    protected int dstHeight;
364
365    // Region of source contributing to the destination
366
367    /**
368     * The X coordinate of the upper-left source pixel that will
369     * actually be copied into the destination image, taking into
370     * account all subsampling, offsetting, and clipping.  That is,
371     * the pixel at (<code>activeSrcMinX</code>,
372     * <code>activeSrcMinY</code>) is to be copied into the
373     * destination pixel at (<code>dstMinX</code>,
374     * <code>dstMinY</code>).
375     *
376     * <p> The pixels in the source region to be copied are
377     * those with X coordinates of the form <code>activeSrcMinX +
378     * k*subsampleX</code>, where <code>k</code> is an integer such
379     * that <code>0 <= k < dstWidth</code>.
380     */
381    protected int activeSrcMinX;
382
383    /**
384     * The Y coordinate of the upper-left source pixel that will
385     * actually be copied into the destination image, taking into account
386     * all subsampling, offsetting, and clipping.
387     *
388     * <p> The pixels in the source region to be copied are
389     * those with Y coordinates of the form <code>activeSrcMinY +
390     * k*subsampleY</code>, where <code>k</code> is an integer such
391     * that <code>0 <= k < dstHeight</code>.
392     */
393    protected int activeSrcMinY;
394
395    /**
396     * The width of the source region that will actually be copied
397     * into the destination image, taking into account all
398     * susbampling, offsetting, and clipping.
399     *
400     * <p> The active source width will always be equal to
401     * <code>(dstWidth - 1)*subsampleX + 1</code>.
402     */
403    protected int activeSrcWidth;
404
405    /**
406     * The height of the source region that will actually be copied
407     * into the destination image, taking into account all
408     * susbampling, offsetting, and clipping.
409     *
410     * <p> The active source height will always be equal to
411     * <code>(dstHeight - 1)*subsampleY + 1</code>.
412     */
413    protected int activeSrcHeight;
414
415    /**
416     * A <code>TIFFColorConverter</code> object describing the color space of
417     * the encoded pixel data, or <code>null</code>.
418     */
419    protected TIFFColorConverter colorConverter;
420
421    boolean isBilevel;
422    boolean isContiguous;
423    boolean isImageSimple;
424    boolean adjustBitDepths;
425    int[][] bitDepthScale;
426
427    // source pixel at (sx, sy) should map to dst pixel (dx, dy), where:
428    //
429    // dx = (sx - sourceXOffset)/subsampleX + dstXOffset;
430    // dy = (sy - sourceYOffset)/subsampleY + dstYOffset; 
431    //
432    // Note that this mapping is many-to-one.  Source pixels such that
433    // (sx - sourceXOffset) % subsampleX != 0 should not be copied
434    // (and similarly for y).
435    // 
436    // The backwards mapping from dest to source is one-to-one:
437    //
438    // sx = (dx - dstXOffset)*subsampleX + sourceXOffset;
439    // sy = (dy - dstYOffset)*subsampleY + sourceYOffset;
440    //
441    // The reader will always hand us the full source region as it
442    // exists in the file.  It will take care of clipping the dest region 
443    // to exactly those dest pixels that are present in the source region.
444
445    /**
446     * Create a <code>PixelInterleavedSampleModel</code> for use in creating
447     * an <code>ImageTypeSpecifier</code>.  Its dimensions will be 1x1 and
448     * it will have ascending band offsets as {0, 1, 2, ..., numBands}.
449     *
450     * @param dataType The data type (DataBuffer.TYPE_*).
451     * @param numBands The number of bands.
452     * @return A <code>PixelInterleavedSampleModel</code>.
453     */
454    // XXX Maybe don't need to have this as a separate method?
455    static SampleModel createInterleavedSM(int dataType,
456                                           int numBands) {
457        int[] bandOffsets = new int[numBands];
458        for(int i = 0; i < numBands; i++) {
459            bandOffsets[i] = i;
460        }
461        return new PixelInterleavedSampleModel(dataType,
462                                               1, // width
463                                               1, // height
464                                               numBands, // pixelStride,
465                                               numBands, // scanlineStride
466                                               bandOffsets);
467    }
468
469    /**
470     * Create a <code>ComponentColorModel</code> for use in creating
471     * an <code>ImageTypeSpecifier</code>.
472     */
473    // This code was copied from javax.imageio.ImageTypeSpecifier and
474    // modified to support floating point data.
475    static ColorModel createComponentCM(ColorSpace colorSpace,
476                                        int numBands,
477                                        int dataType,
478                                        boolean hasAlpha,
479                                        boolean isAlphaPremultiplied) {
480        int transparency =
481            hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
482
483        ColorModel colorModel;
484        if(dataType == DataBuffer.TYPE_FLOAT ||
485           dataType == DataBuffer.TYPE_DOUBLE) {
486
487            colorModel = new ComponentColorModel(colorSpace,
488                                                 hasAlpha,
489                                                 isAlphaPremultiplied,
490                                                 transparency,
491                                                 dataType);
492        } else {
493            int[] numBits = new int[numBands];
494            int bits;
495            if (dataType == DataBuffer.TYPE_BYTE) {
496                bits = 8;
497            } else if (dataType == DataBuffer.TYPE_SHORT ||
498                       dataType == DataBuffer.TYPE_USHORT) {
499                bits = 16;
500            } else if (dataType == DataBuffer.TYPE_INT) {
501                bits = 32;
502            } else {
503                throw new IllegalArgumentException("dataType = " + dataType);
504            }
505            for (int i = 0; i < numBands; i++) {
506                numBits[i] = bits;
507            }
508
509            colorModel = new ComponentColorModel(colorSpace,
510                                                 numBits,
511                                                 hasAlpha,
512                                                 isAlphaPremultiplied,
513                                                 transparency,
514                                                 dataType);
515        }
516
517        return colorModel;
518    }
519
520    private static int createMask(int[] bitsPerSample, int band) {
521        int mask = (1 << bitsPerSample[band]) - 1;
522        for (int i = band + 1; i < bitsPerSample.length; i++) {
523            mask <<= bitsPerSample[i];
524        }
525
526        return mask;
527    }
528
529    private static int getDataTypeFromNumBits(int numBits, boolean isSigned) {
530        int dataType;
531
532        if (numBits <= 8) {
533            dataType = DataBuffer.TYPE_BYTE;
534        } else if (numBits <= 16) {
535            dataType = isSigned ?
536                DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT;
537        } else {
538            dataType = DataBuffer.TYPE_INT;
539        }
540
541        return dataType;
542    }
543
544    private static boolean areIntArraysEqual(int[] a, int[] b) {
545        if(a == null || b == null) {
546            if(a == null && b == null) {
547                return true;
548            } else { // one is null and one is not
549                return false;
550            }
551        }
552
553        if(a.length != b.length) {
554            return false;
555        }
556
557        int length = a.length;
558        for(int i = 0; i < length; i++) {
559            if(a[i] != b[i]) {
560                return false;
561            }
562        }
563
564        return true;
565    }
566
567    /**
568     * Return the number of bits occupied by <code>dataType</code>
569     * which must be one of the <code>DataBuffer</code> <code>TYPE</code>s.
570     */
571    private static int getDataTypeSize(int dataType) throws IIOException {
572        int dataTypeSize = 0;
573        switch(dataType) {
574        case DataBuffer.TYPE_BYTE:
575            dataTypeSize = 8;
576            break;
577        case DataBuffer.TYPE_SHORT:
578        case DataBuffer.TYPE_USHORT:
579            dataTypeSize = 16;
580            break;
581        case DataBuffer.TYPE_INT:
582        case DataBuffer.TYPE_FLOAT:
583            dataTypeSize = 32;
584            break;
585        case DataBuffer.TYPE_DOUBLE:
586            dataTypeSize = 64;
587            break;
588        default:
589            throw new IIOException("Unknown data type "+dataType);
590        }
591
592        return dataTypeSize;
593    }
594
595    /**
596     * Returns the number of bits per pixel.
597     */
598    private static int getBitsPerPixel(SampleModel sm) {
599        int bitsPerPixel = 0;
600        int[] sampleSize = sm.getSampleSize();
601        int numBands = sampleSize.length;
602        for(int i = 0; i < numBands; i++) {
603            bitsPerPixel += sampleSize[i];
604        }
605        return bitsPerPixel;
606    }
607
608    /**
609     * Returns whether all samples have the same number of bits.
610     */
611    private static boolean areSampleSizesEqual(SampleModel sm) {
612        boolean allSameSize = true;
613        int[] sampleSize = sm.getSampleSize();
614        int sampleSize0 = sampleSize[0];
615        int numBands = sampleSize.length;
616
617        for(int i = 1; i < numBands; i++) {
618            if(sampleSize[i] != sampleSize0) {
619                allSameSize = false;
620                break;
621            }
622        }
623
624        return allSameSize;
625    }
626
627    /**
628     * Determines whether the <code>DataBuffer</code> is filled without
629     * any interspersed padding bits.
630     */
631    private static boolean isDataBufferBitContiguous(SampleModel sm)
632        throws IIOException {
633        int dataTypeSize = getDataTypeSize(sm.getDataType());
634
635        if(sm instanceof ComponentSampleModel) {
636            int numBands = sm.getNumBands();
637            for(int i = 0; i < numBands; i++) {
638                if(sm.getSampleSize(i) != dataTypeSize) {
639                    // Sample does not fill data element.
640                    return false;
641                }
642            }
643        } else if(sm instanceof MultiPixelPackedSampleModel) {
644            MultiPixelPackedSampleModel mppsm =
645                (MultiPixelPackedSampleModel)sm;
646            if(dataTypeSize % mppsm.getPixelBitStride() != 0) {
647                // Pixels do not fill the data element.
648                return false;
649            }
650        } else if(sm instanceof SinglePixelPackedSampleModel) {
651            SinglePixelPackedSampleModel sppsm =
652                (SinglePixelPackedSampleModel)sm;
653            int numBands = sm.getNumBands();
654            int numBits = 0;
655            for(int i = 0; i < numBands; i++) {
656                numBits += sm.getSampleSize(i);
657            }
658            if(numBits != dataTypeSize) {
659                // Pixel does not fill the data element.
660                return false;
661            }
662        } else {
663            // Unknown SampleModel class.
664            return false;
665        }
666
667        return true;
668    }
669
670    /**
671     * Reformats data read as bytes into a short or int buffer.
672     */
673    private static void reformatData(byte[] buf,
674                                     int bytesPerRow,
675                                     int numRows,
676                                     short[] shortData,
677                                     int[] intData,
678                                     int outOffset,
679                                     int outStride)
680        throws IIOException {
681
682        if(shortData != null) {
683            if(DEBUG) {
684                System.out.println("Reformatting data to short");
685            }
686            int inOffset = 0;
687            int shortsPerRow = bytesPerRow/2;
688            int numExtraBytes = bytesPerRow % 2;
689            for(int j = 0; j < numRows; j++) {
690                int k = outOffset;
691                for(int i = 0; i < shortsPerRow; i++) {
692                    shortData[k++] =
693                        (short)(((buf[inOffset++]&0xff) << 8) |
694                                (buf[inOffset++]&0xff));
695                }
696                if(numExtraBytes != 0) {
697                    shortData[k++] = (short)((buf[inOffset++]&0xff) << 8);
698                }
699                outOffset += outStride;
700            }
701        } else if(intData != null) {
702            if(DEBUG) {
703                System.out.println("Reformatting data to int");
704            }
705            int inOffset = 0;
706            int intsPerRow = bytesPerRow/4;
707            int numExtraBytes = bytesPerRow % 4;
708            for(int j = 0; j < numRows; j++) {
709                int k = outOffset;
710                for(int i = 0; i < intsPerRow; i++) {
711                    intData[k++] =
712                        ((buf[inOffset++]&0xff) << 24) |
713                        ((buf[inOffset++]&0xff) << 16) |
714                        ((buf[inOffset++]&0xff) << 8) |
715                        (buf[inOffset++]&0xff);
716                }
717                if(numExtraBytes != 0) {
718                    int shift = 24;
719                    int ival = 0;
720                    for(int b = 0; b < numExtraBytes; b++) {
721                        ival |= (buf[inOffset++]&0xff) << shift;
722                        shift -= 8;
723                    }
724                    intData[k++] = ival;
725                }
726                outOffset += outStride;
727            }
728        } else {
729            throw new IIOException("shortData == null && intData == null!");
730        }
731    }
732
733    /**
734     * Reformats bit-discontiguous data into the <code>DataBuffer</code>
735     * of the supplied <code>WritableRaster</code>.
736     */
737    private static void reformatDiscontiguousData(byte[] buf,
738                                                  int stride,
739                                                  int w,
740                                                  int h,
741                                                  WritableRaster raster)
742        throws IOException {
743
744        if(DEBUG) {
745            System.out.println("Reformatting discontiguous data");
746        }
747
748        // Get SampleModel info.
749        SampleModel sm = raster.getSampleModel();
750        int numBands = sm.getNumBands();
751        int[] sampleSize = sm.getSampleSize();
752
753        // Initialize input stream.
754        ByteArrayInputStream is = new ByteArrayInputStream(buf);
755        ImageInputStream iis = new MemoryCacheImageInputStream(is);
756
757        // Reformat.
758        long iisPosition = 0L;
759        int y = raster.getMinY();
760        for(int j = 0; j < h; j++, y++) {
761            iis.seek(iisPosition);
762            int x = raster.getMinX();
763            for(int i = 0; i < w; i++, x++) {
764                for(int b = 0; b < numBands; b++) {
765                    long bits = iis.readBits(sampleSize[b]);
766                    raster.setSample(x, y, b, (int)bits);
767                }
768            }
769            iisPosition += stride;
770        }
771    }
772
773    /**
774     * A utility method that returns an
775     * <code>ImageTypeSpecifier</code> suitable for decoding an image
776     * with the given parameters.
777     *
778     * @param photometricInterpretation the value of the
779     * <code>PhotometricInterpretation</code> field.
780     * @param compression the value of the <code>Compression</code> field.
781     * @param samplesPerPixel the value of the
782     * <code>SamplesPerPixel</code> field.
783     * @param bitsPerSample the value of the <code>BitsPerSample</code> field.
784     * @param sampleFormat the value of the <code>SampleFormat</code> field.
785     * @param extraSamples the value of the <code>ExtraSamples</code> field.
786     * @param colorMap the value of the <code>ColorMap</code> field.
787     *
788     * @return a suitable <code>ImageTypeSpecifier</code>, or
789     * <code>null</code> if it is not possible to create one.
790     */
791    public static ImageTypeSpecifier
792        getRawImageTypeSpecifier(int photometricInterpretation,
793                                 int compression,
794                                 int samplesPerPixel,
795                                 int[] bitsPerSample,
796                                 int[] sampleFormat,
797                                 int[] extraSamples,
798                                 char[] colorMap) {
799        // XXX BEGIN
800        /* XXX
801        System.out.println("samplesPerPixel: "+samplesPerPixel);
802        System.out.print("bitsPerSample:");
803        for(int i = 0; i < bitsPerSample.length; i++) {
804            System.out.print(" "+bitsPerSample[i]);
805        }
806        System.out.println("");
807        System.out.print("sampleFormat:");
808        for(int i = 0; i < sampleFormat.length; i++) {
809            System.out.print(" "+sampleFormat[i]);
810        }
811        System.out.println("");
812        if(extraSamples != null) {
813            System.out.print("extraSamples:");
814            for(int i = 0; i < extraSamples.length; i++) {
815                System.out.print(" "+extraSamples[i]);
816            }
817            System.out.println("");
818        }
819        */
820        // XXX END
821
822        //
823        // Types to support:
824        //
825        // 1, 2, 4, 8, or 16 bit grayscale or indexed
826        // 8,8-bit gray+alpha
827        // 16,16-bit gray+alpha
828        // 8,8,8-bit RGB
829        // 8,8,8,8-bit CMYK
830        // 8,8,8,8-bit RGB+alpha
831        // 16,16,16-bit RGB
832        // 16,16,16,16-bit RGB+alpha
833        // 1,1,1,1 or 2,2,2,2 or 4,4,4,4 CMYK
834        // R+G+B = 8-bit RGB
835        // R+G+B+A = 8-bit RGB
836        // R+G+B = 16-bit RGB
837        // R+G+B+A = 16-bit RGB
838        // 8X-bits/sample, arbitrary numBands.
839        // Arbitrary non-indexed, non-float layouts (discontiguous).
840        //
841
842        // Band-sequential
843
844        if(DEBUG) {
845            System.out.println("\n ---- samplesPerPixel = "+samplesPerPixel+
846                               "\n ---- bitsPerSample[0] = "+bitsPerSample[0]+
847                               "\n ---- sampleFormat[0] = "+sampleFormat[0]);
848        }
849
850        // 1, 2, 4, 8, or 16 bit grayscale or indexed images
851        if (samplesPerPixel == 1 &&
852            (bitsPerSample[0] == 1 ||
853             bitsPerSample[0] == 2 ||
854             bitsPerSample[0] == 4 ||
855             bitsPerSample[0] == 8 ||
856             bitsPerSample[0] == 16)) {
857
858            // 2 and 16 bits images are not in the baseline
859            // specification, but we will allow them anyway
860            // since they fit well into Java2D
861            //
862            // this raises the issue of how to write such images...
863            
864            if (colorMap == null) {
865                // Grayscale
866                boolean isSigned = (sampleFormat[0] ==
867                              BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER);
868                int dataType;
869                if (bitsPerSample[0] <= 8) {
870                    dataType = DataBuffer.TYPE_BYTE;
871                } else {
872                    dataType = sampleFormat[0] == 
873                        BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER ?
874                        DataBuffer.TYPE_SHORT :
875                        DataBuffer.TYPE_USHORT;
876                }
877
878                return ImageTypeSpecifier.createGrayscale(bitsPerSample[0],
879                                                          dataType,
880                                                          isSigned);
881            } else {
882                // Indexed
883                int mapSize = 1 << bitsPerSample[0];
884                byte[] redLut = new byte[mapSize];
885                byte[] greenLut = new byte[mapSize];
886                byte[] blueLut = new byte[mapSize];
887                byte[] alphaLut = null;
888
889                int idx = 0;
890                for (int i = 0; i < mapSize; i++) {
891                    redLut[i] = (byte)((colorMap[i]*255)/65535);
892                    greenLut[i] = (byte)((colorMap[mapSize + i]*255)/65535);
893                    blueLut[i] = (byte)((colorMap[2*mapSize + i]*255)/65535);
894                }
895
896                int dataType = bitsPerSample[0] == 8 ?
897                    DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT;
898                return ImageTypeSpecifier.createIndexed(redLut,
899                                                        greenLut,
900                                                        blueLut,
901                                                        alphaLut,
902                                                        bitsPerSample[0],
903                                                        dataType);
904            }
905        }
906
907        // 8-bit gray-alpha
908        if (samplesPerPixel == 2 &&
909            bitsPerSample[0] == 8 &&
910            bitsPerSample[1] == 8) {
911            int dataType = DataBuffer.TYPE_BYTE;
912            boolean alphaPremultiplied = false;
913            if (extraSamples != null &&
914                extraSamples[0] ==
915                BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
916                alphaPremultiplied = true;
917            }
918            //System.out.println("alphaPremultiplied = "+alphaPremultiplied);//XXX
919            return ImageTypeSpecifier.createGrayscale(8,
920                                                      dataType,
921                                                      false,
922                                                      alphaPremultiplied);
923        }
924
925        // 16-bit gray-alpha
926        if (samplesPerPixel == 2 &&
927            bitsPerSample[0] == 16 &&
928            bitsPerSample[1] == 16) {
929            int dataType = sampleFormat[0] == 
930                BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER ?
931                DataBuffer.TYPE_SHORT :
932                DataBuffer.TYPE_USHORT;
933            boolean alphaPremultiplied = false;
934            if (extraSamples != null &&
935                extraSamples[0] ==
936                BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
937                alphaPremultiplied = true;
938            }
939            //System.out.println("alphaPremultiplied = "+alphaPremultiplied);//XXX
940            boolean isSigned = dataType == DataBuffer.TYPE_SHORT;
941            return ImageTypeSpecifier.createGrayscale(16,
942                                                      dataType,
943                                                      isSigned,
944                                                      alphaPremultiplied);
945        }
946
947        ColorSpace rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
948
949        // 8-bit RGB
950        if (samplesPerPixel == 3 &&
951            bitsPerSample[0] == 8 &&
952            bitsPerSample[1] == 8 &&
953            bitsPerSample[2] == 8) {
954            int[] bandOffsets = new int[3];
955            bandOffsets[0] = 0;
956            bandOffsets[1] = 1;
957            bandOffsets[2] = 2;
958            int dataType = DataBuffer.TYPE_BYTE;
959            ColorSpace theColorSpace;
960            if((photometricInterpretation ==
961                BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR &&
962                compression != BaselineTIFFTagSet.COMPRESSION_JPEG &&
963                compression != BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) ||
964               photometricInterpretation ==
965               BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB) {
966                theColorSpace =
967                    ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
968            } else {
969                theColorSpace = rgb;
970            }
971            return ImageTypeSpecifier.createInterleaved(theColorSpace,
972                                                        bandOffsets,
973                                                        dataType,
974                                                        false,
975                                                        false);
976        }
977
978        // 8-bit RGBA
979        if (samplesPerPixel == 4 &&
980            bitsPerSample[0] == 8 &&
981            bitsPerSample[1] == 8 &&
982            bitsPerSample[2] == 8 &&
983            bitsPerSample[3] == 8) {
984            int[] bandOffsets = new int[4];
985            bandOffsets[0] = 0;
986            bandOffsets[1] = 1;
987            bandOffsets[2] = 2;
988            bandOffsets[3] = 3;
989            int dataType = DataBuffer.TYPE_BYTE;
990
991            ColorSpace theColorSpace;
992            boolean hasAlpha;
993            boolean alphaPremultiplied = false;
994            if(photometricInterpretation ==
995               BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK) {
996                theColorSpace = SimpleCMYKColorSpace.getInstance();
997                hasAlpha = false;
998            } else {
999                theColorSpace = rgb;
1000                hasAlpha = true;
1001                if (extraSamples != null &&
1002                    extraSamples[0] ==
1003                    BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1004                    alphaPremultiplied = true;
1005                }
1006            }
1007
1008            return ImageTypeSpecifier.createInterleaved(theColorSpace,
1009                                                        bandOffsets,
1010                                                        dataType,
1011                                                        hasAlpha,
1012                                                        alphaPremultiplied);
1013        }
1014
1015        // 16-bit RGB
1016        if (samplesPerPixel == 3 &&
1017            bitsPerSample[0] == 16 &&
1018            bitsPerSample[1] == 16 &&
1019            bitsPerSample[2] == 16) {
1020            int[] bandOffsets = new int[3];
1021            bandOffsets[0] = 0;
1022            bandOffsets[1] = 1;
1023            bandOffsets[2] = 2;
1024            int dataType = sampleFormat[0] == 
1025                BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER ?
1026                DataBuffer.TYPE_SHORT :
1027                DataBuffer.TYPE_USHORT;
1028            return ImageTypeSpecifier.createInterleaved(rgb,
1029                                                        bandOffsets,
1030                                                        dataType,
1031                                                        false,
1032                                                        false);
1033        }
1034
1035        // 16-bit RGBA
1036        if (samplesPerPixel == 4 &&
1037            bitsPerSample[0] == 16 &&
1038            bitsPerSample[1] == 16 &&
1039            bitsPerSample[2] == 16 &&
1040            bitsPerSample[3] == 16) {
1041            int[] bandOffsets = new int[4];
1042            bandOffsets[0] = 0;
1043            bandOffsets[1] = 1;
1044            bandOffsets[2] = 2;
1045            bandOffsets[3] = 3;
1046            int dataType = sampleFormat[0] == 
1047                BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER ?
1048                DataBuffer.TYPE_SHORT :
1049                DataBuffer.TYPE_USHORT;
1050
1051            boolean alphaPremultiplied = false;
1052            if (extraSamples != null &&
1053                extraSamples[0] ==
1054                BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1055                alphaPremultiplied = true;
1056            }
1057            return ImageTypeSpecifier.createInterleaved(rgb,
1058                                                        bandOffsets,
1059                                                        dataType,
1060                                                        true,
1061                                                        alphaPremultiplied);
1062        }
1063        
1064        // Support for Tiff files containing half-tone data
1065        // in more than 1 channel
1066        if((photometricInterpretation ==
1067            BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK) &&
1068           (bitsPerSample[0] == 1 || bitsPerSample[0] == 2 ||
1069            bitsPerSample[0] == 4)) {
1070            ColorSpace cs = null;
1071            if(samplesPerPixel == 4)
1072                cs = SimpleCMYKColorSpace.getInstance();
1073            else
1074                cs = new BogusColorSpace(samplesPerPixel);
1075            // By specifying the bits per sample the color values
1076            // will scale on display
1077            ColorModel cm =
1078                new ComponentColorModel(cs, bitsPerSample, false, false,
1079                                        Transparency.OPAQUE,
1080                                        DataBuffer.TYPE_BYTE);            
1081            return new ImageTypeSpecifier(cm,
1082                                          cm.createCompatibleSampleModel(1, 1));
1083        }
1084
1085        // Compute bits per pixel.
1086        int totalBits = 0;
1087        for (int i = 0; i < bitsPerSample.length; i++) {
1088            totalBits += bitsPerSample[i];
1089        }
1090
1091        // Packed: 3- or 4-band, 8- or 16-bit.
1092        if ((samplesPerPixel == 3 || samplesPerPixel == 4) &&
1093            (totalBits == 8 || totalBits == 16)) {
1094            int redMask = createMask(bitsPerSample, 0);
1095            int greenMask = createMask(bitsPerSample, 1);
1096            int blueMask = createMask(bitsPerSample, 2);
1097            int alphaMask = (samplesPerPixel == 4) ?
1098                createMask(bitsPerSample, 3) : 0;
1099            int transferType = totalBits == 8 ?
1100                DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT;
1101            boolean alphaPremultiplied = false;
1102            if (extraSamples != null &&
1103                extraSamples[0] ==
1104                BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1105                alphaPremultiplied = true;
1106            }
1107            return ImageTypeSpecifier.createPacked(rgb,
1108                                                   redMask,
1109                                                   greenMask,
1110                                                   blueMask,
1111                                                   alphaMask,
1112                                                   transferType,
1113                                                   alphaPremultiplied);
1114        }
1115
1116        // Generic components with 8X bits per sample.
1117        if(bitsPerSample[0] % 8 == 0) {
1118            // Check whether all bands have same bit depth.
1119            boolean allSameBitDepth = true;
1120            for(int i = 1; i < bitsPerSample.length; i++) {
1121                if(bitsPerSample[i] != bitsPerSample[i-1]) {
1122                    allSameBitDepth = false;
1123                    break;
1124                }
1125            }
1126
1127            // Proceed if all bands have same bit depth.
1128            if(allSameBitDepth) {
1129                // Determine the data type.
1130                int dataType = -1;
1131                boolean isDataTypeSet = false;
1132                switch(bitsPerSample[0]) {
1133                case 8:
1134                    if(sampleFormat[0] !=
1135                       BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) {
1136                        // Ignore whether signed or unsigned:
1137                        // treat all as unsigned.
1138                        dataType = DataBuffer.TYPE_BYTE;
1139                        isDataTypeSet = true;
1140                    }
1141                    break;
1142                case 16:
1143                    if(sampleFormat[0] !=
1144                       BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) {
1145                        if(sampleFormat[0] ==
1146                           BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) {
1147                            dataType = DataBuffer.TYPE_SHORT;
1148                        } else {
1149                            dataType = DataBuffer.TYPE_USHORT;
1150                        }
1151                        isDataTypeSet = true;
1152                    }
1153                    break;
1154                case 32:
1155                    if(sampleFormat[0] ==
1156                       BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) {
1157                        dataType = DataBuffer.TYPE_FLOAT;
1158                    } else {
1159                        dataType = DataBuffer.TYPE_INT;
1160                    }
1161                    isDataTypeSet = true;
1162                    break;
1163                }
1164
1165                if(isDataTypeSet) {
1166                    // Create the SampleModel.
1167                    SampleModel sm = createInterleavedSM(dataType,
1168                                                         samplesPerPixel);
1169
1170                    // Create the ColorModel.
1171                    ColorModel cm;
1172                    if(samplesPerPixel >= 1 && samplesPerPixel <= 4 &&
1173                       (dataType == DataBuffer.TYPE_INT ||
1174                        dataType == DataBuffer.TYPE_FLOAT)) {
1175                        // Handle the 32-bit cases for 1-4 bands.
1176                        ColorSpace cs = samplesPerPixel <= 2 ?
1177                            ColorSpace.getInstance(ColorSpace.CS_GRAY) : rgb;
1178                        boolean hasAlpha = ((samplesPerPixel % 2) == 0);
1179                        boolean alphaPremultiplied = false;
1180                        if(hasAlpha && extraSamples != null &&
1181                           extraSamples[0] ==
1182                           BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1183                            alphaPremultiplied = true;
1184                        }
1185
1186                        cm = createComponentCM(cs,
1187                                               samplesPerPixel,
1188                                               dataType,
1189                                               hasAlpha,
1190                                               alphaPremultiplied);
1191                    } else {
1192                        ColorSpace cs = new BogusColorSpace(samplesPerPixel);
1193                        cm = createComponentCM(cs,
1194                                               samplesPerPixel,
1195                                               dataType,
1196                                               false, // hasAlpha
1197                                               false); // alphaPremultiplied
1198                    }
1199                    //System.out.println(cm); // XXX
1200                    return new ImageTypeSpecifier(cm, sm);
1201                }
1202            }
1203        }
1204
1205        // Other more bizarre cases including discontiguous DataBuffers
1206        // such as for the image in bug 4918959.
1207
1208        if(colorMap == null &&
1209           sampleFormat[0] !=
1210           BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) {
1211
1212            // Determine size of largest sample.
1213            int maxBitsPerSample = 0;
1214            for(int i = 0; i < bitsPerSample.length; i++) {
1215                if(bitsPerSample[i] > maxBitsPerSample) {
1216                    maxBitsPerSample = bitsPerSample[i];
1217                }
1218            }
1219
1220            // Determine whether data are signed.
1221            boolean isSigned =
1222                (sampleFormat[0] ==
1223                 BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER);
1224
1225            // Grayscale
1226            if(samplesPerPixel == 1) {
1227                int dataType =
1228                    getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1229
1230                return ImageTypeSpecifier.createGrayscale(maxBitsPerSample,
1231                                                          dataType,
1232                                                          isSigned);
1233            }
1234
1235            // Gray-alpha
1236            if (samplesPerPixel == 2) {
1237                boolean alphaPremultiplied = false;
1238                if (extraSamples != null &&
1239                    extraSamples[0] ==
1240                    BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1241                    alphaPremultiplied = true;
1242                }
1243
1244                int dataType =
1245                    getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1246
1247                return ImageTypeSpecifier.createGrayscale(maxBitsPerSample,
1248                                                          dataType,
1249                                                          false,
1250                                                          alphaPremultiplied);
1251            }
1252
1253            if (samplesPerPixel == 3 || samplesPerPixel == 4) {
1254                if(totalBits <= 32 && !isSigned) {
1255                    // Packed RGB or RGBA
1256                    int redMask = createMask(bitsPerSample, 0);
1257                    int greenMask = createMask(bitsPerSample, 1);
1258                    int blueMask = createMask(bitsPerSample, 2);
1259                    int alphaMask = (samplesPerPixel == 4) ?
1260                        createMask(bitsPerSample, 3) : 0;
1261                    int transferType =
1262                        getDataTypeFromNumBits(totalBits, false);
1263                    boolean alphaPremultiplied = false;
1264                    if (extraSamples != null &&
1265                        extraSamples[0] ==
1266                        BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1267                        alphaPremultiplied = true;
1268                    }
1269                    return ImageTypeSpecifier.createPacked(rgb,
1270                                                           redMask,
1271                                                           greenMask,
1272                                                           blueMask,
1273                                                           alphaMask,
1274                                                           transferType,
1275                                                           alphaPremultiplied);
1276                } else if(samplesPerPixel == 3) {
1277                    // Interleaved RGB
1278                    int[] bandOffsets = new int[] {0, 1, 2};
1279                    int dataType =
1280                        getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1281                    return ImageTypeSpecifier.createInterleaved(rgb,
1282                                                                bandOffsets,
1283                                                                dataType,
1284                                                                false,
1285                                                                false);
1286                } else if(samplesPerPixel == 4) {
1287                    // Interleaved RGBA
1288                    int[] bandOffsets = new int[] {0, 1, 2, 3};
1289                    int dataType =
1290                        getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1291                    boolean alphaPremultiplied = false;
1292                    if (extraSamples != null &&
1293                        extraSamples[0] ==
1294                        BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1295                        alphaPremultiplied = true;
1296                    }
1297                    return ImageTypeSpecifier.createInterleaved(rgb,
1298                                                                bandOffsets,
1299                                                                dataType,
1300                                                                true,
1301                                                                alphaPremultiplied);
1302                }
1303            } else {
1304                // Arbitrary Interleaved.
1305                int dataType =
1306                    getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1307                SampleModel sm = createInterleavedSM(dataType,
1308                                                     samplesPerPixel);
1309                ColorSpace cs = new BogusColorSpace(samplesPerPixel);
1310                ColorModel cm = createComponentCM(cs,
1311                                                  samplesPerPixel,
1312                                                  dataType,
1313                                                  false, // hasAlpha
1314                                                  false); // alphaPremultiplied
1315                return new ImageTypeSpecifier(cm, sm);
1316            }
1317        }
1318
1319        if(DEBUG) {
1320            System.out.println("\nNo raw ITS available:");
1321
1322            System.out.println("photometricInterpretation = " +
1323                               photometricInterpretation);
1324            System.out.println("compression = " + compression);
1325            System.out.println("samplesPerPixel = " + samplesPerPixel);
1326            if (bitsPerSample != null) {
1327                for (int i = 0; i < bitsPerSample.length; i++) {
1328                    System.out.println("bitsPerSample[" + i + "] = " +
1329                                       (int)bitsPerSample[i]);
1330                }
1331            }
1332            if (sampleFormat != null) {
1333                for (int i = 0; i < sampleFormat.length; i++) {
1334                    System.out.println("sampleFormat[" + i + "] = " +
1335                                       (int)sampleFormat[i]);
1336                }
1337            }
1338            if (extraSamples != null) {
1339                for (int i = 0; i < extraSamples.length; i++) {
1340                    System.out.println("extraSamples[" + i + "] = " +
1341                                       (int)extraSamples[i]);
1342                }
1343            }
1344            System.out.println("colorMap = " + colorMap);
1345            if (colorMap != null) {
1346                System.out.println("colorMap.length = " + colorMap.length);
1347            }
1348
1349            throw new RuntimeException("Unable to create an ImageTypeSpecifier");
1350        }
1351
1352        return null;
1353    }
1354
1355    /**
1356     * Sets the value of the <code>reader</code> field.
1357     *
1358     * <p> If this method is called, the <code>beginDecoding</code>
1359     * method must be called prior to calling any of the decode
1360     * methods.
1361     *
1362     * @param reader the current <code>ImageReader</code>.
1363     */
1364    public void setReader(ImageReader reader) {
1365        this.reader = reader;
1366    }
1367
1368    /**
1369     * Sets the value of the <code>metadata</code> field.
1370     *
1371     * <p> If this method is called, the <code>beginDecoding</code>
1372     * method must be called prior to calling any of the decode
1373     * methods.
1374     *
1375     * @param metadata the <code>IIOMetadata</code> object for the
1376     * image being read.
1377     */
1378    public void setMetadata(IIOMetadata metadata) {
1379        this.metadata = metadata;
1380    }
1381
1382    /**
1383     * Sets the value of the <code>photometricInterpretation</code>
1384     * field.
1385     *
1386     * <p> If this method is called, the <code>beginDecoding</code>
1387     * method must be called prior to calling any of the decode
1388     * methods.
1389     *
1390     * @param photometricInterpretation the photometric interpretation
1391     * value.
1392     */
1393    public void setPhotometricInterpretation(int photometricInterpretation) {
1394        this.photometricInterpretation = photometricInterpretation;
1395    }
1396
1397    /**
1398     * Sets the value of the <code>compression</code> field.
1399     *
1400     * <p> If this method is called, the <code>beginDecoding</code>
1401     * method must be called prior to calling any of the decode
1402     * methods.
1403     *
1404     * @param compression the compression type. 
1405     */
1406    public void setCompression(int compression) {
1407        this.compression = compression;
1408    }
1409
1410    /**
1411     * Sets the value of the <code>planar</code> field.
1412     *
1413     * <p> If this method is called, the <code>beginDecoding</code>
1414     * method must be called prior to calling any of the decode
1415     * methods.
1416     *
1417     * @param planar <code>true</code> if the image to be decoded is
1418     * stored in planar format.
1419     */
1420    public void setPlanar(boolean planar) {
1421        this.planar = planar;
1422    }
1423
1424    /**
1425     * Sets the value of the <code>samplesPerPixel</code> field.
1426     *
1427     * <p> If this method is called, the <code>beginDecoding</code>
1428     * method must be called prior to calling any of the decode
1429     * methods.
1430     *
1431     * @param samplesPerPixel the number of samples in each source
1432     * pixel.
1433     */
1434    public void setSamplesPerPixel(int samplesPerPixel) {
1435        this.samplesPerPixel = samplesPerPixel;
1436    }
1437
1438    /**
1439     * Sets the value of the <code>bitsPerSample</code> field.
1440     *
1441     * <p> If this method is called, the <code>beginDecoding</code>
1442     * method must be called prior to calling any of the decode
1443     * methods.
1444     *
1445     * @param bitsPerSample the number of bits for each source image
1446     * sample.
1447     */
1448    public void setBitsPerSample(int[] bitsPerSample) {
1449        this.bitsPerSample = bitsPerSample == null ?
1450            null : (int[])bitsPerSample.clone();
1451    }
1452
1453    /**
1454     * Sets the value of the <code>sampleFormat</code> field.
1455     *
1456     * <p> If this method is called, the <code>beginDecoding</code>
1457     * method must be called prior to calling any of the decode
1458     * methods.
1459     *
1460     * @param sampleFormat the format of the source image data,
1461     * for example unsigned integer or floating-point.
1462     */
1463    public void setSampleFormat(int[] sampleFormat) {
1464        this.sampleFormat = sampleFormat == null ?
1465            new int[] {BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER} :
1466            (int[])sampleFormat.clone();
1467    }
1468
1469    /**
1470     * Sets the value of the <code>extraSamples</code> field.
1471     *
1472     * <p> If this method is called, the <code>beginDecoding</code>
1473     * method must be called prior to calling any of the decode
1474     * methods.
1475     *
1476     * @param extraSamples the interpretation of any samples in the
1477     * source file beyond those used for basic color or grayscale
1478     * information.
1479     */
1480    public void setExtraSamples(int[] extraSamples) {
1481        this.extraSamples = extraSamples == null ?
1482            null : (int[])extraSamples.clone();
1483    }
1484    
1485    /**
1486     * Sets the value of the <code>colorMap</code> field.
1487     *
1488     * <p> If this method is called, the <code>beginDecoding</code>
1489     * method must be called prior to calling any of the decode
1490     * methods.
1491     *
1492     * @param colorMap the color map to apply to the source data,
1493     * as an array of <code>char</code>s.
1494     */
1495    public void setColorMap(char[] colorMap) {
1496        this.colorMap = colorMap == null ?
1497            null : (char[])colorMap.clone();
1498    }
1499
1500    /**
1501     * Sets the value of the <code>stream</code> field.
1502     *
1503     * <p> If this method is called, the <code>beginDecoding</code>
1504     * method must be called prior to calling any of the decode
1505     * methods.
1506     *
1507     * @param stream the <code>ImageInputStream</code> to be read.
1508     */
1509    public void setStream(ImageInputStream stream) {
1510        this.stream = stream;
1511    }
1512
1513    /**
1514     * Sets the value of the <code>offset</code> field.
1515     *
1516     * <p> If this method is called, the <code>beginDecoding</code>
1517     * method must be called prior to calling any of the decode
1518     * methods.
1519     *
1520     * @param offset the offset of the beginning of the compressed
1521     * data.
1522     */
1523    public void setOffset(long offset) {
1524        this.offset = offset;
1525    }
1526
1527    /**
1528     * Sets the value of the <code>byteCount</code> field.
1529     *
1530     * <p> If this method is called, the <code>beginDecoding</code>
1531     * method must be called prior to calling any of the decode
1532     * methods.
1533     *
1534     * @param byteCount the number of bytes of compressed data.
1535     */
1536    public void setByteCount(int byteCount) {
1537        this.byteCount = byteCount;
1538    }
1539
1540    // Region of the file image represented in the stream
1541
1542    /**
1543     * Sets the value of the <code>srcMinX</code> field.
1544     *
1545     * <p> If this method is called, the <code>beginDecoding</code>
1546     * method must be called prior to calling any of the decode
1547     * methods.
1548     *
1549     * @param srcMinX the minimum X coordinate of the source region
1550     * being decoded, irrespective of how it will be copied into the
1551     * destination.
1552     */
1553    public void setSrcMinX(int srcMinX) {
1554        this.srcMinX = srcMinX;
1555    }
1556    
1557    /**
1558     * Sets the value of the <code>srcMinY</code> field.
1559     *
1560     * <p> If this method is called, the <code>beginDecoding</code>
1561     * method must be called prior to calling any of the decode
1562     * methods.
1563     *
1564     * @param srcMinY the minimum Y coordinate of the source region
1565     * being decoded, irrespective of how it will be copied into the
1566     * destination.
1567     */
1568    public void setSrcMinY(int srcMinY) {
1569        this.srcMinY = srcMinY;
1570    }
1571    
1572    /**
1573     * Sets the value of the <code>srcWidth</code> field.
1574     *
1575     * <p> If this method is called, the <code>beginDecoding</code>
1576     * method must be called prior to calling any of the decode
1577     * methods.
1578     *
1579     * @param srcWidth the width of the source region being decoded,
1580     * irrespective of how it will be copied into the destination.
1581     */
1582    public void setSrcWidth(int srcWidth) {
1583        this.srcWidth = srcWidth;
1584    }
1585    
1586    /**
1587     * Sets the value of the <code>srcHeight</code> field.
1588     *
1589     * <p> If this method is called, the <code>beginDecoding</code>
1590     * method must be called prior to calling any of the decode
1591     * methods.
1592     *
1593     * @param srcHeight the height of the source region being decoded,
1594     * irrespective of how it will be copied into the destination.
1595     */
1596    public void setSrcHeight(int srcHeight) {
1597        this.srcHeight = srcHeight;
1598    }
1599
1600    // First source pixel to be read
1601
1602    /**
1603     * Sets the value of the <code>sourceXOffset</code> field.
1604     *
1605     * <p> If this method is called, the <code>beginDecoding</code>
1606     * method must be called prior to calling any of the decode
1607     * methods.
1608     *
1609     * @param sourceXOffset the horizontal source offset to be used when
1610     * mapping between source and destination coordinates.
1611     */
1612    public void setSourceXOffset(int sourceXOffset) {
1613        this.sourceXOffset = sourceXOffset;
1614    }
1615
1616    /**
1617     * Sets the value of the <code>dstXOffset</code> field.
1618     *
1619     * <p> If this method is called, the <code>beginDecoding</code>
1620     * method must be called prior to calling any of the decode
1621     * methods.
1622     *
1623     * @param dstXOffset the horizontal destination offset to be
1624     * used when mapping between source and destination coordinates.
1625     */
1626    public void setDstXOffset(int dstXOffset) {
1627        this.dstXOffset = dstXOffset;
1628    }
1629
1630    /**
1631     * Sets the value of the <code>sourceYOffset</code>.
1632     *
1633     * <p> If this method is called, the <code>beginDecoding</code>
1634     * method must be called prior to calling any of the decode
1635     * methods.
1636     *
1637     * @param sourceYOffset the vertical source offset to be used when
1638     * mapping between source and destination coordinates.
1639     */
1640    public void setSourceYOffset(int sourceYOffset) {
1641        this.sourceYOffset = sourceYOffset;
1642    }
1643
1644    /**
1645     * Sets the value of the <code>dstYOffset</code> field.
1646     *
1647     * <p> If this method is called, the <code>beginDecoding</code>
1648     * method must be called prior to calling any of the decode
1649     * methods.
1650     *
1651     * @param dstYOffset the vertical destination offset to be
1652     * used when mapping between source and destination coordinates.
1653     */
1654    public void setDstYOffset(int dstYOffset) {
1655        this.dstYOffset = dstYOffset;
1656    }
1657
1658    // Subsampling to be performed
1659
1660    /**
1661     * Sets the value of the <code>subsampleX</code> field.
1662     *
1663     * <p> If this method is called, the <code>beginDecoding</code>
1664     * method must be called prior to calling any of the decode
1665     * methods.
1666     *
1667     * @param subsampleX the horizontal subsampling factor.
1668     *
1669     * @throws IllegalArgumentException if <code>subsampleX</code> is
1670     * less than or equal to 0.
1671     */
1672    public void setSubsampleX(int subsampleX) {
1673        if (subsampleX <= 0) {
1674            throw new IllegalArgumentException("subsampleX <= 0!");
1675        }
1676        this.subsampleX = subsampleX;
1677    }
1678    
1679    /**
1680     * Sets the value of the <code>subsampleY</code> field.
1681     *
1682     * <p> If this method is called, the <code>beginDecoding</code>
1683     * method must be called prior to calling any of the decode
1684     * methods.
1685     *
1686     * @param subsampleY the vertical subsampling factor.
1687     *
1688     * @throws IllegalArgumentException if <code>subsampleY</code> is
1689     * less than or equal to 0.
1690     */
1691    public void setSubsampleY(int subsampleY) {
1692        if (subsampleY <= 0) {
1693            throw new IllegalArgumentException("subsampleY <= 0!");
1694        }
1695        this.subsampleY = subsampleY;
1696    }
1697    
1698    // Band subsetting/rearrangement
1699
1700    /**
1701     * Sets the value of the <code>sourceBands</code> field.
1702     *
1703     * <p> If this method is called, the <code>beginDecoding</code>
1704     * method must be called prior to calling any of the decode
1705     * methods.
1706     *
1707     * @param sourceBands an array of <code>int</code>s
1708     * specifying the source bands to be read.
1709     */
1710    public void setSourceBands(int[] sourceBands) {
1711        this.sourceBands = sourceBands == null ?
1712            null : (int[])sourceBands.clone();
1713    }
1714
1715    /**
1716     * Sets the value of the <code>destinationBands</code> field.
1717     *
1718     * <p> If this method is called, the <code>beginDecoding</code>
1719     * method must be called prior to calling any of the decode
1720     * methods.
1721     *
1722     * @param destinationBands an array of <code>int</code>s
1723     * specifying the destination bands to be written.
1724     */
1725    public void setDestinationBands(int[] destinationBands) {
1726        this.destinationBands = destinationBands == null ?
1727            null : (int[])destinationBands.clone();
1728    }
1729
1730    // Destination image and region
1731
1732    /**
1733     * Sets the value of the <code>image</code> field.
1734     *
1735     * <p> If this method is called, the <code>beginDecoding</code>
1736     * method must be called prior to calling any of the decode
1737     * methods.
1738     *
1739     * @param image the destination <code>BufferedImage</code>.
1740     */
1741    public void setImage(BufferedImage image) {
1742        this.image = image;
1743    }
1744    
1745    /**
1746     * Sets the value of the <code>dstMinX</code> field.
1747     *
1748     * <p> If this method is called, the <code>beginDecoding</code>
1749     * method must be called prior to calling any of the decode
1750     * methods.
1751     *
1752     * @param dstMinX the minimum X coordinate of the destination
1753     * region. 
1754     */
1755    public void setDstMinX(int dstMinX) {
1756        this.dstMinX = dstMinX;
1757    }
1758    
1759    /**
1760     * Sets the value of the <code>dstMinY</code> field.
1761     *
1762     * <p> If this method is called, the <code>beginDecoding</code>
1763     * method must be called prior to calling any of the decode
1764     * methods.
1765     *
1766     * @param dstMinY the minimum Y coordinate of the destination
1767     * region.
1768     */
1769    public void setDstMinY(int dstMinY) {
1770        this.dstMinY = dstMinY;
1771    }
1772    
1773    /**
1774     * Sets the value of the <code>dstWidth</code> field.
1775     *
1776     * <p> If this method is called, the <code>beginDecoding</code>
1777     * method must be called prior to calling any of the decode
1778     * methods.
1779     *
1780     * @param dstWidth the width of the destination region.
1781     */
1782    public void setDstWidth(int dstWidth) {
1783        this.dstWidth = dstWidth;
1784    }
1785
1786    /**
1787     * Sets the value of the <code>dstHeight</code> field.
1788     *
1789     * <p> If this method is called, the <code>beginDecoding</code>
1790     * method must be called prior to calling any of the decode
1791     * methods.
1792     *
1793     * @param dstHeight the height of the destination region.
1794     */
1795    public void setDstHeight(int dstHeight) {
1796        this.dstHeight = dstHeight;
1797    }
1798
1799    // Active source region
1800
1801    /**
1802     * Sets the value of the <code>activeSrcMinX</code> field.
1803     *
1804     * <p> If this method is called, the <code>beginDecoding</code>
1805     * method must be called prior to calling any of the decode
1806     * methods.
1807     *
1808     * @param activeSrcMinX the minimum X coordinate of the active
1809     * source region.
1810     */
1811    public void setActiveSrcMinX(int activeSrcMinX) {
1812        this.activeSrcMinX = activeSrcMinX;
1813    }
1814    
1815    /**
1816     * Sets the value of the <code>activeSrcMinY</code> field.
1817     *
1818     * <p> If this method is called, the <code>beginDecoding</code>
1819     * method must be called prior to calling any of the decode
1820     * methods.
1821     *
1822     * @param activeSrcMinY the minimum Y coordinate of the active
1823     * source region.
1824     */
1825    public void setActiveSrcMinY(int activeSrcMinY) {
1826        this.activeSrcMinY = activeSrcMinY;
1827    }
1828    
1829    /**
1830     * Sets the value of the <code>activeSrcWidth</code> field.
1831     *
1832     * <p> If this method is called, the <code>beginDecoding</code>
1833     * method must be called prior to calling any of the decode
1834     * methods.
1835     *
1836     * @param activeSrcWidth the width of the active source region.
1837     */
1838    public void setActiveSrcWidth(int activeSrcWidth) {
1839        this.activeSrcWidth = activeSrcWidth;
1840    }
1841    
1842    /**
1843     * Sets the value of the <code>activeSrcHeight</code> field.
1844     *
1845     * <p> If this method is called, the <code>beginDecoding</code>
1846     * method must be called prior to calling any of the decode
1847     * methods.
1848     *
1849     * @param activeSrcHeight the height of the active source region.
1850     */
1851    public void setActiveSrcHeight(int activeSrcHeight) {
1852        this.activeSrcHeight = activeSrcHeight;
1853    }
1854
1855    /**
1856     * Sets the <code>TIFFColorConverter</code> object describing the color
1857     * space of the encoded data in the input stream.  If no
1858     * <code>TIFFColorConverter</code> is set, no conversion will be performed.
1859     *
1860     * @param colorConverter a <code>TIFFColorConverter</code> object, or
1861     * <code>null</code>.
1862     */
1863    public void setColorConverter(TIFFColorConverter colorConverter) {
1864        this.colorConverter = colorConverter;
1865    }
1866
1867    /**
1868     * Returns an <code>ImageTypeSpecifier</code> describing an image
1869     * whose underlying data array has the same format as the raw
1870     * source pixel data.
1871     *
1872     * @return an <code>ImageTypeSpecifier</code>.
1873     */
1874    public ImageTypeSpecifier getRawImageType() {
1875        ImageTypeSpecifier its =
1876            getRawImageTypeSpecifier(photometricInterpretation,
1877                                     compression,
1878                                     samplesPerPixel,
1879                                     bitsPerSample,
1880                                     sampleFormat,
1881                                     extraSamples,
1882                                     colorMap);
1883        return its;
1884    }
1885
1886    /**
1887     * Creates a <code>BufferedImage</code> whose underlying data
1888     * array will be suitable for holding the raw decoded output of
1889     * the <code>decodeRaw</code> method.
1890     *
1891     * <p> The default implementation calls
1892     * <code>getRawImageType</code>, and calls the resulting
1893     * <code>ImageTypeSpecifier</code>'s
1894     * <code>createBufferedImage</code> method.
1895     *
1896     * @return a <code>BufferedImage</code> whose underlying data
1897     * array has the same format as the raw source pixel data, or
1898     * <code>null</code> if it is not possible to create such an
1899     * image.
1900     */
1901    public BufferedImage createRawImage() { 
1902        if (planar) {
1903            // Create a single-banded image of the appropriate data type.
1904
1905            // Get the number of bits per sample.
1906            int bps = bitsPerSample[sourceBands[0]];
1907
1908            // Determine the data type.
1909            int dataType;
1910            if(sampleFormat[0] ==
1911               BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) {
1912                dataType = DataBuffer.TYPE_FLOAT;
1913            } else if(bps <= 8) {
1914                dataType = DataBuffer.TYPE_BYTE;
1915            } else if(bps <= 16) {
1916                if(sampleFormat[0] ==
1917                   BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) {
1918                    dataType = DataBuffer.TYPE_SHORT;
1919                } else {
1920                    dataType = DataBuffer.TYPE_USHORT;
1921                }
1922            } else {
1923                dataType = DataBuffer.TYPE_INT;
1924            }
1925
1926            ColorSpace csGray = ColorSpace.getInstance(ColorSpace.CS_GRAY);
1927            
1928            ImageTypeSpecifier its = null;
1929            // For planar images with 1, 2 or 4 bits per sample, we need to
1930            // use a MultiPixelPackedSampleModel so that when the TIFF
1931            // decoder properly decodes the data per pixel, we know how to
1932            // extract it back out into individual pixels.  This is how the
1933            // pixels are actually stored in the planar bands.
1934            if(bps == 1 || bps == 2 || bps == 4) {
1935                int bits = bps;
1936                int size = 1 << bits;
1937                byte[] r = new byte[size];
1938                byte[] g = new byte[size];
1939                byte[] b = new byte[size];
1940                for(int j=0; j<r.length; j++) {
1941                    r[j] = 0;
1942                    g[j] = 0;
1943                    b[j] = 0;
1944                }
1945                ColorModel cmGray= new IndexColorModel(bits,size,r,g,b);
1946                SampleModel smGray = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, 1, 1, bits);
1947                its = new ImageTypeSpecifier(cmGray, smGray);
1948            }
1949            else {
1950                its = ImageTypeSpecifier.createInterleaved(csGray,
1951                                                     new int[] {0},
1952                                                     dataType,
1953                                                     false,
1954                                                     false);
1955            }
1956
1957            return its.createBufferedImage(srcWidth, srcHeight);
1958
1959            /* XXX Not necessarily byte for planar
1960            return new BufferedImage(srcWidth, srcHeight,
1961                                     BufferedImage.TYPE_BYTE_GRAY);
1962            */
1963        } else {
1964            ImageTypeSpecifier its = getRawImageType();
1965            if (its == null) {
1966                return null;
1967            }
1968            
1969            BufferedImage bi = its.createBufferedImage(srcWidth, srcHeight);
1970            return bi;
1971        }
1972    }
1973
1974    /**
1975     * Decodes the source data into the provided <code>byte</code>
1976     * array <code>b</code>, starting at the offset given by
1977     * <code>dstOffset</code>.  Each pixel occupies
1978     * <code>bitsPerPixel</code> bits, with no padding between pixels.
1979     * Scanlines are separated by <code>scanlineStride</code>
1980     * <code>byte</code>s.
1981     *
1982     * @param b a <code>byte</code> array to be written.
1983     * @param dstOffset the starting offset in <code>b</code> to be
1984     * written.
1985     * @param bitsPerPixel the number of bits for each pixel.
1986     * @param scanlineStride the number of <code>byte</code>s to
1987     * advance between that starting pixels of each scanline.
1988     *
1989     * @throws IOException if an error occurs reading from the source
1990     * <code>ImageInputStream</code>.
1991     */
1992    public abstract void decodeRaw(byte[] b,
1993                                   int dstOffset,
1994                                   int bitsPerPixel,
1995                                   int scanlineStride) throws IOException;
1996
1997    /**
1998     * Decodes the source data into the provided <code>short</code>
1999     * array <code>s</code>, starting at the offset given by
2000     * <code>dstOffset</code>.  Each pixel occupies
2001     * <code>bitsPerPixel</code> bits, with no padding between pixels.
2002     * Scanlines are separated by <code>scanlineStride</code>
2003     * <code>short</code>s
2004     *
2005     * <p> The default implementation calls <code>decodeRaw(byte[] b,
2006     * ...)</code> and copies the resulting data into <code>s</code>.
2007     *
2008     * @param s a <code>short</code> array to be written.
2009     * @param dstOffset the starting offset in <code>s</code> to be
2010     * written.
2011     * @param bitsPerPixel the number of bits for each pixel.
2012     * @param scanlineStride the number of <code>short</code>s to
2013     * advance between that starting pixels of each scanline.
2014     *
2015     * @throws IOException if an error occurs reading from the source
2016     * <code>ImageInputStream</code>.
2017     */
2018    public void decodeRaw(short[] s,
2019                          int dstOffset,
2020                          int bitsPerPixel,
2021                          int scanlineStride) throws IOException {
2022        int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8;
2023        int shortsPerRow = bytesPerRow/2;
2024
2025        byte[] b = new byte[bytesPerRow*srcHeight];
2026        decodeRaw(b, 0, bitsPerPixel, bytesPerRow);
2027
2028        int bOffset = 0;
2029        if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) {
2030            for (int j = 0; j < srcHeight; j++) {
2031                for (int i = 0; i < shortsPerRow; i++) {
2032                    short hiVal = b[bOffset++];
2033                    short loVal = b[bOffset++];
2034                    short sval = (short)((hiVal << 8) | (loVal & 0xff));
2035                    s[dstOffset + i] = sval;
2036                }
2037
2038                dstOffset += scanlineStride;
2039            }
2040        } else { // ByteOrder.LITLE_ENDIAN
2041            for (int j = 0; j < srcHeight; j++) {
2042                for (int i = 0; i < shortsPerRow; i++) {
2043                    short loVal = b[bOffset++];
2044                    short hiVal = b[bOffset++];
2045                    short sval = (short)((hiVal << 8) | (loVal & 0xff));
2046                    s[dstOffset + i] = sval;
2047                }
2048
2049                dstOffset += scanlineStride;
2050            }
2051        }
2052    }
2053
2054    /**
2055     * Decodes the source data into the provided <code>int</code>
2056     * array <code>i</code>, starting at the offset given by
2057     * <code>dstOffset</code>.  Each pixel occupies
2058     * <code>bitsPerPixel</code> bits, with no padding between pixels.
2059     * Scanlines are separated by <code>scanlineStride</code>
2060     * <code>int</code>s.
2061     *
2062     * <p> The default implementation calls <code>decodeRaw(byte[] b,
2063     * ...)</code> and copies the resulting data into <code>i</code>.
2064     *
2065     * @param i an <code>int</code> array to be written.
2066     * @param dstOffset the starting offset in <code>i</code> to be
2067     * written.
2068     * @param bitsPerPixel the number of bits for each pixel.
2069     * @param scanlineStride the number of <code>int</code>s to
2070     * advance between that starting pixels of each scanline.
2071     *
2072     * @throws IOException if an error occurs reading from the source
2073     * <code>ImageInputStream</code>.
2074     */
2075    public void decodeRaw(int[] i,
2076                          int dstOffset,
2077                          int bitsPerPixel,
2078                          int scanlineStride) throws IOException {
2079        int numBands = bitsPerPixel/32;
2080        int intsPerRow = srcWidth*numBands;
2081        int bytesPerRow = intsPerRow*4;
2082
2083        byte[] b = new byte[bytesPerRow*srcHeight];
2084        decodeRaw(b, 0, bitsPerPixel, bytesPerRow);
2085
2086        int bOffset = 0;
2087        if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) {
2088            for (int j = 0; j < srcHeight; j++) {
2089                for (int k = 0; k < intsPerRow; k++) {
2090                    int v0 = b[bOffset++] & 0xff;
2091                    int v1 = b[bOffset++] & 0xff; 
2092                    int v2 = b[bOffset++] & 0xff;
2093                    int v3 = b[bOffset++] & 0xff;
2094                    int ival = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
2095                    i[dstOffset + k] = ival;
2096                }
2097
2098                dstOffset += scanlineStride;
2099            }
2100        } else { // ByteOrder.LITLE_ENDIAN
2101            for (int j = 0; j < srcHeight; j++) {
2102                for (int k = 0; k < intsPerRow; k++) {
2103                    int v3 = b[bOffset++] & 0xff;
2104                    int v2 = b[bOffset++] & 0xff; 
2105                    int v1 = b[bOffset++] & 0xff;
2106                    int v0 = b[bOffset++] & 0xff;
2107                    int ival = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
2108                    i[dstOffset + k] = ival;
2109                }
2110
2111                dstOffset += scanlineStride;
2112            }
2113        }
2114    }
2115
2116    /**
2117     * Decodes the source data into the provided <code>float</code>
2118     * array <code>f</code>, starting at the offset given by
2119     * <code>dstOffset</code>.  Each pixel occupies
2120     * <code>bitsPerPixel</code> bits, with no padding between pixels.
2121     * Scanlines are separated by <code>scanlineStride</code>
2122     * <code>float</code>s.
2123     *
2124     * <p> The default implementation calls <code>decodeRaw(byte[] b,
2125     * ...)</code> and copies the resulting data into <code>f</code>.
2126     *
2127     * @param f a <code>float</code> array to be written.
2128     * @param dstOffset the starting offset in <code>f</code> to be
2129     * written.
2130     * @param bitsPerPixel the number of bits for each pixel.
2131     * @param scanlineStride the number of <code>float</code>s to
2132     * advance between that starting pixels of each scanline.
2133     *
2134     * @throws IOException if an error occurs reading from the source
2135     * <code>ImageInputStream</code>.
2136     */
2137    public void decodeRaw(float[] f,
2138                          int dstOffset,
2139                          int bitsPerPixel,
2140                          int scanlineStride) throws IOException {
2141        int numBands = bitsPerPixel/32;
2142        int floatsPerRow = srcWidth*numBands;
2143        int bytesPerRow = floatsPerRow*4;
2144
2145        byte[] b = new byte[bytesPerRow*srcHeight];
2146        decodeRaw(b, 0, bitsPerPixel, bytesPerRow);
2147
2148        int bOffset = 0;
2149        if(stream.getByteOrder() == ByteOrder.BIG_ENDIAN) {
2150            for (int j = 0; j < srcHeight; j++) {
2151                for (int i = 0; i < floatsPerRow; i++) {
2152                    int v0 = b[bOffset++] & 0xff;
2153                    int v1 = b[bOffset++] & 0xff; 
2154                    int v2 = b[bOffset++] & 0xff;
2155                    int v3 = b[bOffset++] & 0xff;
2156                    int ival = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
2157                    float fval = Float.intBitsToFloat(ival);
2158                    f[dstOffset + i] = fval;
2159                }
2160
2161                dstOffset += scanlineStride;
2162            }
2163        } else { // ByteOrder.LITLE_ENDIAN
2164            for (int j = 0; j < srcHeight; j++) {
2165                for (int i = 0; i < floatsPerRow; i++) {
2166                    int v3 = b[bOffset++] & 0xff;
2167                    int v2 = b[bOffset++] & 0xff; 
2168                    int v1 = b[bOffset++] & 0xff;
2169                    int v0 = b[bOffset++] & 0xff;
2170                    int ival = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
2171                    float fval = Float.intBitsToFloat(ival);
2172                    f[dstOffset + i] = fval;
2173                }
2174
2175                dstOffset += scanlineStride;
2176            }
2177        }
2178    }
2179
2180    //
2181    // Values used to prevent unneeded recalculation of bit adjustment table.
2182    //
2183    private boolean isFirstBitDepthTable = true;
2184    private boolean planarCache = false;
2185    private int[] destBitsPerSampleCache = null;
2186    private int[] sourceBandsCache = null;
2187    private int[] bitsPerSampleCache = null;
2188    private int[] destinationBandsCache = null;
2189
2190    /**
2191     * This routine is called prior to a sequence of calls to the
2192     * <code>decode</code> method, in order to allow any necessary
2193     * tables or other structures to be initialized based on metadata
2194     * values.  This routine is guaranteed to be called any time the
2195     * metadata values have changed.
2196     *
2197     * <p> The default implementation computes tables used by the
2198     * <code>decode</code> method to rescale components to different
2199     * bit depths.  Thus, if this method is overridden, it is
2200     * important for the subclass method to call <code>super()</code>,
2201     * unless it overrides <code>decode</code> as well.
2202     */
2203    public void beginDecoding() {
2204        // Note: This method assumes that sourceBands, destinationBands,
2205        // and bitsPerSample are all non-null which is true as they are
2206        // set up that way in TIFFImageReader. Also the lengths and content
2207        // of sourceBands and destinationBands are checked in TIFFImageReader
2208        // before the present method is invoked.
2209
2210        // Determine if all of the relevant output bands have the
2211        // same bit depth as the source data
2212        this.adjustBitDepths = false;
2213        int numBands = destinationBands.length;
2214        int[] destBitsPerSample = null;
2215        if(planar) {
2216            int totalNumBands = bitsPerSample.length;
2217            destBitsPerSample = new int[totalNumBands];
2218            int dbps = image.getSampleModel().getSampleSize(0);
2219            for(int b = 0; b < totalNumBands; b++) {
2220                destBitsPerSample[b] = dbps;
2221            }
2222        } else {
2223            destBitsPerSample = image.getSampleModel().getSampleSize();
2224        }
2225
2226        // Make sure that the image is not CMYK (separated) or does not have
2227        // bits per sample of 1, 2, or 4 before trying adjust.
2228        if(photometricInterpretation !=
2229           BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK || 
2230           bitsPerSample[0] != 1 && bitsPerSample[0] != 2 &&
2231           bitsPerSample[0] != 4) {
2232            for (int b = 0; b < numBands; b++) {
2233                if (destBitsPerSample[destinationBands[b]] !=
2234                    bitsPerSample[sourceBands[b]]) {
2235                    adjustBitDepths = true;
2236                    break;
2237                }
2238            }
2239        }
2240
2241        // If the bit depths differ, create a lookup table
2242        // per band to perform the conversion
2243        if(adjustBitDepths) {
2244            // Compute the table only if this is the first time one is
2245            // being computed or if any of the variables on which the
2246            // table is based have changed.
2247            if(this.isFirstBitDepthTable ||
2248               planar != planarCache ||
2249               !areIntArraysEqual(destBitsPerSample,
2250                                  destBitsPerSampleCache) ||
2251               !areIntArraysEqual(sourceBands,
2252                                  sourceBandsCache) ||
2253               !areIntArraysEqual(bitsPerSample,
2254                                  bitsPerSampleCache) ||
2255               !areIntArraysEqual(destinationBands,
2256                                  destinationBandsCache)) {
2257
2258                this.isFirstBitDepthTable = false;
2259
2260                // Cache some variables.
2261                this.planarCache = planar;
2262                this.destBitsPerSampleCache =
2263                    (int[])destBitsPerSample.clone(); // never null ...
2264                this.sourceBandsCache = sourceBands == null ?
2265                    null : (int[])sourceBands.clone();
2266                this.bitsPerSampleCache = bitsPerSample == null ?
2267                    null : (int[])bitsPerSample.clone();
2268                this.destinationBandsCache = destinationBands == null ?
2269                    null : (int[])destinationBands.clone();
2270
2271                // Allocate and fill the table.
2272                bitDepthScale = new int[numBands][];
2273                for (int b = 0; b < numBands; b++) {
2274                    int maxInSample = (1 << bitsPerSample[sourceBands[b]]) - 1;
2275                    int halfMaxInSample = maxInSample/2;
2276
2277                    int maxOutSample =
2278                        (1 << destBitsPerSample[destinationBands[b]]) - 1;
2279
2280                    bitDepthScale[b] = new int[maxInSample + 1];
2281                    for (int s = 0; s <= maxInSample; s++) {
2282                        bitDepthScale[b][s] =
2283                            (s*maxOutSample + halfMaxInSample)/
2284                            maxInSample;
2285                    }
2286                }
2287            }
2288        } else { // !adjustBitDepths
2289            // Clear any prior table.
2290            this.bitDepthScale = null;
2291        }
2292
2293        // Determine whether source and destination band lists are ramps.
2294        // Note that these conditions will be true for planar images if
2295        // and only if samplesPerPixel == 1, sourceBands[0] == 0, and
2296        // destinationBands[0] == 0. For the purposes of this method, the
2297        // only difference between such a planar image and a chunky image
2298        // is the setting of the PlanarConfiguration field.
2299        boolean sourceBandsNormal = false;
2300        boolean destinationBandsNormal = false;
2301        if (numBands == samplesPerPixel) {
2302            sourceBandsNormal = true;
2303            destinationBandsNormal = true;
2304            for (int i = 0; i < numBands; i++) {
2305                if (sourceBands[i] != i) {
2306                    sourceBandsNormal = false;
2307                }
2308                if (destinationBands[i] != i) {
2309                    destinationBandsNormal = false;
2310                }
2311            }
2312        }
2313
2314        // Determine whether the image is bilevel and/or contiguous.
2315        // Note that a planar image could be bilevel but it will not
2316        // be contiguous unless it has a single component band stored
2317        // in a single bank.
2318        this.isBilevel =
2319            ImageUtil.isBinary(this.image.getRaster().getSampleModel());
2320        this.isContiguous = this.isBilevel ?
2321            true : ImageUtil.imageIsContiguous(this.image);
2322
2323        // Analyze destination image to see if we can copy into it
2324        // directly
2325
2326        this.isImageSimple =
2327            (colorConverter == null) &&
2328            (subsampleX == 1) && (subsampleY == 1) &&
2329            (srcWidth == dstWidth) && (srcHeight == dstHeight) &&
2330            ((dstMinX + dstWidth) <= image.getWidth()) &&
2331            ((dstMinY + dstHeight) <= image.getHeight()) &&
2332            sourceBandsNormal && destinationBandsNormal &&
2333            !adjustBitDepths;
2334    }
2335
2336    /**
2337     * Decodes the input bit stream (located in the
2338     * <code>ImageInputStream</code> <code>stream</code>, at offset
2339     * <code>offset</code>, and continuing for <code>byteCount</code>
2340     * bytes) into the output <code>BufferedImage</code>
2341     * <code>image</code>.
2342     *
2343     * <p> The default implementation analyzes the destination image
2344     * to determine if it is suitable as the destination for the
2345     * <code>decodeRaw</code> method.  If not, a suitable image is
2346     * created.  Next, <code>decodeRaw</code> is called to perform the
2347     * actual decoding, and the results are copied into the
2348     * destination image if necessary.  Subsampling and offsetting are
2349     * performed automatically.
2350     * 
2351     * <p> The precise responsibilities of this routine are as
2352     * follows.  The input bit stream is defined by the instance
2353     * variables <code>stream</code>, <code>offset</code>, and
2354     * <code>byteCount</code>.  These bits contain the data for the
2355     * region of the source image defined by <code>srcMinX</code>,
2356     * <code>srcMinY</code>, <code>srcWidth</code>, and
2357     * <code>srcHeight</code>.
2358     *
2359     * <p> The source data is required to be subsampling, starting at
2360     * the <code>sourceXOffset</code>th column and including
2361     * every <code>subsampleX</code>th pixel thereafter (and similarly
2362     * for <code>sourceYOffset</code> and
2363     * <code>subsampleY</code>).
2364     *
2365     * <p> Pixels are copied into the destination with an addition shift of 
2366     * (<code>dstXOffset</code>, <code>dstYOffset</code>).  The complete
2367     * set of formulas relating the source and destination coordinate spaces
2368     * are:
2369     *
2370     * <pre>
2371     * dx = (sx - sourceXOffset)/subsampleX + dstXOffset;
2372     * dy = (sy - sourceYOffset)/subsampleY + dstYOffset; 
2373     * </pre>
2374     *
2375     * Only source pixels such that <code>(sx - sourceXOffset) %
2376     * subsampleX == 0</code> and <code>(sy - sourceYOffset) %
2377     * subsampleY == 0</code> are copied.
2378     *
2379     * <p> The inverse mapping, from destination to source coordinates, 
2380     * is one-to-one:
2381     *
2382     * <pre>
2383     * sx = (dx - dstXOffset)*subsampleX + sourceXOffset;
2384     * sy = (dy - dstYOffset)*subsampleY + sourceYOffset;
2385     * </pre>
2386     *
2387     * <p> The region of the destination image to be updated is given
2388     * by the instance variables <code>dstMinX</code>,
2389     * <code>dstMinY</code>, <code>dstWidth</code>, and
2390     * <code>dstHeight</code>.
2391     *
2392     * <p> It is possible that not all of the source data being read
2393     * will contribute to the destination image.  For example, the
2394     * destination offsets could be set such that some of the source
2395     * pixels land outside of the bounds of the image.  As a
2396     * convenience, the bounds of the active source region (that is,
2397     * the region of the strip or tile being read that actually
2398     * contributes to the destination image, taking clipping into
2399     * account) are available as <code>activeSrcMinX</code>,
2400     * <code>activeSrcMinY</code>, <code>activeSrcWidth</code> and
2401     * <code>activeSrcHeight</code>.  Thus, the source pixel at
2402     * (<code>activeSrcMinX</code>, <code>activeSrcMinY</code>) will
2403     * map to the destination pixel (<code>dstMinX</code>,
2404     * <code>dstMinY</code>).
2405     *
2406     * <p> The sequence of source bands given by
2407     * <code>sourceBands</code> are to be copied into the sequence of
2408     * bands in the destination given by
2409     * <code>destinationBands</code>.
2410     *
2411     * <p> Some standard tag information is provided the instance
2412     * variables <code>photometricInterpretation</code>,
2413     * <code>compression</code>, <code>samplesPerPixel</code>,
2414     * <code>bitsPerSample</code>, <code>sampleFormat</code>,
2415     * <code>extraSamples</code>, and <code>colorMap</code>.
2416     *
2417     * <p> In practice, unless there is a significant performance
2418     * advantage to be gained by overriding this routine, most users
2419     * will prefer to use the default implementation of this routine,
2420     * and instead override the <code>decodeRaw</code> and/or
2421     * <code>getRawImageType</code> methods.
2422     *
2423     * @exception IOException if an error occurs in
2424     * <code>decodeRaw</code>.
2425     */
2426    public void decode() throws IOException {
2427        byte[] byteData = null;
2428        short[] shortData = null;
2429        int[] intData = null;
2430        float[] floatData = null;
2431
2432        int dstOffset = 0;
2433        int pixelBitStride = 1;
2434        int scanlineStride = 0;
2435
2436        // Analyze raw image
2437
2438        this.rawImage = null;
2439        if(isImageSimple) {
2440            if(isBilevel) {
2441                rawImage = this.image;
2442            } else if (isContiguous) {
2443                rawImage =
2444                    image.getSubimage(dstMinX, dstMinY, dstWidth, dstHeight);
2445            }
2446        }
2447
2448        boolean isDirectCopy = rawImage != null;
2449
2450        if(rawImage == null) {
2451            rawImage = createRawImage();
2452            if (rawImage == null) {
2453                throw new IIOException("Couldn't create image buffer!");
2454            }
2455        }
2456
2457        WritableRaster ras = rawImage.getRaster();
2458
2459        if(isBilevel) {
2460            Rectangle rect = isImageSimple ?
2461                new Rectangle(dstMinX, dstMinY, dstWidth, dstHeight) :
2462                ras.getBounds();
2463            byteData = ImageUtil.getPackedBinaryData(ras, rect);
2464            dstOffset = 0;
2465            pixelBitStride = 1;
2466            scanlineStride = (rect.width + 7)/8;
2467        } else {
2468            SampleModel sm = ras.getSampleModel();
2469            DataBuffer db = ras.getDataBuffer();
2470
2471            boolean isSupportedType = false;
2472
2473            if (sm instanceof ComponentSampleModel) {
2474                ComponentSampleModel csm = (ComponentSampleModel)sm;
2475                dstOffset = csm.getOffset(-ras.getSampleModelTranslateX(),
2476                                          -ras.getSampleModelTranslateY());
2477                scanlineStride = csm.getScanlineStride();
2478                if(db instanceof DataBufferByte) {
2479                    DataBufferByte dbb = (DataBufferByte)db;
2480
2481                    byteData = dbb.getData();
2482                    pixelBitStride = csm.getPixelStride()*8;
2483                    isSupportedType = true;
2484                } else if(db instanceof DataBufferUShort) {
2485                    DataBufferUShort dbus = (DataBufferUShort)db;
2486
2487                    shortData = dbus.getData();
2488                    pixelBitStride = csm.getPixelStride()*16;
2489                    isSupportedType = true;
2490                } else if(db instanceof DataBufferShort) {
2491                    DataBufferShort dbs = (DataBufferShort)db;
2492
2493                    shortData = dbs.getData();
2494                    pixelBitStride = csm.getPixelStride()*16;
2495                    isSupportedType = true;
2496                } else if(db instanceof DataBufferInt) {
2497                    DataBufferInt dbi = (DataBufferInt)db;
2498
2499                    intData = dbi.getData();
2500                    pixelBitStride = csm.getPixelStride()*32;
2501                    isSupportedType = true;
2502                } else if(db instanceof DataBufferFloat) {
2503                    DataBufferFloat dbf = (DataBufferFloat)db;
2504
2505                    floatData = dbf.getData();
2506                    pixelBitStride = csm.getPixelStride()*32;
2507                    isSupportedType = true;
2508                }
2509            } else if (sm instanceof MultiPixelPackedSampleModel) {
2510                MultiPixelPackedSampleModel mppsm =
2511                    (MultiPixelPackedSampleModel)sm;
2512                dstOffset =
2513                    mppsm.getOffset(-ras.getSampleModelTranslateX(),
2514                                    -ras.getSampleModelTranslateY());
2515                pixelBitStride = mppsm.getPixelBitStride();
2516                scanlineStride = mppsm.getScanlineStride();
2517                if(db instanceof DataBufferByte) {
2518                    DataBufferByte dbb = (DataBufferByte)db;
2519
2520                    byteData = dbb.getData();
2521                    isSupportedType = true;
2522                } else if(db instanceof DataBufferUShort) {
2523                    DataBufferUShort dbus = (DataBufferUShort)db;
2524
2525                    shortData = dbus.getData();
2526                    isSupportedType = true;
2527                } else if(db instanceof DataBufferInt) {
2528                    DataBufferInt dbi = (DataBufferInt)db;
2529
2530                    intData = dbi.getData();
2531                    isSupportedType = true;
2532                }
2533            } else if (sm instanceof SinglePixelPackedSampleModel) {
2534                SinglePixelPackedSampleModel sppsm =
2535                    (SinglePixelPackedSampleModel)sm;
2536                dstOffset =
2537                    sppsm.getOffset(-ras.getSampleModelTranslateX(),
2538                                    -ras.getSampleModelTranslateY());
2539                scanlineStride = sppsm.getScanlineStride();
2540                if(db instanceof DataBufferByte) {
2541                    DataBufferByte dbb = (DataBufferByte)db;
2542
2543                    byteData = dbb.getData();
2544                    pixelBitStride = 8;
2545                    isSupportedType = true;
2546                } else if(db instanceof DataBufferUShort) {
2547                    DataBufferUShort dbus = (DataBufferUShort)db;
2548
2549                    shortData = dbus.getData();
2550                    pixelBitStride = 16;
2551                    isSupportedType = true;
2552                } else if(db instanceof DataBufferInt) {
2553                    DataBufferInt dbi = (DataBufferInt)db;
2554
2555                    intData = dbi.getData();
2556                    pixelBitStride = 32;
2557                    isSupportedType = true;
2558                }
2559            }
2560
2561            if(!isSupportedType) {
2562                throw new IIOException
2563                    ("Unsupported raw image type: SampleModel = "+sm+
2564                     "; DataBuffer = "+db);
2565            }
2566        }
2567
2568        if(isBilevel) {
2569            // Bilevel data are always in a contiguous byte buffer.
2570            decodeRaw(byteData, dstOffset, pixelBitStride, scanlineStride);
2571        } else {
2572            SampleModel sm = ras.getSampleModel();
2573
2574            // Branch based on whether data are bit-contiguous, i.e.,
2575            // data are packaed as tightly as possible leaving no unused
2576            // bits except at the end of a row.
2577            if(isDataBufferBitContiguous(sm)) {
2578                // Use byte or float data directly.
2579                if (byteData != null) {
2580                    if(DEBUG) {
2581                        System.out.println("Decoding bytes directly");
2582                    }
2583                    decodeRaw(byteData, dstOffset,
2584                              pixelBitStride, scanlineStride);
2585                } else if (floatData != null) {
2586                    if(DEBUG) {
2587                        System.out.println("Decoding floats directly");
2588                    }
2589                    decodeRaw(floatData, dstOffset,
2590                              pixelBitStride, scanlineStride);
2591                } else {
2592                    if (shortData != null) {
2593                        if(areSampleSizesEqual(sm) &&
2594                           sm.getSampleSize(0) == 16) {
2595                            if(DEBUG) {
2596                                System.out.println("Decoding shorts directly");
2597                            }
2598                            // Decode directly into short data.
2599                            decodeRaw(shortData, dstOffset,
2600                                      pixelBitStride, scanlineStride);
2601                        } else {
2602                            if(DEBUG) {
2603                                System.out.println("Decoding bytes->shorts");
2604                            }
2605                            // Decode into bytes and reformat into shorts.
2606                            int bpp = getBitsPerPixel(sm);
2607                            int bytesPerRow = (bpp*srcWidth + 7)/8;
2608                            byte[] buf = new byte[bytesPerRow*srcHeight];
2609                            decodeRaw(buf, 0, bpp, bytesPerRow);
2610                            reformatData(buf, bytesPerRow, srcHeight,
2611                                         shortData, null,
2612                                         dstOffset, scanlineStride);
2613                        }
2614                    } else if (intData != null) {
2615                        if(areSampleSizesEqual(sm) &&
2616                           sm.getSampleSize(0) == 32) {
2617                            if(DEBUG) {
2618                                System.out.println("Decoding ints directly");
2619                            }
2620                            // Decode directly into int data.
2621                            decodeRaw(intData, dstOffset,
2622                                      pixelBitStride, scanlineStride);
2623                        } else {
2624                            if(DEBUG) {
2625                                System.out.println("Decoding bytes->ints");
2626                            }
2627                            // Decode into bytes and reformat into ints.
2628                            int bpp = getBitsPerPixel(sm);
2629                            int bytesPerRow = (bpp*srcWidth + 7)/8;
2630                            byte[] buf = new byte[bytesPerRow*srcHeight];
2631                            decodeRaw(buf, 0, bpp, bytesPerRow);
2632                            reformatData(buf, bytesPerRow, srcHeight,
2633                                         null, intData,
2634                                         dstOffset, scanlineStride);
2635                        }
2636                    }
2637                }
2638            } else {
2639                if(DEBUG) {
2640                    System.out.println("Decoding discontiguous data");
2641                }
2642                // Read discontiguous data into bytes and set the samples
2643                // into the Raster.
2644                int bpp = getBitsPerPixel(sm);
2645                int bytesPerRow = (bpp*srcWidth + 7)/8;
2646                byte[] buf = new byte[bytesPerRow*srcHeight];
2647                decodeRaw(buf, 0, bpp, bytesPerRow);
2648                reformatDiscontiguousData(buf, bytesPerRow,
2649                                          srcWidth, srcHeight,
2650                                          ras);
2651            }
2652        }
2653
2654        //         System.out.println("colorConverter = " + colorConverter);
2655
2656        if (colorConverter != null) {
2657            float[] rgb = new float[3];
2658
2659            if(byteData != null) {
2660                for (int j = 0; j < dstHeight; j++) {
2661                    int idx = dstOffset;
2662                    for (int i = 0; i < dstWidth; i++) {
2663                        float x0 = (float)(byteData[idx] & 0xff);
2664                        float x1 = (float)(byteData[idx + 1] & 0xff);
2665                        float x2 = (float)(byteData[idx + 2] & 0xff);
2666
2667                        colorConverter.toRGB(x0, x1, x2, rgb);
2668
2669                        byteData[idx] = (byte)(rgb[0]);
2670                        byteData[idx + 1] = (byte)(rgb[1]);
2671                        byteData[idx + 2] = (byte)(rgb[2]);
2672
2673                        idx += 3;
2674                    }
2675
2676                    dstOffset += scanlineStride;
2677                }
2678            } else if(shortData != null) {
2679                if(sampleFormat[0] ==
2680                   BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) {
2681                    for (int j = 0; j < dstHeight; j++) {
2682                        int idx = dstOffset;
2683                        for (int i = 0; i < dstWidth; i++) {
2684                            float x0 = (float)shortData[idx];
2685                            float x1 = (float)shortData[idx + 1];
2686                            float x2 = (float)shortData[idx + 2];
2687
2688                            colorConverter.toRGB(x0, x1, x2, rgb);
2689
2690                            shortData[idx] = (short)(rgb[0]);
2691                            shortData[idx + 1] = (short)(rgb[1]);
2692                            shortData[idx + 2] = (short)(rgb[2]);
2693
2694                            idx += 3;
2695                        }
2696
2697                        dstOffset += scanlineStride;
2698                    }
2699                } else {
2700                    for (int j = 0; j < dstHeight; j++) {
2701                        int idx = dstOffset;
2702                        for (int i = 0; i < dstWidth; i++) {
2703                            float x0 = (float)(shortData[idx] & 0xffff);
2704                            float x1 = (float)(shortData[idx + 1] & 0xffff);
2705                            float x2 = (float)(shortData[idx + 2] & 0xffff);
2706
2707                            colorConverter.toRGB(x0, x1, x2, rgb);
2708
2709                            shortData[idx] = (short)(rgb[0]);
2710                            shortData[idx + 1] = (short)(rgb[1]);
2711                            shortData[idx + 2] = (short)(rgb[2]);
2712
2713                            idx += 3;
2714                        }
2715
2716                        dstOffset += scanlineStride;
2717                    }
2718                }
2719            } else if(intData != null) {
2720                for (int j = 0; j < dstHeight; j++) {
2721                    int idx = dstOffset;
2722                    for (int i = 0; i < dstWidth; i++) {
2723                        float x0 = (float)intData[idx];
2724                        float x1 = (float)intData[idx + 1];
2725                        float x2 = (float)intData[idx + 2];
2726
2727                        colorConverter.toRGB(x0, x1, x2, rgb);
2728
2729                        intData[idx] = (int)(rgb[0]);
2730                        intData[idx + 1] = (int)(rgb[1]);
2731                        intData[idx + 2] = (int)(rgb[2]);
2732
2733                        idx += 3;
2734                    }
2735
2736                    dstOffset += scanlineStride;
2737                }
2738            } else if(floatData != null) {
2739                for (int j = 0; j < dstHeight; j++) {
2740                    int idx = dstOffset;
2741                    for (int i = 0; i < dstWidth; i++) {
2742                        float x0 = floatData[idx];
2743                        float x1 = floatData[idx + 1];
2744                        float x2 = floatData[idx + 2];
2745
2746                        colorConverter.toRGB(x0, x1, x2, rgb);
2747
2748                        floatData[idx] = rgb[0];
2749                        floatData[idx + 1] = rgb[1];
2750                        floatData[idx + 2] = rgb[2];
2751
2752                        idx += 3;
2753                    }
2754
2755                    dstOffset += scanlineStride;
2756                }
2757            }
2758
2759//             int[] p = new int[3];
2760//             ras.getPixel(0, 0, p);
2761//             System.out.println("p00 = " + 
2762//                                p[0] + " " + p[1] + " " + p[2]);
2763//             ras.getPixel(1, 0, p);
2764//             System.out.println("p10 = " + 
2765//                                p[0] + " " + p[1] + " " + p[2]);
2766//             ras.getPixel(2, 0, p);
2767//             System.out.println("p20 = " + 
2768//                                p[0] + " " + p[1] + " " + p[2]);
2769//             ras.getPixel(3, 0, p);
2770//             System.out.println("p30 = " + 
2771//                                p[0] + " " + p[1] + " " + p[2]);
2772
2773//             ColorSpace rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
2774//             ColorConvertOp op = new ColorConvertOp(colorSpace, rgb, null);
2775//             WritableRaster dest = op.createCompatibleDestRaster(ras);
2776//             op.filter(ras, dest);
2777//             ras = dest;
2778        }
2779        
2780        if (photometricInterpretation ==
2781            BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO) {
2782            if(byteData != null) {
2783                int bytesPerRow = (srcWidth*pixelBitStride + 7)/8;
2784                for (int y = 0; y < srcHeight; y++) {
2785                    int offset = dstOffset + y*scanlineStride;
2786                    for (int i = 0; i < bytesPerRow; i++) {
2787                        byteData[offset + i] ^= 0xff;
2788                    }
2789                }
2790            } else if(shortData != null) {
2791                int shortsPerRow = (srcWidth*pixelBitStride + 15)/16;
2792                if(sampleFormat[0] ==
2793                   BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) {
2794                    for (int y = 0; y < srcHeight; y++) {
2795                        int offset = dstOffset + y*scanlineStride;
2796                        for (int i = 0; i < shortsPerRow; i++) {
2797                            int shortOffset = offset + i;
2798                            // XXX Does this make any sense?
2799                            shortData[shortOffset] =
2800                                (short)(Short.MAX_VALUE -
2801                                        shortData[shortOffset]);
2802                        }
2803                    }
2804                } else {
2805                    for (int y = 0; y < srcHeight; y++) {
2806                        int offset = dstOffset + y*scanlineStride;
2807                        for (int i = 0; i < shortsPerRow; i++) {
2808                            shortData[offset + i] ^= 0xffff;
2809                        }
2810                    }
2811                }
2812            } else if(intData != null) {
2813                int intsPerRow = (srcWidth*pixelBitStride + 15)/16;
2814                for (int y = 0; y < srcHeight; y++) {
2815                    int offset = dstOffset + y*scanlineStride;
2816                    for (int i = 0; i < intsPerRow; i++) {
2817                        int intOffset = offset + i;
2818                        // XXX Does this make any sense?
2819                        intData[intOffset] =
2820                            Integer.MAX_VALUE - intData[intOffset];
2821                    }
2822                }
2823            } else if(floatData != null) {
2824                int floatsPerRow = (srcWidth*pixelBitStride + 15)/16;
2825                for (int y = 0; y < srcHeight; y++) {
2826                    int offset = dstOffset + y*scanlineStride;
2827                    for (int i = 0; i < floatsPerRow; i++) {
2828                        int floatOffset = offset + i;
2829                        // XXX Does this make any sense?
2830                        floatData[floatOffset] =
2831                            1.0F - floatData[floatOffset];
2832                    }
2833                }
2834            }
2835        }
2836
2837        if(isBilevel) {
2838            Rectangle rect = isImageSimple ?
2839                new Rectangle(dstMinX, dstMinY, dstWidth, dstHeight) :
2840                ras.getBounds();
2841            ImageUtil.setPackedBinaryData(byteData, ras, rect);
2842        }
2843
2844        // XXX A better test might be if the rawImage raster either
2845        // equals the raster of 'image' or is a child thereof.
2846        if (isDirectCopy) { // rawImage == image) {
2847            return;
2848        }
2849
2850        // Copy the raw image data into the true destination image
2851        Raster src = rawImage.getRaster();
2852
2853        // Create band child of source
2854        Raster srcChild = src.createChild(0, 0,
2855                                          srcWidth, srcHeight,
2856                                          srcMinX, srcMinY,
2857                                          planar ? null : sourceBands);
2858
2859        WritableRaster dst = image.getRaster();
2860
2861        // Create dst child covering area and bands to be written
2862        WritableRaster dstChild = dst.createWritableChild(dstMinX, dstMinY,
2863                                                          dstWidth, dstHeight,
2864                                                          dstMinX, dstMinY,
2865                                                          destinationBands);
2866
2867        if (subsampleX == 1 && subsampleY == 1 && !adjustBitDepths) {
2868            srcChild = srcChild.createChild(activeSrcMinX,
2869                                            activeSrcMinY,
2870                                            activeSrcWidth, activeSrcHeight,
2871                                            dstMinX, dstMinY,
2872                                            null);
2873
2874            dstChild.setRect(srcChild);
2875        } else if (subsampleX == 1 && !adjustBitDepths) {
2876            int sy = activeSrcMinY;
2877            int dy = dstMinY;
2878            while (sy < srcMinY + srcHeight) {
2879                Raster srcRow = srcChild.createChild(activeSrcMinX, sy,
2880                                                     activeSrcWidth, 1,
2881                                                     dstMinX, dy,
2882                                                     null);
2883                dstChild.setRect(srcRow);
2884                
2885                sy += subsampleY;
2886                ++dy;
2887            }
2888        } else {
2889            int[] p = srcChild.getPixel(srcMinX, srcMinY, (int[])null);
2890            int numBands = p.length;
2891
2892            int sy = activeSrcMinY;
2893            int dy = dstMinY;
2894
2895            while (sy < activeSrcMinY + activeSrcHeight) {
2896                int sx = activeSrcMinX;
2897                int dx = dstMinX;
2898
2899                while (sx < activeSrcMinX + activeSrcWidth) {
2900                    srcChild.getPixel(sx, sy, p);
2901                    if (adjustBitDepths) {
2902                        for (int band = 0; band < numBands; band++) {
2903                            p[band] = bitDepthScale[band][p[band]];
2904                        }
2905                    }
2906                    dstChild.setPixel(dx, dy, p);
2907                    
2908                    sx += subsampleX;
2909                    ++dx;
2910                }
2911
2912                sy += subsampleY;
2913                ++dy;
2914            }
2915        }
2916    }
2917}