Search in sources :

Example 1 with DecodeOptions

use of org.apache.pdfbox.filter.DecodeOptions in project pdfbox by apache.

the class SampledImageReader method from8bit.

// faster, 8-bit non-decoded, non-colormasked image conversion
private static BufferedImage from8bit(PDImage pdImage, WritableRaster raster, Rectangle clipped, final int subsampling, final int width, final int height) throws IOException {
    int currentSubsampling = subsampling;
    DecodeOptions options = new DecodeOptions(currentSubsampling);
    options.setSourceRegion(clipped);
    try (InputStream input = pdImage.createInputStream(options)) {
        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 int numComponents = pdImage.getColorSpace().getNumberOfComponents();
        // get the raster's underlying byte buffer
        byte[] bank = ((DataBufferByte) raster.getDataBuffer()).getData();
        if (startx == 0 && starty == 0 && scanWidth == width && scanHeight == height && currentSubsampling == 1) {
            // we just need to copy all sample data, then convert to RGB image.
            long inputResult = input.read(bank);
            if (Long.compare(inputResult, width * height * (long) numComponents) != 0) {
                LOG.debug("Tried reading " + width * height * (long) numComponents + " bytes but only " + inputResult + " bytes read");
            }
            return pdImage.getColorSpace().toRGBImage(raster);
        }
        // either subsampling is required, or reading only part of the image, so its
        // not possible to blindly copy all data.
        byte[] tempBytes = new byte[numComponents * inputWidth];
        // compromise between memory and time usage:
        // reading the whole image consumes too much memory
        // reading one pixel at a time makes it slow in our buffering infrastructure
        int i = 0;
        for (int y = 0; y < starty + scanHeight; ++y) {
            long inputResult = input.read(tempBytes);
            if (Long.compare(inputResult, tempBytes.length) != 0) {
                LOG.debug("Tried reading " + tempBytes.length + " bytes but only " + inputResult + " bytes read");
            }
            if (y < starty || y % currentSubsampling > 0) {
                continue;
            }
            if (currentSubsampling == 1) {
                // Not the entire region was requested, but if no subsampling should
                // be performed, we can still copy the entire part of this row
                System.arraycopy(tempBytes, startx * numComponents, bank, y * inputWidth * numComponents, scanWidth * numComponents);
            } else {
                for (int x = startx; x < startx + scanWidth; x += currentSubsampling) {
                    for (int c = 0; c < numComponents; c++) {
                        bank[i] = tempBytes[x * numComponents + c];
                        ++i;
                    }
                }
            }
        }
        // use the color space to convert the image to RGB
        return pdImage.getColorSpace().toRGBImage(raster);
    }
}
Also used : ImageInputStream(javax.imageio.stream.ImageInputStream) MemoryCacheImageInputStream(javax.imageio.stream.MemoryCacheImageInputStream) InputStream(java.io.InputStream) DataBufferByte(java.awt.image.DataBufferByte) Point(java.awt.Point) Paint(java.awt.Paint) DecodeOptions(org.apache.pdfbox.filter.DecodeOptions)

Example 2 with DecodeOptions

use of org.apache.pdfbox.filter.DecodeOptions in project pdfbox by apache.

the class SampledImageReader method from1Bit.

