private static BufferedImage fromAny()

in pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/SampledImageReader.java [554:703]


    private static BufferedImage fromAny(PDImage pdImage, WritableRaster raster, COSArray colorKey, Rectangle clipped,
                                         final int subsampling, final int width, final int height)
            throws IOException
    {
        int currentSubsampling = subsampling;
        final PDColorSpace colorSpace = pdImage.getColorSpace();
        final int numComponents = colorSpace.getNumberOfComponents();
        final int bitsPerComponent = pdImage.getBitsPerComponent();
        final float[] decode = getDecodeArray(pdImage);

        DecodeOptions options = new DecodeOptions(currentSubsampling);
        options.setSourceRegion(clipped);
        // MemoryCacheImageInputStream doesn't close the wrapped stream
        try (InputStream imageStream = pdImage.createInputStream(options))
        {
            // read bit stream
            try (ImageInputStream iis = new MemoryCacheImageInputStream(imageStream))
            {
                final int inputWidth;
                final int startx;
                final int starty;
                final int scanWidth;
                final int scanHeight;
                if (options.isFilterSubsampled())
                {
                    // Decode options were honored, and so there is no need for additional clipping or subsampling
                    inputWidth = width;
                    startx = 0;
                    starty = 0;
                    scanWidth = width;
                    scanHeight = height;
                    currentSubsampling = 1;
                }
                else
                {
                    // Decode options not honored, so we need to clip and subsample ourselves.
                    inputWidth = pdImage.getWidth();
                    startx = clipped.x;
                    starty = clipped.y;
                    scanWidth = clipped.width;
                    scanHeight = clipped.height;
                }
                final float sampleMax = (float) Math.pow(2, bitsPerComponent) - 1f;
                final boolean isIndexed = colorSpace instanceof PDIndexed;

                // init color key mask
                float[] colorKeyRanges = null;
                BufferedImage colorKeyMask = null;
                if (colorKey != null)
                {
                    if (colorKey.size() >= numComponents * 2)
                    {
                        colorKeyRanges = colorKey.toFloatArray();
                        colorKeyMask = new BufferedImage(width, height,
                                BufferedImage.TYPE_BYTE_GRAY);
                    }
                    else
                    {
                        LOG.warn("colorKey mask size is {}, should be {}, ignored", colorKey.size(),
                                numComponents * 2);
                    }
                }

                // calculate row padding
                int padding = 0;
                if (inputWidth * numComponents * bitsPerComponent % 8 > 0)
                {
                    padding = 8 - (inputWidth * numComponents * bitsPerComponent % 8);
                }

                // read stream
                byte[] srcColorValues = new byte[numComponents];
                byte[] alpha = new byte[1];
                for (int y = 0; y < starty + scanHeight; y++)
                {
                    for (int x = 0; x < startx + scanWidth; x++)
                    {
                        boolean isMasked = true;
                        for (int c = 0; c < numComponents; c++)
                        {
                            int value = (int) iis.readBits(bitsPerComponent);

                            // color key mask requires values before they are decoded
                            if (colorKeyRanges != null)
                            {
                                isMasked &= value >= colorKeyRanges[c * 2]
                                        && value <= colorKeyRanges[c * 2 + 1];
                            }

                            // decode array
                            final float dMin = decode[c * 2];
                            final float dMax = decode[(c * 2) + 1];

                            // interpolate to domain
                            float output = dMin + (value * ((dMax - dMin) / sampleMax));

                            if (isIndexed)
                            {
                                // indexed color spaces get the raw value, because the TYPE_BYTE
                                // below cannot be reversed by the color space without it having
                                // knowledge of the number of bits per component
                                srcColorValues[c] = (byte) Math.round(output);
                            }
                            else
                            {
                                // interpolate to TYPE_BYTE
                                int outputByte = Math.round(
                                        ((output - Math.min(dMin, dMax)) / Math.abs(dMax - dMin))
                                                * 255f);

                                srcColorValues[c] = (byte) outputByte;
                            }
                        }
                        // only write to output if within requested region and subsample.
                        if (x >= startx && y >= starty && x % currentSubsampling == 0
                                && y % currentSubsampling == 0)
                        {
                            raster.setDataElements((x - startx) / currentSubsampling,
                                    (y - starty) / currentSubsampling, srcColorValues);

                            // set alpha channel in color key mask, if any
                            if (colorKeyMask != null)
                            {
                                alpha[0] = (byte) (isMasked ? 255 : 0);
                                colorKeyMask.getRaster().setDataElements(
                                        (x - startx) / currentSubsampling,
                                        (y - starty) / currentSubsampling, alpha);
                            }
                        }
                    }

                    // rows are padded to the nearest byte
                    iis.readBits(padding);
                }

                // use the color space to convert the image to RGB
                BufferedImage rgbImage = colorSpace.toRGBImage(raster);

                // apply color mask, if any
                if (colorKeyMask != null)
                {
                    return applyColorKeyMask(rgbImage, colorKeyMask);
                }
                else
                {
                    return rgbImage;
                }
            }
        }
    }