Author: lehmi Date: Sun Dec 31 11:25:56 2023 New Revision: 1915019 URL: http://svn.apache.org/viewvc?rev=1915019&view=rev Log: PDFBOX-5375: extract JPX values from image stream on first access
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java?rev=1915019&r1=1915018&r2=1915019&view=diff ============================================================================== --- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java (original) +++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java Sun Dec 31 11:25:56 2023 @@ -80,6 +80,8 @@ public final class PDImageXObject extend private int cachedImageSubsampling = Integer.MAX_VALUE; // indicates whether this image has an JPX-based filter applied private boolean hasJPXFilter = false; + // is set to true after reading some values from a JPX-based image + private boolean jpxValuesInitialized = false; /** * current resource dictionary (has color spaces) @@ -449,7 +451,7 @@ public final class PDImageXObject extend return cached; } } - + initJPXValues(); // get RGB image w/o reference because applyMask might modify it, take long time and a lot of memory. final BufferedImage image; final PDImageXObject softMask = getSoftMask(); @@ -694,6 +696,34 @@ public final class PDImageXObject extend return color < 0 ? 0 : color > 255 ? 255 : color; } + private void initJPXValues() + { + if (!hasJPXFilter || jpxValuesInitialized) + { + return; + } + // some of the dictionary values of the COSStream may be overwritten by values which are extracted from the + // image itself, such as + // width and height of the image + // 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()) + { + DecodeResult decodeResult = is.getDecodeResult(); + stream.getCOSObject().addAll(decodeResult.getParameters()); + if (colorSpace == null) + { + colorSpace = decodeResult.getJPXColorSpace(); + } + jpxValuesInitialized = true; + } + catch (IOException exception) + { + LOG.debug("Can't initialize JPX based values", exception); + } + } + /** * High-quality image scaling. */ @@ -794,6 +824,7 @@ public final class PDImageXObject extend } else { + initJPXValues(); return getCOSObject().getInt(COSName.BITS_PER_COMPONENT, COSName.BPC); } } @@ -836,15 +867,9 @@ public final class PDImageXObject extend // stencil mask color space must be gray, it is often missing colorSpace = PDDeviceGray.INSTANCE; } - else if (hasJPXFilter) + else { - PDStream stream = getStream(); - try (COSInputStream is = stream.createInputStream()) - { - DecodeResult decodeResult = is.getDecodeResult(); - stream.getCOSObject().addAll(decodeResult.getParameters()); - colorSpace = decodeResult.getJPXColorSpace(); - } + initJPXValues(); } if (colorSpace == null) { @@ -890,6 +915,7 @@ public final class PDImageXObject extend @Override public int getHeight() { + initJPXValues(); return getCOSObject().getInt(COSName.HEIGHT); } @@ -902,6 +928,7 @@ public final class PDImageXObject extend @Override public int getWidth() { + initJPXValues(); return getCOSObject().getInt(COSName.WIDTH); }