public ImageBuilder readImageData()

in src/main/java/org/apache/commons/imaging/formats/tiff/datareaders/DataReaderStrips.java [248:342]


    public ImageBuilder readImageData(final Rectangle subImageSpecification,
        final boolean hasAlpha,
        final boolean isAlphaPreMultiplied)
        throws IOException, ImagingException {

        final Rectangle subImage;
        if (subImageSpecification == null) {
            // configure subImage to read entire image
            subImage = new Rectangle(0, 0, width, height);
        } else {
            subImage = subImageSpecification;
        }

        // the legacy code is optimized to the reading of whole
        // strips (except for the last strip in the image, which can
        // be a partial).  So create a working image with compatible
        // dimensions and read that.  Later on, the working image
        // will be sub-imaged to the proper size.
        // strip0 and strip1 give the indices of the strips containing
        // the first and last rows of pixels in the subimage
        final int strip0 = subImage.y / rowsPerStrip;
        final int strip1 = (subImage.y + subImage.height - 1) / rowsPerStrip;
        final int workingHeight = (strip1 - strip0 + 1) * rowsPerStrip;

        // the legacy code uses a member element "y" to keep track
        // of the row index of the output image that is being processed
        // by interpretStrip. y is set to zero before the first
        // call to interpretStrip.  y0 will be the index of the first row
        // in the full image (the source image) that will be processed.
        final int y0 = strip0 * rowsPerStrip;
        final int yLimit = subImage.y - y0 + subImage.height;

        final ImageBuilder workingBuilder
            = new ImageBuilder(width, workingHeight,
                hasAlpha, isAlphaPreMultiplied);
        if (planarConfiguration != TiffPlanarConfiguration.PLANAR) {
            for (int strip = strip0; strip <= strip1; strip++) {
                final long rowsPerStripLong = 0xFFFFffffL & rowsPerStrip;
                final long rowsRemaining = height - (strip * rowsPerStripLong);
                final long rowsInThisStrip = Math.min(rowsRemaining, rowsPerStripLong);
                final long bytesPerRow = (bitsPerPixel * width + 7) / 8;
                final long bytesPerStrip = rowsInThisStrip * bytesPerRow;
                final long pixelsPerStrip = rowsInThisStrip * width;

                final byte[] compressed = imageData.getImageData(strip).getData();

                final byte[] decompressed = decompress(compressed, compression,
                        (int) bytesPerStrip, width, (int) rowsInThisStrip);

                interpretStrip(
                    workingBuilder,
                    decompressed,
                    (int) pixelsPerStrip,
                    yLimit);
            }
        } else {
            final int nStripsInPlane = imageData.getImageDataLength() / 3;
            for (int strip = strip0; strip <= strip1; strip++) {
                final long rowsPerStripLong = 0xFFFFffffL & rowsPerStrip;
                final long rowsRemaining = height - (strip * rowsPerStripLong);
                final long rowsInThisStrip = Math.min(rowsRemaining, rowsPerStripLong);
                final long bytesPerRow = (bitsPerPixel * width + 7) / 8;
                final long bytesPerStrip = rowsInThisStrip * bytesPerRow;
                final long pixelsPerStrip = rowsInThisStrip * width;

                final byte[] b = Allocator.byteArray((int) bytesPerStrip);
                for (int iPlane = 0; iPlane < 3; iPlane++) {
                    final int planeStrip = iPlane * nStripsInPlane + strip;
                    final byte[] compressed = imageData.getImageData(planeStrip).getData();
                    final byte[] decompressed = decompress(compressed, compression,
                        (int) bytesPerStrip, width, (int) rowsInThisStrip);
                    int index = iPlane;
                    for (final byte element : decompressed) {
                        b[index] = element;
                        index += 3;
                    }
                }
                interpretStrip(workingBuilder, b, (int) pixelsPerStrip, height);
            }
        }

        if (subImage.x == 0
                && subImage.y == y0
                && subImage.width == width
                && subImage.height == workingHeight) {
            // the subimage exactly matches the ImageBuilder bounds
            // so we can return that.
            return workingBuilder;
        }
        return workingBuilder.getSubset(
                subImage.x,
                subImage.y - y0,
                subImage.width,
                subImage.height);
    }