0

the title says it all, I am able to visually sign a pdf using pdfbox version 2.0.8. Currently I have to hard-code the starting coordination of image in code. but as PDFs varies position of image always needs to be changed accordingly. I want to apply signature image at the end of pdf in left corner. how do I get that position in code? here is my code, hard coding coordinates using _x & _y. In code 'signing' is visible signature object and 'page' is the last page of pdf, 'args[2]' is pdf-file to be signed:

int _x = 30;
int _y = 420;
signing.setVisibleSignDesigner(args[2], _x, _y, -50, imageStream, page);
imageStream.close();
signing.setExternalSigning(externalSig);
signing.signPDF(documentFile, signedDocumentFile, tsaClient);
removeFile(imageResult);

Example of Signature I want:

Example of Signature I want

Edit: added Image to clarify that I want signature field to be at the end of document, not at the end of last page. document may be completed at the top of the last page so field should also be right after the text not at the end of the page. sorry I wasn't clear with my question earlier.

mkl
  • 90,588
  • 15
  • 125
  • 265
Hemant
  • 13
  • 5
  • The bottom left is (0,0), did you try that? The current PDFBox version is 2.0.17. – Tilman Hausherr Oct 17 '19 at 09:23
  • @TilmanHausherr *The bottom left is (0,0)* - for the target page coordinates that is not necessarily the case. Or does `VisibleSignature` and the `VisibleSignDesigner` normalize that away? – mkl Oct 17 '19 at 11:26
  • @mkl if you mean rotation, there is a method `PDVisibleSignDesigner.adjustForRotation()` which was inspired by an answer by you. – Tilman Hausherr Oct 17 '19 at 11:44
  • @TilmanHausherr *"if you mean rotation"* - No, I was thinking of document pages with crop boxes which do not have the origin in their lower left corner. – mkl Oct 17 '19 at 13:53
  • Oh, I didn't think about that one. Shouldn't be a problem for non rotated pages, don't know about rotated ones. – Tilman Hausherr Oct 18 '19 at 07:33
  • hey @TilmanHausherr, in my settings (_x=0,_y=0) indicates upper left corner. plus last page of pdf may not be filled completely. i want signature field to be at right after my document finishes not at the end of page in left corner. Let me know if I am not clear enough. – Hemant Oct 18 '19 at 10:16
  • *"i want signature field to be at right after my document finishes not at the end of page in left corner."* - What do you mean exactly by "after my document finishes"? Is determining the bounding box of the contents of that last page and positioning the signature thereunder ok? Or are you hoping for a solution which ignores footers, watermarks, and other artifacts? What about other annotations? What if there is not free space thereunder? – mkl Oct 18 '19 at 17:49
  • *"in my settings (_x=0,_y=0) indicates upper left corner"* - in that case you shouldn't use those values as direct inputs to PDFBox method (except during text extraction... ). PDFBox mostly uses the natural coordinate system of the PDF page in question in its API, so you will have to transform your coordinates first. – mkl Oct 18 '19 at 17:52
  • @mkl it is given that there are no footers and watermarks in the document and there will always be enough space below the document for signature field to be at. Please check the image I have attached in the post for clarification. – Hemant Oct 19 '19 at 09:04
  • 1
    So you essentially look for the bounding box of existing contents of that page. You can see how to determine that bounding box in [this answer](https://stackoverflow.com/a/52969119/1729265). Simply determine the bounding box as explained there and position the signature right underneath. – mkl Oct 28 '19 at 16:56
  • hey @mkl, I have followed the bounding box method, but it does not come out be effective for me. coordinates I've gotten using this method leads to sign. stamp over my pdf, and in some cases way below than where pdf ends. hence, it is not consistent for me. is there any alternative I can make use of? Thanks in advance. – Hemant Oct 31 '19 at 11:21

1 Answers1

1

According to the clarifications in comments to the question, you try to position the signature right underneath the bounding box of existing contents of the last document page.

To determine that bounding box you can use the BoundingBoxFinder presented in this answer.

But as you found out in response to a comment to that effect, you cannot simply use its result as input for CreateVisibleSignature.setVisibleSignDesigner as different coordinate systems are assumed:

  • The BoundingBoxFinder uses the PDF default user space coordinates of the page in question: They are given by the MediaBox of the page in question and have their y coordinates increase upwards. Usually the origin is in the lower left corner of the page.
  • CreateVisibleSignature on the other hand uses a coordinate system with the same unit length but having the origin in the upper left corner of the page and the y coordinates increasing downwards.

Thus, the coordinates have to be transformed, e.g. like this:

File documentFile = new File(SOURCE);
File signedDocumentFile = new File(RESULT);

Rectangle2D boundingBox;
PDRectangle mediaBox;
try (   PDDocument document = PDDocument.load(documentFile) ) {
    PDPage pdPage = document.getPage(0);
    BoundingBoxFinder boundingBoxFinder = new BoundingBoxFinder(pdPage);
    boundingBoxFinder.processPage(pdPage);
    boundingBox = boundingBoxFinder.getBoundingBox();
    mediaBox = pdPage.getMediaBox();
}

CreateVisibleSignature signing = new CreateVisibleSignature(ks, PASSWORD.clone());
try (   InputStream imageStream = IMAGE_STREAM) {
    signing.setVisibleSignDesigner(documentFile.getPath(), (int)boundingBox.getX(), (int)(mediaBox.getUpperRightY() - boundingBox.getY()), -50, imageStream, 1);
}
signing.setVisibleSignatureProperties("name", "location", "Security", 0, 1, true);
signing.setExternalSigning(false);
signing.signPDF(documentFile, signedDocumentFile, null);

(CreateSignature test signLikeHemantPdfTest)

Remarks

I found a document looking like your Yukon Education PDF Test File here. Applying the code above to that file, one observes that there is a small gap between the last visible line of text and the image. This gap is caused by some space characters in a line below the "Please visit our website" line. The BoundingBoxFinder does not check whether a drawing instruction eventually results in something visible, it always adds the area in question to the bounding box.

In general you may want to subtract a small bit from the y coordinate calculated by the code above to create a visual gap between former page content and the new signature widget.

Looking into the sources of the CreateVisibleSignature one sees that there actually the y coordinates are transformed by subtracting them from the height of the MediaBox, not from its upper border value. Eventually these coordinates are copied into the target document. Thus, it may be necessary to use mediaBox.getHeight() instead of mediaBox.getUpperRightY() in the code above.

Looking into the sources of the CreateVisibleSignature2 one sees that there actually the CropBox is used instead of the MediaBox. If your code derives from that example, you may have to replace pdPage.getMediaBox() by pdPage.getCropBox() in the code above.

In general this arbitrary use of different coordinate systems is one of the fairly few sources of irritation when working with PDFBox.

Community
  • 1
  • 1
mkl
  • 90,588
  • 15
  • 125
  • 265
  • as I have said I am only dealing with simple PDFs without any complicated contents. This solution works fine for me. Thanks :) – Hemant Nov 04 '19 at 06:28