Reputation: 19
I want render a PDF as image and draw the borders of all included images on it. For this I need the correct dimensions for the images on a page.
this is working with the following code:
public class PrintImageLocations extends PDFStreamEngine
{
@Override
protected void processOperator( Operator operator, List<COSBase> operands) throws IOException
{
String operation = operator.getName();
if( "Do".equals(operation) )
{
COSName objectName = (COSName) operands.get( 0 );
PDXObject xobject = getResources().getXObject( objectName );
if( xobject instanceof PDImageXObject)
{
PDImageXObject image = (PDImageXObject)xobject;
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
System.out.println("Found image " + objectName.getName());
Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
float imageXScale = ctmNew.getScalingFactorX();
float imageYScale = ctmNew.getScalingFactorY();
// position in user space units. 1 unit = 1/72 inch at 72 dpi
System.out.println("position in PDF = " + ctmNew.getTranslateX() + ", " + ctmNew.getTranslateY() + " in user space units");
}
else if(xobject instanceof PDFormXObject)
{
PDFormXObject form = (PDFormXObject)xobject;
showForm(form);
}
}
else
{
super.processOperator( operator, operands);
}
}
}
Source: PrintImageLocations.java
Output Example: position in PDF = 535.68, 97.79052 in user space units
Unfortunatly I have a problem when the page is rotated. There are lot of pdfs which return 90 on "getCurrentPage().getRotation()". For 90 degree I have to switch getTranslateX and getTranslateY values to get the correct position, but this only works specially for 90 degree. Is there any cool Matrix trasnformation which I can use for rotating the position?
I think in this code, the author tried to solve this rotation problem, but 1st) I don't understand what the transformations are doing and 2nd) it doesn't work correctly because after rotation one value in in negative.
Upvotes: 1
Views: 942
Reputation: 19
OK... I thought I can gt it work with some math... unfortunatly it didn't work (I think the problem was sitting before the computer)
protected void processOperator(Operator operator, List<COSBase> operands) throws IOException {
String operation = operator.getName();
if ("Do".equals(operation)) {
COSName objectName = (COSName) operands.get(0);
PDXObject xobject = getResources().getXObject(objectName);
if (xobject instanceof PDImageXObject) {
PDImageXObject image = (PDImageXObject) xobject;
Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
float imageXScale = ctmNew.getScalingFactorX();
float imageYScale = ctmNew.getScalingFactorY();
int rotationDegree = getCurrentPage().getRotation();
float pageHeight = this.getCurrentPage().getBBox().getHeight();
float pageWidth = this.getCurrentPage().getBBox().getWidth();
float translateX;
float translateY;
if (rotationDegree == 0) {
translateX = ctmNew.getTranslateX();
translateY = pageHeight - ctmNew.getTranslateY() - imageYScale;
} else if (rotationDegree == 90) {
translateX = ctmNew.getTranslateY();
translateY = ctmNew.getTranslateX() - imageYScale;
} else if (rotationDegree == 270) {
translateX = pageHeight - ctmNew.getTranslateY();
translateY = pageWidth - ctmNew.getTranslateX() - imageYScale;
} else if (rotationDegree == 180) {
translateX=pageWidth - ctmNew.getTranslateX() -imageXScale ;
translateY=pageHeight - ctmNew.getTranslateY() - imageYScale;
logger.log(Level.INFO, "image rotation 180 degree. not fully tested yet");
}
else {
throw new RuntimeException("");
}
PdfImage pdfImage = new PdfImage(objectName.getName(), translateX, translateY, imageXScale, imageYScale, image.getImage());
pdfImages.add(pdfImage);
} else if (xobject instanceof PDFormXObject) {
PDFormXObject form = (PDFormXObject) xobject;
showForm(form);
}
} else {
super.processOperator(operator, operands);
}
}
Upvotes: 0
Reputation: 2188
You can perform a rotation in Euclidean space using the following rotation matrices.
Counter-clockwise:
R = ⎡ cosθ -sinθ ⎤
⎣ sinθ cosθ ⎦
Clockwise:
R = ⎡ cosθ sinθ ⎤
⎣ -sinθ cosθ ⎦
Each matrix will rotate points in the 2-dimensional Cartesian plane through an angle θ about the origin. This technique assumes that each point is represented a column vector v
. The new value of each point is calculated by R * v
where *
represents matrix multiplication.
This technique will produce negative values (relative to the initial values, anyway) for at least some points on at least one of the two dimensions. In order to correct this relative to the Cartesian origin, translate the rotated image "up" by min(y) - min(y')
and "right" by min(x) - min(x')
, where min(d)
represents the minimum value along that dimension of any point.
So that you don't have to do all the boilerplate on this yourself, you should take a look at the AffineTransform
class.
Upvotes: 0