[
https://issues.apache.org/jira/browse/PDFBOX-3678?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15857701#comment-15857701
]
Roman edited comment on PDFBOX-3678 at 2/8/17 9:11 AM:
-------------------------------------------------------
[~tilman], we are migrating code from 1.8 to 2.0, which is used to edit image.
The code finds all images which intersect given rectangular area, and fills all
such intersections with black color.
The code for 1.8, it is used to populate "transformsMap" with "AffineTransform"
for every image:
{code}
public class ImageTransformsCalculator extends PDFStreamEngine {
// <...>
/**
* This is used to handle an operation.
*
* @param operator The operation to perform.
* @param arguments The list of arguments.
*
* @throws IOException If there is an error processing the operation.
*/
protected void processOperator( PDFOperator operator, List<COSBase>
arguments ) throws IOException {
String operation = operator.getOperation();
if (INVOKE_OPERATOR.equals(operation)) {
COSName objectName = (COSName) arguments.get(0);
Map<String, PDXObject> xobjects = getResources().getXObjects();
PDXObject xobject = xobjects.get(objectName.getName());
if (xobject instanceof PDXObjectImage) {
PDXObjectImage img = (PDXObjectImage) xobject;
AffineTransform imageTransform = calcTransform(img);
transformsMap.put(img.getCOSObject(), imageTransform);
}
else if (xobject instanceof PDXObjectForm) {
// save the graphics state
getGraphicsStack().push((PDGraphicsState)
getGraphicsState().clone());
PDPage page = getCurrentPage();
PDXObjectForm form = (PDXObjectForm) xobject;
COSStream invoke = (COSStream) form.getCOSObject();
PDResources pdResources = form.getResources();
if (pdResources == null) {
pdResources = page.findResources();
}
// if there is an optional form matrix, we have to
// map the form space to the user space
Matrix matrix = form.getMatrix();
if (matrix != null) {
Matrix xobjectCTM =
matrix.multiply(getGraphicsState().getCurrentTransformationMatrix());
getGraphicsState().setCurrentTransformationMatrix(xobjectCTM);
}
processSubStream(page, pdResources, invoke);
// restore the graphics state
setGraphicsState( getGraphicsStack().pop());
}
}
else {
super.processOperator(operator, arguments);
}
}
private AffineTransform calcTransform(PDXObjectImage image) {
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
AffineTransform imageTransform = ctmNew.createAffineTransform();
imageTransform.scale(1.0 / imageWidth, -1.0 / imageHeight);
imageTransform.translate(0, -imageHeight);
imageTransform.translate(0, -1 *
getCurrentPage().findCropBox().getHeight() / imageTransform.getScaleY());
imageTransform.scale(1.0, -1.0);
imageTransform.translate(0, -2 * imageTransform.getTranslateY() /
imageTransform.getScaleY()); // PCC-8330
try {
return imageTransform.createInverse();
} catch (NoninvertibleTransformException e) {
return null;
}
}
// <...>
}
{code}
Then, "AffineTransform" objects are checked for intersection as the following:
{code}
for (AffineTransform at : transforms) {
for (Rectangle2D.Double rect : rects) {
Shape result = at.createTransformedShape(rect);
if (!result.intersects(0, 0, img.getWidth(), img.getHeight()))
// this current rect does not cover any part of this img
continue;
//else fills image area with black
// ...
}
}
{code}
On 2.0, the complicated thing is that
*getGraphicsState().getCurrentTransformationMatrix();* started to return
different value. However, our current code for 2.0 is different (we are trying
to setup it to work like it was on 1.8 but it still not 100% correct):
{code}
protected void processOperator(Operator operator, List<COSBase> arguments)
throws IOException {
String operation = operator.getName();
if (INVOKE_OPERATOR.equals(operation)) {
COSName objectName = (COSName) arguments.get(0);
PDXObject xobject = getResources().getXObject(objectName);
if (xobject instanceof PDImageXObject) {
PDImageXObject img = (PDImageXObject) xobject;
AffineTransform imageTransform = calcTransform(img);
transformsMap.put(img.getCOSObject(), imageTransform);
}
else if (xobject instanceof PDFormXObject) {
PDFormXObject form = (PDFormXObject) xobject;
showForm(form);
}
}
else {
super.processOperator(operator, arguments);
}
}
private AffineTransform calcTransform(PDImageXObject image) {
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
AffineTransform imageTransform = ctmNew.createAffineTransform();
imageTransform.scale(getCurrentPage().getCropBox().getWidth(),
getCurrentPage().getCropBox().getHeight());
imageTransform.scale(1.0 / imageWidth, -1.0 / imageHeight);
imageTransform.translate(0, -imageHeight);
imageTransform.translate(0, -1 *
getCurrentPage().getCropBox().getHeight() / imageTransform.getScaleY());
imageTransform.scale(1.0, -1.0);
imageTransform.translate(0, -2 * imageTransform.getTranslateY() /
imageTransform.getScaleY()); // PCC-8330
try {
return imageTransform.createInverse();
} catch (NoninvertibleTransformException e) {
return null;
}
}
{code}
Sorry for mixing different issues, however these code snippets hopingly gives
idea of what we are trying to do.
was (Author: rmakarov):
[~tilman], we are migrating code from 1.8 to 2.0, which is used to edit image.
The code finds all images which intersect given rectangular area, and fills all
such intersections with black color.
The code for 1.8, it is used to populate "transformsMap" with "AffineTransform"
for every image:
{code}
/**
* This is used to handle an operation.
*
* @param operator The operation to perform.
* @param arguments The list of arguments.
*
* @throws IOException If there is an error processing the operation.
*/
protected void processOperator( PDFOperator operator, List<COSBase>
arguments ) throws IOException {
String operation = operator.getOperation();
if (INVOKE_OPERATOR.equals(operation)) {
COSName objectName = (COSName) arguments.get(0);
Map<String, PDXObject> xobjects = getResources().getXObjects();
PDXObject xobject = xobjects.get(objectName.getName());
if (xobject instanceof PDXObjectImage) {
PDXObjectImage img = (PDXObjectImage) xobject;
AffineTransform imageTransform = calcTransform(img);
transformsMap.put(img.getCOSObject(), imageTransform);
}
else if (xobject instanceof PDXObjectForm) {
// save the graphics state
getGraphicsStack().push((PDGraphicsState)
getGraphicsState().clone());
PDPage page = getCurrentPage();
PDXObjectForm form = (PDXObjectForm) xobject;
COSStream invoke = (COSStream) form.getCOSObject();
PDResources pdResources = form.getResources();
if (pdResources == null) {
pdResources = page.findResources();
}
// if there is an optional form matrix, we have to
// map the form space to the user space
Matrix matrix = form.getMatrix();
if (matrix != null) {
Matrix xobjectCTM =
matrix.multiply(getGraphicsState().getCurrentTransformationMatrix());
getGraphicsState().setCurrentTransformationMatrix(xobjectCTM);
}
processSubStream(page, pdResources, invoke);
// restore the graphics state
setGraphicsState( getGraphicsStack().pop());
}
}
else {
super.processOperator(operator, arguments);
}
}
private AffineTransform calcTransform(PDXObjectImage image) {
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
AffineTransform imageTransform = ctmNew.createAffineTransform();
imageTransform.scale(1.0 / imageWidth, -1.0 / imageHeight);
imageTransform.translate(0, -imageHeight);
imageTransform.translate(0, -1 *
getCurrentPage().findCropBox().getHeight() / imageTransform.getScaleY());
imageTransform.scale(1.0, -1.0);
imageTransform.translate(0, -2 * imageTransform.getTranslateY() /
imageTransform.getScaleY()); // PCC-8330
try {
return imageTransform.createInverse();
} catch (NoninvertibleTransformException e) {
return null;
}
}
{code}
Then, "AffineTransform" objects are checked for intersection as the following:
{code}
for (AffineTransform at : transforms) {
for (Rectangle2D.Double rect : rects) {
Shape result = at.createTransformedShape(rect);
if (!result.intersects(0, 0, img.getWidth(), img.getHeight()))
// this current rect does not cover any part of this img
continue;
//else fills image area with black
// ...
}
}
{code}
On 2.0, the complicated thing is that
*getGraphicsState().getCurrentTransformationMatrix();* started to return
different value. However, our current code for 2.0 is different (we are trying
to setup it to work like it was on 1.8 but it still not 100% correct):
{code}
protected void processOperator(Operator operator, List<COSBase> arguments)
throws IOException {
String operation = operator.getName();
if (INVOKE_OPERATOR.equals(operation)) {
COSName objectName = (COSName) arguments.get(0);
PDXObject xobject = getResources().getXObject(objectName);
if (xobject instanceof PDImageXObject) {
PDImageXObject img = (PDImageXObject) xobject;
AffineTransform imageTransform = calcTransform(img);
transformsMap.put(img.getCOSObject(), imageTransform);
}
else if (xobject instanceof PDFormXObject) {
PDFormXObject form = (PDFormXObject) xobject;
showForm(form);
}
}
else {
super.processOperator(operator, arguments);
}
}
private AffineTransform calcTransform(PDImageXObject image) {
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
AffineTransform imageTransform = ctmNew.createAffineTransform();
imageTransform.scale(getCurrentPage().getCropBox().getWidth(),
getCurrentPage().getCropBox().getHeight());
imageTransform.scale(1.0 / imageWidth, -1.0 / imageHeight);
imageTransform.translate(0, -imageHeight);
imageTransform.translate(0, -1 *
getCurrentPage().getCropBox().getHeight() / imageTransform.getScaleY());
imageTransform.scale(1.0, -1.0);
imageTransform.translate(0, -2 * imageTransform.getTranslateY() /
imageTransform.getScaleY()); // PCC-8330
try {
return imageTransform.createInverse();
} catch (NoninvertibleTransformException e) {
return null;
}
}
{code}
Sorry for mixing different issues, however these code snippets hopingly gives
idea of what we are trying to do.
> JBIG2 decoding error in 2.0
> ---------------------------
>
> Key: PDFBOX-3678
> URL: https://issues.apache.org/jira/browse/PDFBOX-3678
> Project: PDFBox
> Issue Type: Bug
> Reporter: Roman
> Attachments: BTB0010010004.1-Bit_Jbig2.pdf
>
>
> After migration from PdfBox 1.8 to 2.0, we started to get the following
> error, when processing attached PDF (on 1.8 it was working fine):
> {code}
> java.io.IOException: Could not read JBIG2 image
> at org.apache.pdfbox.filter.JBIG2Filter.decode(JBIG2Filter.java:91)
> ~[pdfbox-2.0.3.jar:2.0.3]
> at org.apache.pdfbox.cos.COSInputStream.create(COSInputStream.java:69)
> ~[pdfbox-2.0.3.jar:2.0.3]
> at
> org.apache.pdfbox.cos.COSStream.createInputStream(COSStream.java:162)
> ~[pdfbox-2.0.3.jar:2.0.3]
> at
> org.apache.pdfbox.pdmodel.common.PDStream.createInputStream(PDStream.java:235)
> ~[pdfbox-2.0.3.jar:2.0.3]
> at
> org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.<init>(PDImageXObject.java:147)
> ~[pdfbox-2.0.3.jar:2.0.3]
> at
> org.apache.pdfbox.pdmodel.graphics.PDXObject.createXObject(PDXObject.java:70)
> ~[pdfbox-2.0.3.jar:2.0.3]
> at
> org.apache.pdfbox.pdmodel.PDResources.getXObject(PDResources.java:409)
> ~[pdfbox-2.0.3.jar:2.0.3]
> at
> com.accusoft.pdfps.redaction.utils.pdfbox.ImageTransformsCalculator.processOperator(ImageTransformsCalculator.java:78)
> ~[classes/:?]
> at
> org.apache.pdfbox.contentstream.PDFStreamEngine.processStreamOperators(PDFStreamEngine.java:472)
> ~[pdfbox-2.0.3.jar:2.0.3]
> at
> org.apache.pdfbox.contentstream.PDFStreamEngine.processStream(PDFStreamEngine.java:446)
> ~[pdfbox-2.0.3.jar:2.0.3]
> at
> org.apache.pdfbox.contentstream.PDFStreamEngine.processPage(PDFStreamEngine.java:149)
> ~[pdfbox-2.0.3.jar:2.0.3]
> Caused by: java.io.EOFException
> at
> javax.imageio.stream.ImageInputStreamImpl.readBit(ImageInputStreamImpl.java:652)
> ~[?:1.8.0_101]
> at com.levigo.jbig2.SegmentHeader.e(gn:75)
> ~[pdfone-5.3.17.507.jar:5.3.17.507]
> at com.levigo.jbig2.SegmentHeader.D(gn:208)
> ~[pdfone-5.3.17.507.jar:5.3.17.507]
> at com.levigo.jbig2.SegmentHeader.<init>(gn:67)
> ~[pdfone-5.3.17.507.jar:5.3.17.507]
> at com.levigo.jbig2.e.k(hm:148) ~[pdfone-5.3.17.507.jar:5.3.17.507]
> at com.levigo.jbig2.e.<init>(hm:204) ~[pdfone-5.3.17.507.jar:5.3.17.507]
> at com.levigo.jbig2.JBIG2ImageReader.D(uf:275)
> ~[pdfone-5.3.17.507.jar:5.3.17.507]
> at com.levigo.jbig2.JBIG2ImageReader.D(uf:233)
> ~[pdfone-5.3.17.507.jar:5.3.17.507]
> at com.levigo.jbig2.JBIG2ImageReader.read(uf:29)
> ~[pdfone-5.3.17.507.jar:5.3.17.507]
> at org.apache.pdfbox.filter.JBIG2Filter.decode(JBIG2Filter.java:86)
> ~[pdfbox-2.0.3.jar:2.0.3]
> {code}
--
This message was sent by Atlassian JIRA
(v6.3.15#6346)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]