private static BufferedImage from1Bit(PDImage pdImage, Rectangle clipped, final int subsampling, final int width, final int height) throws IOException {
    int currentSubsampling = subsampling;
    final PDColorSpace colorSpace = pdImage.getColorSpace();
    final float[] decode = getDecodeArray(pdImage);
    BufferedImage bim = null;
    WritableRaster raster;
    byte[] output;
    DecodeOptions options = new DecodeOptions(currentSubsampling);
    options.setSourceRegion(clipped);
    // read bit stream
    try (InputStream iis = pdImage.createInputStream(options)) {
        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;
        }
        if (colorSpace instanceof PDDeviceGray) {
            // TYPE_BYTE_GRAY and not TYPE_BYTE_BINARY because this one is handled
            // without conversion to RGB by Graphics.drawImage
            // this reduces the memory footprint, only one byte per pixel instead of three.
            bim = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
            raster = bim.getRaster();
        } else {
            raster = Raster.createBandedRaster(DataBuffer.TYPE_BYTE, width, height, 1, new Point(0, 0));
        }
        output = ((DataBufferByte) raster.getDataBuffer()).getData();
        final boolean isIndexed = colorSpace instanceof PDIndexed;
        int rowLen = inputWidth / 8;
        if (inputWidth % 8 > 0) {
            rowLen++;
        }
        // read stream
        byte value0;
        byte value1;
        if (isIndexed || decode[0] < decode[1]) {
            value0 = 0;
            value1 = (byte) 255;
        } else {
            value0 = (byte) 255;
            value1 = 0;
        }
        byte[] buff = new byte[rowLen];
        int idx = 0;
        for (int y = 0; y < starty + scanHeight; y++) {
            int x = 0;
            int readLen = iis.read(buff);
            if (y < starty || y % currentSubsampling > 0) {
                continue;
            }
            for (int r = 0; r < rowLen && r < readLen; r++) {
                int value = buff[r];
                int mask = 128;
                for (int i = 0; i < 8; i++) {
                    if (x >= startx + scanWidth) {
                        break;
                    }
                    int bit = value & mask;
                    mask >>= 1;
                    if (x >= startx && x % currentSubsampling == 0) {
                        output[idx++] = bit == 0 ? value0 : value1;
                    }
                    x++;
                }
            }
            if (readLen != rowLen) {
                LOG.warn("premature EOF, image will be incomplete");
                break;
            }
        }
        if (bim != null) {
            return bim;
        }
        // use the color space to convert the image to RGB
        return colorSpace.toRGBImage(raster);
    }
}
Also used : PDIndexed(org.apache.pdfbox.pdmodel.graphics.color.PDIndexed) ImageInputStream(javax.imageio.stream.ImageInputStream) MemoryCacheImageInputStream(javax.imageio.stream.MemoryCacheImageInputStream) InputStream(java.io.InputStream) Point(java.awt.Point) Point(java.awt.Point) Paint(java.awt.Paint) BufferedImage(java.awt.image.BufferedImage) DecodeOptions(org.apache.pdfbox.filter.DecodeOptions) PDDeviceGray(org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray) WritableRaster(java.awt.image.WritableRaster) PDColorSpace(org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace)

Example 3 with DecodeOptions

use of org.apache.pdfbox.filter.DecodeOptions in project pdfbox by apache.

the class SampledImageReader method fromAny.

// slower, general-purpose image conversion from any image format
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);
    // read bit stream
    try (ImageInputStream iis = new MemoryCacheImageInputStream(pdImage.createInputStream(options))) {
        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) {
            colorKeyRanges = colorKey.toFloatArray();
            colorKeyMask = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
        }
        // 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;
        }
    }
}
Also used : PDIndexed(org.apache.pdfbox.pdmodel.graphics.color.PDIndexed) ImageInputStream(javax.imageio.stream.ImageInputStream) MemoryCacheImageInputStream(javax.imageio.stream.MemoryCacheImageInputStream) MemoryCacheImageInputStream(javax.imageio.stream.MemoryCacheImageInputStream) Point(java.awt.Point) Paint(java.awt.Paint) DecodeOptions(org.apache.pdfbox.filter.DecodeOptions) BufferedImage(java.awt.image.BufferedImage) PDColorSpace(org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace)

Aggregations

Paint (java.awt.Paint)3 Point (java.awt.Point)3 ImageInputStream (javax.imageio.stream.ImageInputStream)3 MemoryCacheImageInputStream (javax.imageio.stream.MemoryCacheImageInputStream)3 DecodeOptions (org.apache.pdfbox.filter.DecodeOptions)3 BufferedImage (java.awt.image.BufferedImage)2 InputStream (java.io.InputStream)2 PDColorSpace (org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace)2 PDIndexed (org.apache.pdfbox.pdmodel.graphics.color.PDIndexed)2 DataBufferByte (java.awt.image.DataBufferByte)1 WritableRaster (java.awt.image.WritableRaster)1 PDDeviceGray (org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray)1