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