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 }