Reputation: 6245
I am using pdfbox-1.8.8 to do the signing function on PDF file.
It works well with PDF file in portrait mode. But with landscape file, I have an issue
It looks like the coordinate is wrong for the landscape file.
Does anyone know what is wrong with the file ?
Here is the link of pdf file
Here is the code I used to sign
public void signDetached(String inputFilePath, String outputFilePath, String signatureImagePath, Sign signProperties) {
OutputStream outputStream = null;
InputStream inputStream = null;
PDDocument document = null;
InputStream signImageStream = null;
try {
setTsaClient(null);
document = PDDocument.load(inputFilePath);
// create signature dictionary
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("VANDUC1102");
signature.setLocation(null);
String displayName = "Hello World, Document signed by VANDUC1102";
String reason = reasonText+ " " + displayName;
signature.setReason(reason);
// the signing date, needed for valid signature
signature.setSignDate(Calendar.getInstance());
int signatureInPage = signProperties.getPageNumber() + 1;
signImageStream = new FileInputStream(new File(signatureImagePath));
PDVisibleSignDesigner visibleSig = new PDVisibleSignDesigner(inputFilePath, signImageStream, signatureInPage);
float xAxis = convertPixel2Point(signProperties.getX()) ;
float yAxis = convertPixel2Point(signProperties.getY());
float signImageHeight = convertPixel2Point(signImageHeight);
float signImageWidth = convertPixel2Point(signImageWidth);
visibleSig.xAxis(xAxis)
.yAxis(yAxis)
.zoom(0)
.signatureFieldName("Signature")
.height(signImageHeight)
.width(signImageWidth);
PDVisibleSigProperties signatureProperties = new PDVisibleSigProperties();
signatureProperties.signerName(eiUser.getName())
.signerLocation(null)
.signatureReason(reason)
.preferredSize(0)
.page(signProperties.getPageNumber())
.visualSignEnabled(true)
.setPdVisibleSignature(visibleSig)
.buildSignature();
// register signature dictionary and sign interface
SignatureOptions signatureOptions = new SignatureOptions();
signatureOptions.setVisualSignature(signatureProperties);
signatureOptions.setPage(signatureInPage);
document.addSignature(signature, this, signatureOptions);
File outputFile = new File(outputFilePath);
outputStream = new FileOutputStream(outputFile);
inputStream = new FileInputStream(inputFilePath);
IOUtils.copyStream(inputStream, outputStream);
document.saveIncremental(inputStream, outputStream);
outputStream.flush();
} catch (COSVisitorException | SignatureException | IOException ex) {
log.error("signDetached ", ex);
} finally {
IOUtils.closeStream(outputStream);
IOUtils.closeStream(inputStream);
IOUtils.closeStream(signImageStream);
IOUtils.closeStream(document);
}
}
private float convertPixel2Point(float pixel){
return pixel * (float) 72/96;
}
As I said this code work well with portrait PDF
Thanks.
Upvotes: 2
Views: 1952
Reputation: 18851
Starting with version 2.0.5, adjusting the signature field for rotated pages will be possible with the adjustForRotation()
call. In the CreateVisibleSignature.java example, this line
visibleSignDesigner.xAxis(x).yAxis(y).zoom(zoomPercent);
has to be changed to this:
visibleSignDesigner.xAxis(x).yAxis(y).zoom(zoomPercent).adjustForRotation();
The change (issue PDFBOX-3671) is partially based on the answer by @mkl. It will not be available for 1.8.*.
Update 24.10.2018:
All 2.0.* versions up to 2.0.12 had the problem that adjustForRotation()
was hard-coded for 200 x 100 image size. This has been fixed in 2.0.13. Alternatively derive your own PDVisibleSignDesigner
and extend adjustForRotation()
with the correct implementation:
public PDVisibleSignDesigner adjustForRotation()
{
switch (rotation)
{
case 90:
float temp = yAxis;
yAxis = pageHeight - xAxis - imageWidth;
xAxis = temp;
affineTransform = new AffineTransform(
0, imageHeight / imageWidth, -imageWidth / imageHeight, 0, imageWidth, 0);
temp = imageHeight;
imageHeight = imageWidth;
imageWidth = temp;
break;
case 180:
float newX = pageWidth - xAxis - imageWidth;
float newY = pageHeight - yAxis - imageHeight;
xAxis = newX;
yAxis = newY;
affineTransform = new AffineTransform(-1, 0, 0, -1, imageWidth, imageHeight);
break;
case 270:
temp = xAxis;
xAxis = pageWidth - yAxis - imageHeight;
yAxis = temp;
affineTransform = new AffineTransform(
0, -imageHeight / imageWidth, imageWidth / imageHeight, 0, 0, imageHeight);
temp = imageHeight;
imageHeight = imageWidth;
imageWidth = temp;
break;
case 0:
default:
break;
}
return this;
}
Upvotes: 4
Reputation: 95898
The page in question has a non-zero Rotate value. The PDFBox visual signing classes completely ignore this value, so one has to give it the coordinates and dimensions as if the page was not rotated.
This can be done by adding the following switch
statement:
float xAxis = convertPixel2Point(/*signProperties.getX()*/x) ;
float yAxis = convertPixel2Point(/*signProperties.getY()*/y);
float signImageHeight = convertPixel2Point(/*signImageHeight*/324);
float signImageWidth = convertPixel2Point(/*signImageWidth*/309);
int rotation = getPageRotation(inputFilePath, page) % 360;
switch (rotation)
{
case 0:
// all ok;
break;
case 90:
visibleSig.affineTransformParams(new byte[] {0, 1, -2, 0, 100, 0})
.formaterRectangleParams(new byte[]{0, 0, 100, 100});
float temp = yAxis;
yAxis = visibleSig.getPageHeight() - xAxis - signImageWidth;
xAxis = temp;
temp = signImageHeight;
signImageHeight = signImageWidth;
signImageWidth = temp;
break;
case 180:
// Implement in a similar fashion
case 270:
// Implement in a similar fashion
}
visibleSig.xAxis(xAxis)
.yAxis(yAxis)
.zoom(0)
.signatureFieldName("Signature")
.height(signImageHeight)
.width(signImageWidth);
and the following method:
private int getPageRotation(String documentPath, int page) throws IOException
{
try (PDDocument document = PDDocument.load(documentPath))
{
List<?> pages = document.getDocumentCatalog().getAllPages();
PDPage pageObject =(PDPage) pages.get(page);
return pageObject.getRotation();
}
}
For Rotate values of 180 and 270, analogous corrections have to be made.
(Test methods testLandscapeOriginal
and testLandscapeFixed
in SignLikeVanduc1102)
Upvotes: 4