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