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