View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.imaging.formats.tiff.datareaders;
18  
19  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_CCITT_1D;
20  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_3;
21  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_4;
22  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_DEFLATE_ADOBE;
23  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_DEFLATE_PKZIP;
24  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_LZW;
25  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_PACKBITS;
26  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_UNCOMPRESSED;
27  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_FLAG_T4_OPTIONS_2D;
28  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_FLAG_T4_OPTIONS_FILL;
29  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_FLAG_T4_OPTIONS_UNCOMPRESSED_MODE;
30  import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_FLAG_T6_OPTIONS_UNCOMPRESSED_MODE;
31  
32  import java.awt.Rectangle;
33  import java.io.ByteArrayInputStream;
34  import java.io.IOException;
35  import java.io.InputStream;
36  import java.nio.ByteOrder;
37  import java.util.Arrays;
38  
39  import org.apache.commons.imaging.ImagingException;
40  import org.apache.commons.imaging.common.Allocator;
41  import org.apache.commons.imaging.common.ImageBuilder;
42  import org.apache.commons.imaging.common.PackBits;
43  import org.apache.commons.imaging.common.ZlibDeflate;
44  import org.apache.commons.imaging.formats.tiff.TiffDirectory;
45  import org.apache.commons.imaging.formats.tiff.TiffField;
46  import org.apache.commons.imaging.formats.tiff.TiffRasterData;
47  import org.apache.commons.imaging.formats.tiff.constants.TiffPlanarConfiguration;
48  import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
49  import org.apache.commons.imaging.formats.tiff.itu_t4.T4AndT6Compression;
50  import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreter;
51  import org.apache.commons.imaging.mylzw.MyLzwDecompressor;
52  
53  /**
54   * 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
55   * class defines common elements for both representations.
56   * <p>
57   * <strong>The TIFF Floating-Point Formats </strong>
58   * <p>
59   * 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
60   * support some floating-point data formats.
61   * <p>
62   * 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
63   * 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
64   * floating-point data that can be processed as additional test data become available. When implementing extensions to this logic, developers are reminded that
65   * image processing requires the handling of literally millions of pixels, so attention to performance is essential to a successful implementation (please see
66   * the notes in {@link DataReaderStrips} for more information).
67   * <p>
68   * 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
69   * documentation and C-code examples are available in "TIFF Technical Note 3, April 8, 2005)".
70   * <p>
71   * <strong>The Predictor==3 Case</strong>
72   * <p>
73   * TIFF specifies an extension for a predictor that is intended to improve data compression ratios for floating-point values. This predictor is specified using
74   * 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
75   * 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
76   * 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
77   * byte, followed by the one remaining exponent bit and the mantissa in the lower-order bytes.
78   * <p>
79   * 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
80   * 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
81   * 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.
82   * 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
83   * length 3 pixels -- A, B, and C -- the data for two rows would be given as shown below (again, ignoring endian issues):
84   *
85   * <pre>
86   *   Original:
87   *      A3 A2 A1 A0   B3 B2 B1 B0   C3 C2 C1 C0
88   *      D3 D3 D1 D0   E3 E2 E2 E0   F3 F2 F1 F0
89   *
90   *   Bytes split into groups by order-of-magnitude:
91   *      A3 B3 C3   A2 B2 C2   A1 B1 C1   A0 B0 C0
92   *      D3 E3 F3   D2 E2 F2   D1 E1 F1   D0 E0 F0
93   * </pre>
94   *
95   * To further improve the compression, the predictor takes the difference of each subsequent bytes. Again, the differences (deltas) are computed on a
96   * 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
97   * end of each order-of-magnitude set (shown in parentheses):
98   *
99   * <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  */
144 public 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 }