diff --git a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java index e85b098b047..9559616a290 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java @@ -84,6 +84,9 @@ public final class PDImageXObject extends PDXObject implements PDImage private boolean jpxValuesInitialized = false; private BufferedImage jpxSMask = null; + // PDFBOX-5876: upper bound for the subsampling used by initJPXValues method. + private static final int JPX_METADATA_SUBSAMPLING = 8; + /** * current resource dictionary (has color spaces) */ @@ -739,7 +742,12 @@ private void initJPXValues() // bits per component // the colorspace of the image is used if the dictionary doesn't provide any value PDStream stream = getStream(); - try (COSInputStream is = stream.createInputStream()) + // PDFBOX-5876: subsample this metadata-only read, see the JPX_METADATA_SUBSAMPLING field. + // Not when a soft mask may be extracted from the image data, because that mask is kept + // and used later at its own resolution, so it must not be subsampled. + try (COSInputStream is = mayHaveJPXSMask() + ? stream.createInputStream() + : stream.createInputStream(new DecodeOptions(JPX_METADATA_SUBSAMPLING))) { DecodeResult decodeResult = is.getDecodeResult(); stream.getCOSObject().addAll(decodeResult.getParameters()); @@ -756,6 +764,19 @@ private void initJPXValues() } } + /** + * Tells whether decoding this image may produce a soft mask taken from the image data + * (PDFBOX-5657). {@code JPXFilter} only extracts such a mask when the image dictionary has no + * /ColorSpace entry and a positive /SMaskInData entry, so both are checked here to mirror it. + * + * @return true if a soft mask may be extracted from the image data. + */ + private boolean mayHaveJPXSMask() + { + COSDictionary dict = getCOSObject(); + return !dict.containsKey(COSName.COLORSPACE) && dict.getInt(COSName.SMASK_IN_DATA) > 0; + } + /** * High-quality image scaling. */