001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.imaging.formats.tiff.datareaders; 018 019import java.awt.Rectangle; 020import java.io.ByteArrayInputStream; 021import java.io.IOException; 022import java.io.InputStream; 023import java.nio.ByteOrder; 024import java.util.Arrays; 025 026import org.apache.commons.imaging.ImagingException; 027import org.apache.commons.imaging.common.Allocator; 028import org.apache.commons.imaging.common.ImageBuilder; 029import org.apache.commons.imaging.common.PackBits; 030import org.apache.commons.imaging.common.ZlibDeflate; 031import org.apache.commons.imaging.formats.tiff.AbstractTiffRasterData; 032import org.apache.commons.imaging.formats.tiff.TiffDirectory; 033import org.apache.commons.imaging.formats.tiff.TiffField; 034import org.apache.commons.imaging.formats.tiff.constants.TiffConstants; 035import org.apache.commons.imaging.formats.tiff.constants.TiffPlanarConfiguration; 036import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants; 037import org.apache.commons.imaging.formats.tiff.itu_t4.T4AndT6Compression; 038import org.apache.commons.imaging.formats.tiff.photometricinterpreters.AbstractPhotometricInterpreter; 039import org.apache.commons.imaging.mylzw.MyLzwDecompressor; 040 041/** 042 * Defines the base class for the TIFF file reader classes. The TIFF format defines two broad organizations for image pixel storage: strips and tiles. This 043 * class defines common elements for both representations. 044 * <p> 045 * <strong>The TIFF Floating-Point Formats </strong> 046 * <p> 047 * In addition to providing images, TIFF files can supply data in the form of numerical values. As of March 2020 the Commons Imaging library was extended to 048 * support some floating-point data formats. 049 * <p> 050 * Unfortunately, the TIFF floating-point format allows for a lot of different variations. At this time, only the most widely used of these are supported. When 051 * this code was written, only a small set of test data products were available. Thus it is likely that developers will wish to extend the range of 052 * floating-point data that can be processed as additional test data become available. When implementing extensions to this logic, developers are reminded that 053 * image processing requires the handling of literally millions of pixels, so attention to performance is essential to a successful implementation (please see 054 * the notes in {@link DataReaderStrips} for more information). 055 * <p> 056 * The TIFF floating-point specification is poorly documented. So these notes are included to provide clarification on at least some aspects of the format. Some 057 * documentation and C-code examples are available in "TIFF Technical Note 3, April 8, 2005)". 058 * <p> 059 * <strong>The Predictor==3 Case</strong> 060 * <p> 061 * TIFF specifies an extension for a predictor that is intended to improve data compression ratios for floating-point values. This predictor is specified using 062 * the TIFF predictor TAG with a value of 3 (see TIFF Technical Note 3). Consider a 4-byte floating point value given in IEEE-754 format. Let f3 be the 063 * high-order byte, with f2 the next highest, followed by f1, and f0 for the low-order byte. This designation should not be confused with the in-memory layout 064 * of the bytes (little-endian versus big-endian), but rather their numerical values. The sign bit and upper 7 bits of the exponent are given in the high-order 065 * byte, followed by the one remaining exponent bit and the mantissa in the lower-order bytes. 066 * <p> 067 * In many real-valued raster data sets, the sign and magnitude (exponent) of the values change slowly. But the bits in the mantissa vary rapidly in a 068 * semi-random manner. The information entropy in the mantissa tends to increase in the lowest ordered bytes. Thus, the high-order bytes have more redundancy 069 * than the low-order bytes and can compress more efficiently. To exploit this, the TIFF format splits the bytes into groups based on their order-of-magnitude. 070 * This splitting process takes place on a ROW-BY-ROW basis (note the emphasis, this point is not clearly documented in the spec). For example, for a row of 071 * length 3 pixels -- A, B, and C -- the data for two rows would be given as shown below (again, ignoring endian issues): 072 * 073 * <pre> 074 * Original: 075 * A3 A2 A1 A0 B3 B2 B1 B0 C3 C2 C1 C0 076 * D3 D3 D1 D0 E3 E2 E2 E0 F3 F2 F1 F0 077 * 078 * Bytes split into groups by order-of-magnitude: 079 * A3 B3 C3 A2 B2 C2 A1 B1 C1 A0 B0 C0 080 * D3 E3 F3 D2 E2 F2 D1 E1 F1 D0 E0 F0 081 * </pre> 082 * 083 * To further improve the compression, the predictor takes the difference of each subsequent bytes. Again, the differences (deltas) are computed on a 084 * row-byte-row basis. For the most part, the differences combine bytes associated with the same order-of-magnitude, though there is a special transition at the 085 * end of each order-of-magnitude set (shown in parentheses): 086 * 087 * <pre> 088 * A3, B3-A3, C3-B3, (A2-C3), B2-A2, C2-B2, (A1-C2), etc. 089 * D3, E3-D3, F3-D3, (D2-F3), E3-D2, etc. 090 * </pre> 091 * 092 * Once the predictor transform is complete, the data is stored using conventional data compression techniques such as Deflate or LZW. In practice, floating 093 * point data does not compress especially well, but using the above technique, the TIFF process typically reduces the overall storage size by 20 to 30 percent 094 * (depending on the data). The TIFF Technical Note 3 specifies 3 data size formats for storing floating point values: 095 * 096 * <pre> 097 * 32 bits IEEE-754 single-precision standard 098 * 16 bits IEEE-754 half-precision standard 099 * 24 bits A non-standard representation 100 * </pre> 101 * 102 * At this time, we have not obtained data samples for the smaller representations used in combination with a predictor. 103 * <p> 104 * <strong>Interleaved formats</strong> 105 * <p> 106 * TIFF Technical Note 3 also provides example code for cases where each pixel (or raster cell) in the image is associated with more than one floating-point 107 * samples. Data in this format might be used for real-valued vector data, complex-valued pairs, or other numerical applications). 108 * <p> 109 * At this time, we have encountered only a limited selection of the possible configurations for multi-variable data. The code below only supports those 110 * configurations for which we had actual images that could be used to verify our implementation. The implementation supports the following formats: 111 * <ul> 112 * <li>32-bit floating-point data</li> 113 * <li>Uncompressed, Deflate, or LZW compression</li> 114 * <li>Optional horizontal predictors used with compression</li> 115 * <li>PlanarConfiguration interleaved (CHUNKY) or non-interleaved (PLANAR)</li> 116 * </ul> 117 * <p> 118 * Note that integer formats are not supported at this time. 119 * <p> 120 * Often, the TIFF files store multi-variable data in so that samples are interleaved. For example, a configuration that gave two samples per pixel (or cell) 121 * would give the two values for the first pixel in order followed by the two values for the second pixel, etc. If a differencing approach were used for data 122 * compression, the byte-stream would begin with the high-order byte for each of the two samples for the first pixel, followed by the high-order byte for each 123 * of the next two samples, and so forth for the remainder of the row of pixels. It would then follow with the second-highest-order bytes for the first two 124 * samples, etc. 125 * <p> 126 * This implementation also supports the non-interleaved (PLANAR) configuration. One consideration in implementing this feature was that TIFF Technical Note 3 127 * does not address the case where a TIFF image uses the alternate planar configuration. For conventional images, the TIFF specification (Revision 6.0) 128 * recommends that the planar configuration should be avoided (see pg. 38). But for numerical data products, the planar configuration may yield better data 129 * compression in the case where different sample sets have different statistical properties. Because separated groups often have more uniformity and 130 * predictability than interleaved data sets, they sometimes lead to a small improvement in storage-size reduction when data compression is used. 131 */ 132public abstract class AbstractImageDataReader { 133 134 protected final TiffDirectory directory; 135 protected final AbstractPhotometricInterpreter photometricInterpreter; 136 private final int[] bitsPerSample; 137 protected final int bitsPerSampleLength; 138 private final int[] last; 139 140 protected final int predictor; 141 protected final int samplesPerPixel; 142 protected final int width; 143 protected final int height; 144 protected final int sampleFormat; 145 146 protected final TiffPlanarConfiguration planarConfiguration; 147 148 public AbstractImageDataReader(final TiffDirectory directory, final AbstractPhotometricInterpreter photometricInterpreter, final int[] bitsPerSample, 149 final int predictor, final int samplesPerPixel, final int sampleFormat, final int width, final int height, 150 final TiffPlanarConfiguration planarConfiguration) { 151 this.directory = directory; 152 this.photometricInterpreter = photometricInterpreter; 153 this.bitsPerSample = bitsPerSample; 154 this.bitsPerSampleLength = bitsPerSample.length; 155 this.samplesPerPixel = samplesPerPixel; 156 this.sampleFormat = sampleFormat; 157 this.predictor = predictor; 158 this.width = width; 159 this.height = height; 160 this.planarConfiguration = planarConfiguration; 161 last = Allocator.intArray(samplesPerPixel); 162 } 163 164 protected int[] applyPredictor(final int[] samples) { 165 if (predictor == 2) { 166 // Horizontal differencing. 167 for (int i = 0; i < samples.length; i++) { 168 samples[i] = 0xff & samples[i] + last[i]; 169 last[i] = samples[i]; 170 } 171 } 172 173 return samples; 174 } 175 176 protected void applyPredictorToBlock(final int width, final int height, final int nSamplesPerPixel, final byte[] p) { 177 final int k = width * nSamplesPerPixel; 178 for (int i = 0; i < height; i++) { 179 final int j0 = i * k + nSamplesPerPixel; 180 final int j1 = (i + 1) * k; 181 for (int j = j0; j < j1; j++) { 182 p[j] += p[j - nSamplesPerPixel]; 183 } 184 } 185 } 186 187 protected byte[] decompress(final byte[] compressedInput, final int compression, final int expectedSize, final int tileWidth, final int tileHeight) 188 throws ImagingException, IOException { 189 final TiffField fillOrderField = directory.findField(TiffTagConstants.TIFF_TAG_FILL_ORDER); 190 int fillOrder = TiffTagConstants.FILL_ORDER_VALUE_NORMAL; 191 if (fillOrderField != null) { 192 fillOrder = fillOrderField.getIntValue(); 193 } 194 final byte[] compressedOrdered; // re-ordered bytes (if necessary) 195 if (fillOrder == TiffTagConstants.FILL_ORDER_VALUE_NORMAL) { 196 compressedOrdered = compressedInput; 197 // good 198 } else if (fillOrder == TiffTagConstants.FILL_ORDER_VALUE_REVERSED) { 199 compressedOrdered = new byte[compressedInput.length]; 200 for (int i = 0; i < compressedInput.length; i++) { 201 compressedOrdered[i] = (byte) (Integer.reverse(0xff & compressedInput[i]) >>> 24); 202 } 203 } else { 204 throw new ImagingException("TIFF FillOrder=" + fillOrder + " is invalid"); 205 } 206 207 switch (compression) { 208 case TiffConstants.COMPRESSION_UNCOMPRESSED: 209 // None; 210 return compressedOrdered; 211 case TiffConstants.COMPRESSION_CCITT_1D: 212 // CCITT Group 3 1-Dimensional Modified Huffman run-length encoding. 213 return T4AndT6Compression.decompressModifiedHuffman(compressedOrdered, tileWidth, tileHeight); 214 case TiffConstants.COMPRESSION_CCITT_GROUP_3: { 215 int t4Options = 0; 216 final TiffField field = directory.findField(TiffTagConstants.TIFF_TAG_T4_OPTIONS); 217 if (field != null) { 218 t4Options = field.getIntValue(); 219 } 220 final boolean is2D = (t4Options & TiffConstants.FLAG_T4_OPTIONS_2D) != 0; 221 final boolean usesUncompressedMode = (t4Options & TiffConstants.FLAG_T4_OPTIONS_UNCOMPRESSED_MODE) != 0; 222 if (usesUncompressedMode) { 223 throw new ImagingException("T.4 compression with the uncompressed mode extension is not yet supported"); 224 } 225 final boolean hasFillBitsBeforeEOL = (t4Options & TiffConstants.FLAG_T4_OPTIONS_FILL) != 0; 226 if (is2D) { 227 return T4AndT6Compression.decompressT4_2D(compressedOrdered, tileWidth, tileHeight, hasFillBitsBeforeEOL); 228 } 229 return T4AndT6Compression.decompressT4_1D(compressedOrdered, tileWidth, tileHeight, hasFillBitsBeforeEOL); 230 } 231 case TiffConstants.COMPRESSION_CCITT_GROUP_4: { 232 int t6Options = 0; 233 final TiffField field = directory.findField(TiffTagConstants.TIFF_TAG_T6_OPTIONS); 234 if (field != null) { 235 t6Options = field.getIntValue(); 236 } 237 final boolean usesUncompressedMode = (t6Options & TiffConstants.FLAG_T6_OPTIONS_UNCOMPRESSED_MODE) != 0; 238 if (usesUncompressedMode) { 239 throw new ImagingException("T.6 compression with the uncompressed mode extension is not yet supported"); 240 } 241 return T4AndT6Compression.decompressT6(compressedOrdered, tileWidth, tileHeight); 242 } 243 case TiffConstants.COMPRESSION_LZW: { 244 final InputStream is = new ByteArrayInputStream(compressedOrdered); 245 final int lzwMinimumCodeSize = 8; 246 return new MyLzwDecompressor(lzwMinimumCodeSize, ByteOrder.BIG_ENDIAN, true).decompress(is, expectedSize); 247 } 248 249 // Packbits 250 case TiffConstants.COMPRESSION_PACKBITS: { 251 return PackBits.decompress(compressedOrdered, expectedSize); 252 } 253 254 // deflate 255 case TiffConstants.COMPRESSION_DEFLATE_ADOBE: 256 case TiffConstants.COMPRESSION_DEFLATE_PKZIP: { 257 return ZlibDeflate.decompress(compressedInput, expectedSize); 258 } 259 260 default: 261 throw new ImagingException("Tiff: unknown/unsupported compression: " + compression); 262 } 263 } 264 265 /** 266 * Reads samples and returns them in an int array. 267 * 268 * @param bis the stream to read from 269 * @param result the samples array to populate, must be the same length as bitsPerSample.length 270 * @throws IOException 271 */ 272 void getSamplesAsBytes(final BitInputStream bis, final int[] result) throws IOException { 273 for (int i = 0; i < bitsPerSample.length; i++) { 274 final int bits = bitsPerSample[i]; 275 int sample = bis.readBits(bits); 276 if (bits < 8) { 277 final int sign = sample & 1; 278 sample = sample << 8 - bits; // scale to byte. 279 if (sign > 0) { 280 sample = sample | (1 << 8 - bits) - 1; // extend to byte 281 } 282 } else if (bits > 8) { 283 sample = sample >> bits - 8; // extend to byte. 284 } 285 result[i] = sample; 286 } 287 } 288 289 /** 290 * Checks if all the bits per sample entries are the same size 291 * 292 * @param size the size to check 293 * @return true if all the bits per sample entries are the same 294 */ 295 protected boolean isHomogenous(final int size) { 296 for (final int element : bitsPerSample) { 297 if (element != size) { 298 return false; 299 } 300 } 301 return true; 302 } 303 304 /** 305 * Reads the image data from the IFD associated with this instance of ImageDataReader using the optional sub-image specification if desired. 306 * 307 * @param subImageSpecification a rectangle describing a sub-region of the image for reading, or a null if the whole image is to be read. 308 * @param hasAlpha indicates that the image has an alpha (transparency) channel (RGB color model only). 309 * @param isAlphaPremultiplied indicates that the image uses the associated alpha channel format (pre-multiplied alpha). 310 * @return a valid instance containing the pixel data from the image. 311 * @throws IOException in the event of an unrecoverable I/O error. 312 * @throws ImagingException TODO 313 */ 314 public abstract ImageBuilder readImageData(Rectangle subImageSpecification, boolean hasAlpha, boolean isAlphaPremultiplied) 315 throws IOException, ImagingException; 316 317 /** 318 * Defines a method for accessing the floating-point raster data in a TIFF image. These implementations of this method in DataReaderStrips and 319 * DataReaderTiled assume that this instance is of a compatible data type (floating-point) and that all access checks have already been performed. 320 * 321 * @param subImage if non-null, instructs the access method to retrieve only a sub-section of the image data. 322 * @return a valid instance 323 * @throws ImagingException in the event of an incompatible data form. 324 * @throws IOException in the event of I/O error. 325 */ 326 public abstract AbstractTiffRasterData readRasterData(Rectangle subImage) throws ImagingException, IOException; 327 328 protected void resetPredictor() { 329 Arrays.fill(last, 0); 330 } 331 332 /** 333 * Transfer samples obtained from the TIFF file to a floating-point raster. 334 * 335 * @param xBlock coordinate of block relative to source data 336 * @param yBlock coordinate of block relative to source data 337 * @param blockWidth width of block, in pixels 338 * @param blockHeight height of block in pixels 339 * @param blockData the data for the block 340 * @param xRaster coordinate of raster relative to source data 341 * @param yRaster coordinate of raster relative to source data 342 * @param rasterWidth width of the raster (always smaller than source data) 343 * @param rasterHeight height of the raster (always smaller than source data) 344 * @param rasterData the raster data. 345 */ 346 void transferBlockToRaster(final int xBlock, final int yBlock, final int blockWidth, final int blockHeight, final int[] blockData, final int xRaster, 347 final int yRaster, final int rasterWidth, final int rasterHeight, final int samplesPerPixel, final float[] rasterData) { 348 349 // xR0, yR0 are the coordinates within the raster (upper-left corner) 350 // xR1, yR1 are ONE PAST the coordinates of the lower-right corner 351 int xR0 = xBlock - xRaster; // xR0, yR0 coordinates relative to 352 int yR0 = yBlock - yRaster; // the raster 353 int xR1 = xR0 + blockWidth; 354 int yR1 = yR0 + blockHeight; 355 if (xR0 < 0) { 356 xR0 = 0; 357 } 358 if (yR0 < 0) { 359 yR0 = 0; 360 } 361 if (xR1 > rasterWidth) { 362 xR1 = rasterWidth; 363 } 364 if (yR1 > rasterHeight) { 365 yR1 = rasterHeight; 366 } 367 368 // Recall that the above logic may have adjusted xR0, xY0 so that 369 // they are not necessarily point to the source pixel at xRaster, yRaster 370 // we compute xSource = xR0+xRaster. 371 // xOffset = xSource-xBlock 372 // since the block cannot be accessed with a negative offset, 373 // we check for negatives and adjust xR0, yR0 upward as necessary 374 int xB0 = xR0 + xRaster - xBlock; 375 int yB0 = yR0 + yRaster - yBlock; 376 if (xB0 < 0) { 377 xR0 -= xB0; 378 xB0 = 0; 379 } 380 if (yB0 < 0) { 381 yR0 -= yB0; 382 yB0 = 0; 383 } 384 385 int w = xR1 - xR0; 386 int h = yR1 - yR0; 387 if (w <= 0 || h <= 0) { 388 // The call to this method put the block outside the 389 // bounds of the raster. There is nothing to do. Ideally, 390 // this situation never arises, because it would mean that 391 // the data was read from the file unnecessarily. 392 return; 393 } 394 // see if the xR1, yR1 would extend past the limits of the block 395 if (w > blockWidth) { 396 w = blockWidth; 397 } 398 if (h > blockHeight) { 399 h = blockHeight; 400 } 401 402 // The TiffRasterData class expects data to be in the order 403 // corresponding to TiffPlanarConfiguration.PLANAR. So for the 404 // multivariable case, we must convert CHUNKY data to PLANAR. 405 if (samplesPerPixel == 1) { 406 for (int i = 0; i < h; i++) { 407 final int yR = yR0 + i; 408 final int yB = yB0 + i; 409 final int rOffset = yR * rasterWidth + xR0; 410 final int bOffset = yB * blockWidth + xB0; 411 for (int j = 0; j < w; j++) { 412 rasterData[rOffset + j] = Float.intBitsToFloat(blockData[bOffset + j]); 413 } 414 } 415 } else if (this.planarConfiguration == TiffPlanarConfiguration.CHUNKY) { 416 // The source data is in the interleaved (Chunky) order, 417 // but the TiffRasterData class expects non-interleaved order. 418 // So we transcribe the elements as appropriate. 419 final int pixelsPerPlane = rasterWidth * rasterHeight; 420 for (int i = 0; i < h; i++) { 421 final int yR = yR0 + i; 422 final int yB = yB0 + i; 423 final int rOffset = yR * rasterWidth + xR0; 424 final int bOffset = yB * blockWidth + xB0; 425 for (int j = 0; j < w; j++) { 426 for (int k = 0; k < samplesPerPixel; k++) { 427 rasterData[k * pixelsPerPlane + rOffset + j] = Float.intBitsToFloat(blockData[(bOffset + j) * samplesPerPixel + k]); 428 } 429 } 430 } 431 } else { 432 for (int iPlane = 0; iPlane < samplesPerPixel; iPlane++) { 433 final int rPlanarOffset = iPlane * rasterWidth * rasterHeight; 434 final int bPlanarOffset = iPlane * blockWidth * blockHeight; 435 for (int i = 0; i < h; i++) { 436 final int yR = yR0 + i; 437 final int yB = yB0 + i; 438 final int rOffset = rPlanarOffset + yR * rasterWidth + xR0; 439 final int bOffset = bPlanarOffset + yB * blockWidth + xB0; 440 for (int j = 0; j < w; j++) { 441 rasterData[rOffset + j] = Float.intBitsToFloat(blockData[bOffset + j]); 442 } 443 } 444 } 445 } 446 447 } 448 449 /** 450 * Transfer samples obtained from the TIFF file to an integer raster. 451 * 452 * @param xBlock coordinate of block relative to source data 453 * @param yBlock coordinate of block relative to source data 454 * @param blockWidth width of block, in pixels 455 * @param blockHeight height of block in pixels 456 * @param blockData the data for the block 457 * @param xRaster coordinate of raster relative to source data 458 * @param yRaster coordinate of raster relative to source data 459 * @param rasterWidth width of the raster (always smaller than source data) 460 * @param rasterHeight height of the raster (always smaller than source data) 461 * @param rasterData the raster data. 462 */ 463 void transferBlockToRaster(final int xBlock, final int yBlock, final int blockWidth, final int blockHeight, final int[] blockData, final int xRaster, 464 final int yRaster, final int rasterWidth, final int rasterHeight, final int[] rasterData) { 465 466 // xR0, yR0 are the coordinates within the raster (upper-left corner) 467 // xR1, yR1 are ONE PAST the coordinates of the lower-right corner 468 int xR0 = xBlock - xRaster; // xR0, yR0 coordinates relative to 469 int yR0 = yBlock - yRaster; // the raster 470 int xR1 = xR0 + blockWidth; 471 int yR1 = yR0 + blockHeight; 472 if (xR0 < 0) { 473 xR0 = 0; 474 } 475 if (yR0 < 0) { 476 yR0 = 0; 477 } 478 if (xR1 > rasterWidth) { 479 xR1 = rasterWidth; 480 } 481 if (yR1 > rasterHeight) { 482 yR1 = rasterHeight; 483 } 484 485 // Recall that the above logic may have adjusted xR0, xY0 so that 486 // they are not necessarily point to the source pixel at xRaster, yRaster 487 // we compute xSource = xR0+xRaster. 488 // xOffset = xSource-xBlock 489 // since the block cannot be accessed with a negative offset, 490 // we check for negatives and adjust xR0, yR0 upward as necessary 491 int xB0 = xR0 + xRaster - xBlock; 492 int yB0 = yR0 + yRaster - yBlock; 493 if (xB0 < 0) { 494 xR0 -= xB0; 495 xB0 = 0; 496 } 497 if (yB0 < 0) { 498 yR0 -= yB0; 499 yB0 = 0; 500 } 501 502 int w = xR1 - xR0; 503 int h = yR1 - yR0; 504 if (w <= 0 || h <= 0) { 505 // The call to this method puts the block outside the 506 // bounds of the raster. There is nothing to do. Ideally, 507 // this situation never arises, because it would mean that 508 // the data was read from the file unnecessarily. 509 return; 510 } 511 // see if the xR1, yR1 would extend past the limits of the block 512 if (w > blockWidth) { 513 w = blockWidth; 514 } 515 if (h > blockHeight) { 516 h = blockHeight; 517 } 518 519 for (int i = 0; i < h; i++) { 520 final int yR = yR0 + i; 521 final int yB = yB0 + i; 522 final int rOffset = yR * rasterWidth + xR0; 523 final int bOffset = yB * blockWidth + xB0; 524 System.arraycopy(blockData, bOffset, rasterData, rOffset, w); 525 } 526 } 527 528 /** 529 * Given a source file that specifies the floating-point data format, unpack the raw bytes obtained from the source file and organize them into an array of 530 * integers containing the bit-equivalent of IEEE-754 32-bit floats. Source files containing 64 bit doubles are downcast to floats. 531 * <p> 532 * This method supports either the tile format or the strip format of TIFF source files. The scan size indicates the number of columns to be extracted. For 533 * strips, the width and the scan size are always the full width of the image. For tiles, the scan size is the full width of the tile, but the width may be 534 * smaller in the cases where the tiles do not evenly divide the width (for example, a 256 pixel wide tile in a 257 pixel wide image would result in two 535 * columns of tiles, the second column having only one column of pixels that were worth extracting. 536 * 537 * @param width the width of the data block to be extracted 538 * @param height the height of the data block to be extracted 539 * @param scanSize the number of pixels in a single row of the block 540 * @param bytes the raw bytes 541 * @param bitsPerPixel the number of bits per sample, 32 or 64. 542 * @param byteOrder the byte order for the source data 543 * @return a valid array of integers in row major order, dimensions scan-size wide and height. 544 * @throws ImagingException in the event of an invalid format. 545 */ 546 protected int[] unpackFloatingPointSamples(final int width, final int height, final int scanSize, final byte[] bytes, final int bitsPerPixel, 547 final ByteOrder byteOrder) throws ImagingException { 548 final int bitsPerSample = bitsPerPixel / samplesPerPixel; 549 final int bytesPerSample = bitsPerSample / 8; 550 final int bytesPerScan = scanSize * samplesPerPixel * bytesPerSample; 551 final int nBytes = bytesPerScan * height; 552 final int length = bytes.length < nBytes ? nBytes / bytesPerScan : height; 553 final int[] samples = Allocator.intArray(scanSize * samplesPerPixel * height); 554 // floating-point differencing is indicated by a predictor value of 3. 555 if (predictor == TiffTagConstants.PREDICTOR_VALUE_FLOATING_POINT_DIFFERENCING) { 556 // at this time, this class supports the 32-bit format. The 557 // main reason for this is that we have not located sample data 558 // that can be used for testing and analysis. 559 if (bitsPerPixel / samplesPerPixel != 32) { 560 throw new ImagingException( 561 "Imaging does not yet support floating-point data" + " with predictor type 3 for " + bitsPerPixel + " bits per sample"); 562 } 563 564 if (planarConfiguration == TiffPlanarConfiguration.CHUNKY) { 565 final int bytesInRow = scanSize * 4 * samplesPerPixel; 566 for (int i = 0; i < length; i++) { 567 final int aOffset = i * bytesInRow; 568 final int bOffset = aOffset + scanSize * samplesPerPixel; 569 final int cOffset = bOffset + scanSize * samplesPerPixel; 570 final int dOffset = cOffset + scanSize * samplesPerPixel; 571 // in this loop, the source bytes give delta values. 572 // we adjust them to give true values. This operation is 573 // done on a row-by-row basis. 574 for (int j = 1; j < bytesInRow; j++) { 575 bytes[aOffset + j] += bytes[aOffset + j - 1]; 576 } 577 // pack the bytes into the integer bit-equivalent of 578 // floating point values 579 int index = i * scanSize; 580 for (int j = 0; j < width * samplesPerPixel; j++) { 581 final int a = bytes[aOffset + j]; 582 final int b = bytes[bOffset + j]; 583 final int c = bytes[cOffset + j]; 584 final int d = bytes[dOffset + j]; 585 // Pack the 4 byte components into a single integer 586 // in the byte order used by the TIFF standard 587 samples[index++] = (a & 0xff) << 24 | (b & 0xff) << 16 | (c & 0xff) << 8 | d & 0xff; 588 } 589 } 590 } else { 591 final int bytesInRow = scanSize * 4; 592 for (int iPlane = 0; iPlane < samplesPerPixel; iPlane++) { 593 final int planarIntOffset = iPlane * length * scanSize; 594 final int planarByteOffset = planarIntOffset * 4; 595 596 for (int i = 0; i < length; i++) { 597 final int aOffset = i * bytesInRow + planarByteOffset; 598 final int bOffset = aOffset + scanSize; 599 final int cOffset = bOffset + scanSize; 600 final int dOffset = cOffset + scanSize; 601 // in this loop, the source bytes give delta values. 602 // we adjust them to give true values. This operation is 603 // done on a row-by-row basis. 604 for (int j = 1; j < bytesInRow; j++) { 605 bytes[aOffset + j] += bytes[aOffset + j - 1]; 606 } 607 // pack the bytes into the integer bit-equivalent of 608 // floating point values 609 int index = planarIntOffset + i * scanSize; 610 for (int j = 0; j < width; j++) { 611 final int a = bytes[aOffset + j]; 612 final int b = bytes[bOffset + j]; 613 final int c = bytes[cOffset + j]; 614 final int d = bytes[dOffset + j]; 615 // Pack the 4 byte components into a single integer 616 // in the byte order used by the TIFF standard 617 samples[index++] = (a & 0xff) << 24 | (b & 0xff) << 16 | (c & 0xff) << 8 | d & 0xff; 618 } 619 } 620 } 621 622 } 623 return samples; 624 } // end of predictor==3 case. 625 626 // simple packing case, 64 or 32 bits -------------------------- 627 if (bitsPerSample == 64) { 628 int k = 0; 629 int index = 0; 630 for (int i = 0; i < length; i++) { 631 for (int j = 0; j < scanSize; j++) { 632 final long b0 = bytes[k++] & 0xffL; 633 final long b1 = bytes[k++] & 0xffL; 634 final long b2 = bytes[k++] & 0xffL; 635 final long b3 = bytes[k++] & 0xffL; 636 final long b4 = bytes[k++] & 0xffL; 637 final long b5 = bytes[k++] & 0xffL; 638 final long b6 = bytes[k++] & 0xffL; 639 final long b7 = bytes[k++] & 0xffL; 640 final long sbits; 641 if (byteOrder == ByteOrder.LITTLE_ENDIAN) { 642 sbits = b7 << 56 | b6 << 48 | b5 << 40 | b4 << 32 | b3 << 24 | b2 << 16 | b1 << 8 | b0; 643 644 } else { 645 sbits = b0 << 56 | b1 << 48 | b2 << 40 | b3 << 32 | b4 << 24 | b5 << 16 | b6 << 8 | b7; 646 } 647 // since the photometric interpreter does not 648 // currently support doubles, we need to replace this 649 // element with a float. This action is inefficient and 650 // should be improved. 651 final float f = (float) Double.longBitsToDouble(sbits); 652 samples[index++] = Float.floatToRawIntBits(f); 653 } 654 } 655 } else if (bitsPerSample == 32) { 656 int k = 0; 657 int index = 0; 658 for (int i = 0; i < length; i++) { 659 for (int j = 0; j < scanSize * samplesPerPixel; j++) { 660 final int b0 = bytes[k++] & 0xff; 661 final int b1 = bytes[k++] & 0xff; 662 final int b2 = bytes[k++] & 0xff; 663 final int b3 = bytes[k++] & 0xff; 664 final int sbits; 665 if (byteOrder == ByteOrder.LITTLE_ENDIAN) { 666 sbits = b3 << 24 | b2 << 16 | b1 << 8 | b0; 667 668 } else { 669 sbits = b0 << 24 | b1 << 16 | b2 << 8 | b3; 670 } 671 // since the photometric interpreter does not 672 // currently support doubles, we need to replace this 673 // element with a float. This action is inefficient and 674 // should be improved. 675 samples[index++] = sbits; 676 } 677 } 678 } else { 679 throw new ImagingException("Imaging does not support floating-point samples with " + bitsPerPixel + " bits per sample"); 680 } 681 682 return samples; 683 } 684 685 /** 686 * Given a source file that specifies numerical data as short integers, unpack the raw bytes obtained from the source file and organize them into an array 687 * of integers. 688 * <p> 689 * This method supports either the tile format or the strip format of TIFF source files. The scan size indicates the number of columns to be extracted. For 690 * strips, the width and the scan size are always the full width of the image. For tiles, the scan size is the full width of the tile, but the "width" 691 * parameter may be smaller in the cases where the tiles do not evenly divide the width (for example, a 256 pixel wide tile in a 257 pixel wide image would 692 * result in two columns of tiles, the second column having only one column of pixels that were worth extracting. 693 * 694 * @param width the width of the data block to be extracted 695 * @param height the height of the data block to be extracted 696 * @param scanSize the number of pixels in a single row of the block 697 * @param bytes the raw bytes 698 * @param predictor the predictor specified by the source, only predictor 3 is supported. 699 * @param bitsPerSample the number of bits per sample, 32 or 64. 700 * @param byteOrder the byte order for the source data 701 * @return a valid array of integers in row major order, dimensions scan-size wide and height. 702 */ 703 protected int[] unpackIntSamples(final int width, final int height, final int scanSize, final byte[] bytes, final int predictor, final int bitsPerSample, 704 final ByteOrder byteOrder) { 705 final int bytesPerSample = bitsPerSample / 8; 706 final int nBytes = bytesPerSample * scanSize * height; 707 final int length = bytes.length < nBytes ? nBytes / scanSize : height; 708 709 final int[] samples = Allocator.intArray(scanSize * height); 710 // At this time, Commons Imaging only supports two-byte 711 // two's complement short integers. It is assumed that 712 // the calling module already checked the arguments for 713 // compliance, so this method simply assumes that they are correct. 714 715 // The logic that follows is simplified by the fact that 716 // the existing API only supports two-byte signed integers. 717 final boolean useDifferencing = predictor == TiffTagConstants.PREDICTOR_VALUE_HORIZONTAL_DIFFERENCING; 718 719 for (int i = 0; i < length; i++) { 720 final int index = i * scanSize; 721 int offset = index * bytesPerSample; 722 if (bitsPerSample == 16) { 723 if (byteOrder == ByteOrder.LITTLE_ENDIAN) { 724 for (int j = 0; j < width; j++, offset += 2) { 725 samples[index + j] = bytes[offset + 1] << 8 | bytes[offset] & 0xff; 726 } 727 } else { 728 for (int j = 0; j < width; j++, offset += 2) { 729 samples[index + j] = bytes[offset] << 8 | bytes[offset + 1] & 0xff; 730 } 731 } 732 } else if (bitsPerSample == 32) { 733 if (byteOrder == ByteOrder.LITTLE_ENDIAN) { 734 for (int j = 0; j < width; j++, offset += 4) { 735 samples[index + j] = bytes[offset + 3] << 24 | (bytes[offset + 2] & 0xff) << 16 | (bytes[offset + 1] & 0xff) << 8 736 | bytes[offset] & 0xff; 737 } 738 } else { 739 for (int j = 0; j < width; j++, offset += 4) { 740 samples[index + j] = bytes[offset] << 24 | (bytes[offset + 1] & 0xff) << 16 | (bytes[offset + 2] & 0xff) << 8 741 | bytes[offset + 3] & 0xff; 742 } 743 } 744 } 745 if (useDifferencing) { 746 for (int j = 1; j < width; j++) { 747 samples[index + j] += samples[index + j - 1]; 748 } 749 } 750 } 751 752 return samples; 753 } 754}