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