protected BufferedImage getBufferedImage()

in src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java [248:398]


    protected BufferedImage getBufferedImage(final TiffDirectory directory,
            final ByteOrder byteOrder, final TiffImagingParameters params)
            throws ImagingException, IOException {
        final short compressionFieldValue;
        if (directory.findField(TiffTagConstants.TIFF_TAG_COMPRESSION) != null) {
            compressionFieldValue = directory.getFieldValue(TiffTagConstants.TIFF_TAG_COMPRESSION);
        } else {
            compressionFieldValue = TIFF_COMPRESSION_UNCOMPRESSED_1;
        }
        final int compression = 0xffff & compressionFieldValue;
        final int width = directory.getSingleFieldValue(TiffTagConstants.TIFF_TAG_IMAGE_WIDTH);
        final int height = directory.getSingleFieldValue(TiffTagConstants.TIFF_TAG_IMAGE_LENGTH);

        final Rectangle subImage = checkForSubImage(params);
        if (subImage != null) {
            // Check for valid subimage specification. The following checks
            // are consistent with BufferedImage.getSubimage()
            if (subImage.width <= 0) {
                throw new ImagingException("Negative or zero subimage width.");
            }
            if (subImage.height <= 0) {
                throw new ImagingException("Negative or zero subimage height.");
            }
            if (subImage.x < 0 || subImage.x >= width) {
                throw new ImagingException("Subimage x is outside raster.");
            }
            if (subImage.x + subImage.width > width) {
                throw new ImagingException("Subimage (x+width) is outside raster.");
            }
            if (subImage.y < 0 || subImage.y >= height) {
                throw new ImagingException("Subimage y is outside raster.");
            }
            if (subImage.y + subImage.height > height) {
                throw new ImagingException("Subimage (y+height) is outside raster.");
            }
        }

        int samplesPerPixel = 1;
        final TiffField samplesPerPixelField = directory.findField(
                TiffTagConstants.TIFF_TAG_SAMPLES_PER_PIXEL);
        if (samplesPerPixelField != null) {
            samplesPerPixel = samplesPerPixelField.getIntValue();
        }
        int[] bitsPerSample = { 1 };
        int bitsPerPixel = samplesPerPixel;
        final TiffField bitsPerSampleField = directory.findField(
                TiffTagConstants.TIFF_TAG_BITS_PER_SAMPLE);
        if (bitsPerSampleField != null) {
            bitsPerSample = bitsPerSampleField.getIntArrayValue();
            bitsPerPixel = bitsPerSampleField.getIntValueOrArraySum();
        }

        // int bitsPerPixel = getTagAsValueOrArraySum(entries,
        // TIFF_TAG_BITS_PER_SAMPLE);

        int predictor = -1;
        {
            // dumpOptionalNumberTag(entries, TIFF_TAG_FILL_ORDER);
            // dumpOptionalNumberTag(entries, TIFF_TAG_FREE_BYTE_COUNTS);
            // dumpOptionalNumberTag(entries, TIFF_TAG_FREE_OFFSETS);
            // dumpOptionalNumberTag(entries, TIFF_TAG_ORIENTATION);
            // dumpOptionalNumberTag(entries, TIFF_TAG_PLANAR_CONFIGURATION);
            final TiffField predictorField = directory.findField(
                    TiffTagConstants.TIFF_TAG_PREDICTOR);
            if (null != predictorField) {
                predictor = predictorField.getIntValueOrArraySum();
            }
        }

        if (samplesPerPixel != bitsPerSample.length) {
            throw new ImagingException("Tiff: samplesPerPixel ("
                    + samplesPerPixel + ")!=fBitsPerSample.length ("
                    + bitsPerSample.length + ")");
        }


        final int photometricInterpretation = 0xffff & directory.getFieldValue(
                TiffTagConstants.TIFF_TAG_PHOTOMETRIC_INTERPRETATION);

        boolean hasAlpha = false;
        boolean isAlphaPremultiplied = false;
        if (photometricInterpretation == TiffTagConstants.PHOTOMETRIC_INTERPRETATION_VALUE_RGB
                && samplesPerPixel == 4) {
            final TiffField extraSamplesField
                    = directory.findField(TiffTagConstants.TIFF_TAG_EXTRA_SAMPLES);
            if (extraSamplesField == null) {
                // this state is not defined in the TIFF specification
                // and so this code will interpret it as meaning that the
                // proper handling would be ARGB.
                hasAlpha = true;
                isAlphaPremultiplied = false;
            } else {
                final int extraSamplesValue = extraSamplesField.getIntValue();
                switch (extraSamplesValue) {
                    case TiffTagConstants.EXTRA_SAMPLE_UNASSOCIATED_ALPHA:
                        hasAlpha = true;
                        isAlphaPremultiplied = false;
                        break;
                    case TiffTagConstants.EXTRA_SAMPLE_ASSOCIATED_ALPHA:
                        hasAlpha = true;
                        isAlphaPremultiplied = true;
                        break;
                    case 0:
                    default:
                        hasAlpha = false;
                        isAlphaPremultiplied = false;
                        break;
                }
            }
        }

        PhotometricInterpreter photometricInterpreter = params.getCustomPhotometricInterpreter();
        if (photometricInterpreter == null) {
            photometricInterpreter = getPhotometricInterpreter(
                directory, photometricInterpretation, bitsPerPixel,
                bitsPerSample, predictor, samplesPerPixel, width, height);
        }

        // Obtain the planar configuration
        final TiffField pcField = directory.findField(
          TiffTagConstants.TIFF_TAG_PLANAR_CONFIGURATION);
        final TiffPlanarConfiguration planarConfiguration
          = pcField == null
            ? TiffPlanarConfiguration.CHUNKY
            : TiffPlanarConfiguration.lenientValueOf(pcField.getIntValue());

        if (planarConfiguration == TiffPlanarConfiguration.PLANAR) {
            // currently, we support the non-interleaved (non-chunky)
            // option only in the case of a 24-bit RBG photometric interpreter
            // and for strips (not for tiles).
            if (photometricInterpretation
              != TiffTagConstants.PHOTOMETRIC_INTERPRETATION_VALUE_RGB
              || bitsPerPixel != 24) {
                throw new ImagingException("For planar configuration 2, only 24 bit RGB is currently supported");
            }
            if (null == directory.findField(TiffTagConstants.TIFF_TAG_STRIP_OFFSETS)) {
                throw new ImagingException("For planar configuration 2, only strips-organization is supported");
            }
        }

        final TiffImageData imageData = directory.getTiffImageData();

        final ImageDataReader dataReader = imageData.getDataReader(directory,
                photometricInterpreter, bitsPerPixel, bitsPerSample, predictor,
          samplesPerPixel, width, height, compression,
          planarConfiguration, byteOrder);

        final ImageBuilder iBuilder = dataReader.readImageData(
            subImage, hasAlpha, isAlphaPremultiplied);
        return iBuilder.getBufferedImage();
    }