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}