Author: lehmi Date: Sun Dec 31 11:24:12 2023 New Revision: 1915018 URL: http://svn.apache.org/viewvc?rev=1915018&view=rev Log: PDFBOX-5375: extract JPX values from image stream on first access
Modified: pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java Modified: pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java URL: http://svn.apache.org/viewvc/pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java?rev=1915018&r1=1915017&r2=1915018&view=diff ============================================================================== --- pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java (original) +++ pdfbox/branches/3.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java Sun Dec 31 11:24:12 2023 @@ -81,6 +81,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) @@ -451,6 +453,8 @@ public final class PDImageXObject extend } } + 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(); @@ -695,6 +699,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. */ @@ -795,6 +827,7 @@ public final class PDImageXObject extend } else { + initJPXValues(); return getCOSObject().getInt(COSName.BITS_PER_COMPONENT, COSName.BPC); } } @@ -837,15 +870,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) { @@ -891,6 +918,7 @@ public final class PDImageXObject extend @Override public int getHeight() { + initJPXValues(); return getCOSObject().getInt(COSName.HEIGHT); } @@ -903,6 +931,7 @@ public final class PDImageXObject extend @Override public int getWidth() { + initJPXValues(); return getCOSObject().getInt(COSName.WIDTH); }