[
https://issues.apache.org/jira/browse/PDFBOX-4598?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16888436#comment-16888436
]
Hee Jeong Kim edited comment on PDFBOX-4598 at 7/19/19 1:49 AM:
----------------------------------------------------------------
Hi Tilman, Jörg!
Thank you for your comments. I could understand why that part was needed.
As Jörg suggested, we can make 1 bpp is returned for the unscaled case only.
[^approach_1.patch]
Or we may move (or copy) codes that adjusting type of image from pdfbox so that
jbig2-imageio return BufferedImage with TYPE_BYTE_BINARY not TYPE_BYTE_INDEXED.
[https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java#L122]
[^approach_2.patch]
Actually, I found this issue because my code to avoid out of memory didn't work.
Sometimes I get out of memory exception because of a image of high resolution
(or large) in pdf files.
So I wrote a code to check how much memory image COSStream will take after
decoding, and if its size is huge, my code ignores the COSStream.
{code:java}
private static final float TO_MB = 1 / 1024f / 1024f;
public static boolean isHugeImage(COSStream stream, PDResources resources) {
int imageWidth = stream.getInt(COSName.WIDTH);
int imageHeight = stream.getInt(COSName.HEIGHT);
int numOfColorComponentsPerSample;
try {
numOfColorComponentsPerSample = getColorSpace(stream,
resources).getNumberOfComponents();
} catch (Exception e) {
return getRoughSizeOfImageInMB(imageWidth, imageHeight) >
Constants.PDF_IMAGE_SIZE_LIMIT_IN_MB;
}
int numOfBitsPerColorComponent = getBitsPerComponent(stream);
return TO_MB * imageWidth * imageHeight * numOfBitsPerColorComponent / 8
* numOfColorComponentsPerSample > Constants.PDF_IMAGE_SIZE_LIMIT_IN_MB;
}
//
https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java#L686
private static PDColorSpace getColorSpace(COSStream stream, PDResources
resources) throws IOException {
COSBase cosBase = stream.getDictionaryObject(COSName.COLORSPACE, COSName.CS);
if (cosBase != null) {
return PDColorSpace.create(cosBase, resources);
} else if (isStencil(stream)) {
// stencil mask color space must be gray, it is often missing
return PDDeviceGray.INSTANCE;
} else {
// an image without a color space is always broken
throw new IOException("could not determine color space");
}
}
//
https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java#L667
private static int getBitsPerComponent(COSStream stream) {
return isStencil(stream) ? 1 : stream.getInt(COSName.BITS_PER_COMPONENT,
COSName.BPC);
}
//
https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java#L810
private static boolean isStencil(COSStream stream) {
return stream.getBoolean(COSName.IMAGE_MASK, false);
}{code}
isHugeImage method returns false because it calculate the size of image with
numOfBitsPerColorComponent which is 1.
so my code decodes the jbig2 image and gets out of memory exception because
jbig2-imageio creates BufferedImage with numOfBitsPerColorComponent which is 8..
I don't scale image in my code so my code will work well with approach_1.patch
/ approach_2.path,
but above patches can still generate the same issue in the future when someone
try to read scaled jbig2 image, I think..
So I still have a question. I don't know much about this area but..
Losing information because of scaling is really unusal? Should information not
lost after scaling down?
[https://en.wikipedia.org/wiki/Image_resolution#/media/File:Resolution_illustration.png]
Or why don't we use box scaling?
You can test with [^approach_3.patch] and [^amb_2.jb2].
please run JBIG2ImageReaderDemo to test.
was (Author: heejeong kim):
Hi Tilman, Jörg!
Thank you for your comments. I could understand why that part was needed.
As Jörg suggested, we can make 1 bpp is returned for the unscaled case only.
[^approach_1.patch]
Or we may move (or copy) codes that adjusting type of image from pdfbox so that
jbig2-imageio return BufferedImage with TYPE_BYTE_BINARY not TYPE_BYTE_INDEXED.
https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java#L122
[^approach_2.patch]
Actually, I found this issue because my code to avoid out of memory didn't work.
Sometimes I get out of memory exception because of a image of high resolution
(or large) in pdf files.
So I wrote a code to check how much memory image COSStream will take after
decoding, and if its size is huge, my code ignores the COSStream.
{{{code:java}}}
private static final float TO_MB = 1 / 1024f / 1024f;
public static boolean isHugeImage(COSStream stream, PDResources resources) {
int imageWidth = stream.getInt(COSName.WIDTH);
int imageHeight = stream.getInt(COSName.HEIGHT);
int numOfColorComponentsPerSample;
try {
numOfColorComponentsPerSample = getColorSpace(stream,
resources).getNumberOfComponents();
} catch (Exception e) {
return getRoughSizeOfImageInMB(imageWidth, imageHeight) >
Constants.PDF_IMAGE_SIZE_LIMIT_IN_MB;
}
System.out.println("numOfColorComponentsPerSample=" +
numOfColorComponentsPerSample);
int numOfBitsPerColorComponent = getBitsPerComponent(stream);
return TO_MB * imageWidth * imageHeight * numOfBitsPerColorComponent / 8
* numOfColorComponentsPerSample > Constants.PDF_IMAGE_SIZE_LIMIT_IN_MB;
}
//
https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java#L686
private static PDColorSpace getColorSpace(COSStream stream, PDResources
resources) throws IOException {
COSBase cosBase = stream.getDictionaryObject(COSName.COLORSPACE, COSName.CS);
if (cosBase != null) {
return PDColorSpace.create(cosBase, resources);
} else if (isStencil(stream)) {
// stencil mask color space must be gray, it is often missing
return PDDeviceGray.INSTANCE;
} else {
// an image without a color space is always broken
throw new IOException("could not determine color space");
}
}
//
https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java#L667
private static int getBitsPerComponent(COSStream stream) {
return isStencil(stream) ? 1 : stream.getInt(COSName.BITS_PER_COMPONENT,
COSName.BPC);
}
//
https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/image/PDImageXObject.java#L810
private static boolean isStencil(COSStream stream) {
return stream.getBoolean(COSName.IMAGE_MASK, false);
}
{{{code}}}
isHugeImage method returns false because it calculate the size of image with
numOfBitsPerColorComponent which is 1.
so my code decodes the jbig2 image and gets out of memory exception because
jbig2-imageio creates BufferedImage with numOfBitsPerColorComponent which is 8..
I don't scale image in my code so my code will work well with approach_1.patch
/ approach_2.path,
but above patches can still generate the same issue in the future when someone
try to read scaled jbig2 image, I think..
So I still have a question. I don't know much about this area but..
Losing information because of scaling is really unusal? Should information not
lost after scaling down?
https://en.wikipedia.org/wiki/Image_resolution#/media/File:Resolution_illustration.png
Or why don't we use box scaling?
You can test with [^approach_3.patch] and [^amb_2.jb2].
please run JBIG2ImageReaderDemo to test.
> oversized jbig2 decoded result that causing unnecessary operation
> -----------------------------------------------------------------
>
> Key: PDFBOX-4598
> URL: https://issues.apache.org/jira/browse/PDFBOX-4598
> Project: PDFBox
> Issue Type: Bug
> Components: JBIG2
> Affects Versions: 3.0.2 JBIG2
> Reporter: Hee Jeong Kim
> Priority: Minor
> Attachments: amb_2.jb2, approach_1.patch, approach_2.patch,
> approach_3.patch, sample.pdf, use_packed_raster_to_read_Jbig2_image.patch
>
>
> Hi! I am using pdfbox 2.0.16 and jbig2-imageio 3.0.2 to read JBIG2 images,
> and found some issue to report.
> It seems like jbig2-imageio creates oversized BufferedImage, and this also
> makes pdfbox to do unnecessary operations.
> To read Jbig2 image, pdfbox with jbig2-imageio do followings:
> 1. find JBIG2 ImageReader
> (https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java#L67)
> 2. read Image and get BufferedImage as a result
> (https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java#L106)
> 2-1. JBIG2 ImageIO 3.0.2 get decoded bitmap
> (https://github.com/apache/pdfbox-jbig2/blob/3.0.2/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReader.java#L249)
> 2-2. return the given bitmap as buffered image
> (https://github.com/apache/pdfbox-jbig2/blob/3.0.2/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReader.java#L259)
> The problem is
> At step 2-1, roughly 59MB Bitmap is created for given Jbig2 image on the
> second page of sample.pdf (which is correct),
> but oversize(473MB, roughly) BufferedImage is returned at the step 2-2.
> I think this is because jbig2-imageio uses a raster based on a
> PixelInterleavedSampleModel and IndexColorModel with 8 bits.
> https://github.com/apache/pdfbox-jbig2/blob/3.0.2/src/main/java/org/apache/pdfbox/jbig2/image/Bitmaps.java#L177
> https://github.com/apache/pdfbox-jbig2/blob/3.0.2/src/main/java/org/apache/pdfbox/jbig2/image/Bitmaps.java#L286
> https://github.com/apache/pdfbox-jbig2/blob/3.0.2/src/main/java/org/apache/pdfbox/jbig2/image/Bitmaps.java#L291
> This also makes pdfbox to check a pixel size of the color model of result
> buffered image,
> https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java#L116
> and to create another BufferedImage with binary type since it is not 1.
> (jbig2 is 1-bit depth)
> https://github.com/apache/pdfbox/blob/2.0.16/pdfbox/src/main/java/org/apache/pdfbox/filter/JBIG2Filter.java#L122
> I think we should call createPackedRaster and use the returned raster which
> is based on MultiPixelPackedSampleModel, and use IndexColorModel with 1 bits
> since jbig2 is for bi-level image. Please check the attached patch. I tested
> with the patch, and it seems like this patch works well.
> You can reproduce this issue with the second of the sample.pdf file that I
> attached.
> You can also download the file from here:
> http://www.newsgn.com/data/newsgn_com/pdf/201802/2018022229524590.pdf
--
This message was sent by Atlassian JIRA
(v7.6.14#76016)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]