OpenPDF icon indicating copy to clipboard operation
OpenPDF copied to clipboard

Signature form field flattening distortion issue

Open Lonzak opened this issue 1 year ago • 6 comments

After fixing [#992] and [#1047] I have another case of distorted images after flattening.

This PDF is in landscape mode and contains fields with 90° rotation etc - the full program ... When it is signed and then flattened the signatures are distorted:

grafik

On the first glance I didn't spot the error - I'll have to investigate deeper. But maybe someone already fixed this or knows where the problem is? @mkl-public :-D

Lonzak avatar Oct 23 '24 16:10 Lonzak

You remember https://github.com/LibrePDF/OpenPDF/pull/992#discussion_r1416396424 ? I wouldn't be surprised if the decision back then to stick with /R for now comes back to haunt us now... ;)

Seriously, though, I'll take a look at the example file sometime the next days.

mkl-public avatar Oct 24 '24 16:10 mkl-public

@mkl-public But the field does contain /R so normally it should be ok... (except they additionally fiddled with the matrix)

Lonzak avatar Nov 14 '24 15:11 Lonzak

Page 1 (842.0x595.22) is rotated by 90°. The signature fields are rotated as well, e.g. ll(x,y)=208.025; 55.179993 ur(x,y)=332.335 ; 70.77997 , rotation=90. The image looks distorted so the coordinates seem to be handled incorrectly...

Lonzak avatar Dec 03 '24 12:12 Lonzak

@mkl-public Did you find the time to take a look at the file? I can't spot the error...

Lonzak avatar Apr 01 '25 06:04 Lonzak

I just took a look.

As already assumed before, it's indeed the decision linked above (https://github.com/LibrePDF/OpenPDF/pull/992#discussion_r1416396424) that in this case causes the problem.

The code currently decides based on the /MK /R value whether or not the appearance stream needs to be rotated when flattened.

This works alright if the PDF processor that created the annotation appearance added rotation to it using a rotation /Matrix: Because that matrix is ignored by the flattening code, its rotation effect gets lost and must explicitly be provided by the flattening matrix.

In the case at hand, though, the annotation appearance is not rotated by the /Matrix but by an explicit cm instruction in the appearance stream. So this rotation effect does not get lost here and, therefore, must not be provided by the flattening matrix.

By rotating with the flattening matrix here the code actually rotates the appearance a second time and, therefore, 90° too far.

Essentially, to fix the flattening code correctly the code needs to implement the algorithm in 12.5.5 instead of the current guessing with /MK /R.

mkl-public avatar Apr 01 '25 16:04 mkl-public

Thank you!

You mean this:

Algorithm: appearance streams

  1. The appearance’s bounding box (specified by its BBox entry) shall be transformed, using Matrix, to produce a quadrilateral with arbitrary orientation. The transformed appearance box is the smallest upright rectangle that encompasses this quadrilateral.

  2. A matrix A shall be computed that scales and translates the transformed appearance box to align with the edges of the annotation’s rectangle (specified by the Rect entry). A maps the lower-left corner (the corner with the smallest x and y coordinates) and the upper-right corner (the corner with the greatest x and y coordinates) of the transformed appearance box to the corresponding corners of the annotation’s rectangle.

  3. Matrix shall be concatenated with A to form a matrix AA that maps from the appearance’s coordinate system to the annotation’s rectangle in default user space:𝐴𝐴 = 𝑀𝑎𝑡𝑟𝑖𝑥 × 𝐴

The annotation may be further scaled and rotated if either the NoZoom or NoRotate flag is set (see 12.5.3, "Annotation flags"). Any transformation applied to the annotation as a whole shall be applied to the appearance within it.

Lonzak avatar Apr 24 '25 10:04 Lonzak