iText 7.1.0 flattening signature field with appearance stretched - itext

I have a PDF (https://github.com/giacgbj/stackOverflow/blob/master/xxx.pdf), somehow digitally signed by a third party, whose signature has an appearance
When I flatten the PDF (https://github.com/giacgbj/stackOverflow/blob/master/xxxFlattened.pdf) using the following code (iText 7.1.0)
try (PdfWriter output = new PdfWriter("output.pdf");
PdfDocument input = new PdfDocument(new PdfReader("input.pdf"), output)) {
PdfAcroForm.getAcroForm(input, true).flattenFields();
}
the appearance of the signature is stretched like this:
Flattening the same PDF using PDFBox or command line arguments like GhostScript or convert (imagemagick) or pdf2ps/ps2pdf works.
What's the reason of this behavior?

The problem is that the signature annotation has this Rect value:
[35.0 115.0 215.0 155.0]
which is a rectangle with its lower left at (35,115) and the upper left at (215,155), i.e. a rectangle 180 wide and 40 high.
Its appearance, though, has this BBox value:
[100.0 50.0 0.0 0.0]
which is a rectangle 100 units wide and 50 high. (Strictly speaking this is not completely valid: generally in PDFs rectangles are written as an array of four numbers giving the coordinates of a pair of diagonally opposite corners. For BBox values, though, the order is fixed: An array of four numbers giving the left, bottom, right, and top coordinates, respectively. But the problem discussed here also turns up if the correct order is used.)
According to the PDF specification the appearance will be stretched to match the annotation rectangle.
During flattening, though, the former signature appearance is added to the page using a transformation matrix of:
1 0 0 1 35 115
which correctly positions its lower left at (35,115) but maps the rectangle using the identity matrix; thus, it incorrectly is not stretched to a size of 180x40 but remains a 100x50 which is the stretch (actually the missing stretch!) you observe.
In short, you appear to have found a bug in iText, a missing transformation...

Related

Mapbox style to separate overlapping lines

Given two linestrings that occupy the same space, is it possible to define a style such that the lines are offset from each other and are rendered side-by-side?
A colleague says he can half remember that this functionality is available in the style spec, but I have not been able to find reference to it. Is it possible?
The property you are looking for is "Line-Offset".
From documentation (paint-line-line-offset as of 2018-09-17) :
line-offset (Paint property) Optional number. Units in pixels. Defaults to 0. Transitionable.
The line's offset.
For linear features, a positive value offsets the line to the right, relative
to the direction of the line, and a negative value to the left.
For polygon features, a positive value results in an inset, and a negative value results in an outset.

iText: Do margins apply when using PdfContentByte?

I created a new document with 36 points margin all around:
Rectangle rect = new Rectangle(1224f, 792f);
Document doc = new Document(rect, 36f, 36f, 36f, 36f);
I drew a rectangle at (0, 0) using PdfContentByte:
cb.rectangle(0, 0, 100, 100);
cb.fill();
The rectangle gets drawn at the lower-left hand corner of the page. It ignores the margins completely. Is this the expected result?
Is this the expected result?
Yes, it is. The margins only are taken into account by operations adding content via the Document.
Whenever you access the content directly (DirectContent, UnderContent,OverContent), you can draw wherever you want.
When creating footers or headers, you actually rely on that behavior.
Furthermore, the margins have no influence on the coordinate system. As the coordinate system is configurable, one could have chosen 0,0 to be the lower left of the margin border. Actually you can do so by defining a page size rectangle that way. But that is not the normal usage of iText.

How to auto-crop a barrel-distorted image using ImageMagick?

Using ImageMagick's convert to barrel-distort a photo to correct a strongly visible pincushion distortion, I provide positive a, b or c values (from a database for my lens + focal length). This results in an image that is corrected, has the original width and height, but includes a non-rectangular, bent/distorted border, as the image is corrected towards its center. Simplified example:
convert rose: -virtual-pixel black -distort Barrel '+0.0 +0.1 +0.0' out.png
How can I automatically crop the black, bent border to the largest possible rectangle in the original aspect ratio within the rose?
The ImageMagick website says, that a parameter "d" is automatically calculated, that could do this (resulting in linear distortion effectively zooming into the image and pushing the bent border right outside the image bounds), but the imagemagick-calculated value seems to aim for something different (v6.6.9 on ubuntu 12.04). If I guess and manually specify a "d", I can get the intended result:
convert rose: -virtual-pixel black -distort Barrel '+0.0 +0.1 +0.0 +0.6' out.png
The given formular a+b+c+d=1 does not seem to be a proper d for my cropping case. Also, d seems to depend on the aspect ratio of the image and not only on a/b/c. How do I make ImageMagick crop the image, or, how to I calculate a proper d?
Update
I found Fred's ImageMagick script innercrop (http://www.fmwconcepts.com/imagemagick/innercrop/index.php) that does a bit what I need, but has drawbacks and is no solution for me. It asumes arbitrary outer areas, so it takes long to find the cropping rectangle. It does not work within Unix pipes, and it does not keep the original aspect ratio.
Update 2
Contemplating on the problem makes me think that calculating a "d" is not the solution, as changing d introduces more or less bending and seems to do more than just zoom. The d=1-(a+b+c) that is calculated by imagemagick results in the bent image touching the upper/lower bounds (for landscape images) or the left/right bounds (for portrait images). So I think the proper solution would be to calculate where one of the new 4 corners will be given a/b/c/d, and then crop to those new corners.
The way I understand the docs, you do not use commas to separate the parameters for the barrel-distort operator.
Here is an example image, alongside the output of the two commands you gave:
convert o.png -virtual-pixel black -distort Barrel '+0.0 +0.1 +0.0' out0.png
convert o.png -virtual-pixel black -distort Barrel '+0.0 +0.1 +0.0 +0.6' out1.png
I created the example image in order to better visualize what you possibly want to achieve.
However, I do not see the point you stated about the automatically calculated parameter 'd', and I do not see the effect you stated about using 'd=+0.6'...
I'm not sure I understand your wanted result correctly, so I'm assuming you want the area marked by the yellow rectangle cropped.
The image on the left is out0.png as created by the first command above.
In order to guess the required coordinates, we have to determine the image dimensions first:
identify out0.png
out0.png PNG 700x700 700x700+0+0 8-bit sRGB 36KB 0.000u 0:00.000
The image in the center is marked up with the white rectangle. The rectangle is there so you can look at it and tell me if that is the region you want cropped. The image on the right is the cropped image (without scaling it back to the original size).
Is this what you want? If yes, I can possibly update the answer in order to automatically determine the required coordinates of the cropping. (For now I've done it based on guessing.)
Update
I think you may have mis-understood the purpose of the barrel-distortion operation. It is meant for correcting a barrel (slight) distortion, as is produced by camera lenses. The 3 parameters a, b and c to be used for any specific combination of camera, lens and current zoom could possibly be stated in your photo's EXIF data. The formula were a+b+c+d = 1 is meant to be used when the new, distortion-corrected image should have the same dimensions as the original (distorted) image.
So to imitate the barrel-correction, we should probably use the second image from the last row above as our input:
convert out3.png -virtual-pixel gray -distort barrel '0 -0.2 0' corrected.png
Result:

Drawing text using PdfTextArray in iTextSharp - how?

I am drawing text in a PDF page using iTextSharp, and I have two requirements:
1) the text needs to be searchable by Adobe Reader and such
2) I need character-level control over where the text is drawn.
I can draw the text word-by-word using PdfContentByte.ShowText(), but I don't have control over where each character is drawn.
I can draw the text character-by-character using PdfContentByte.ShowText() but then it isn't searchable.
I'm now trying to create a PdfTextArray, which would seem to satisfy both of my requirements, but I'm having trouble calculating the correct offsets.
So my first question is: do you agree that PdfTextArray is what I need to do, in order to satisfy both of my original requirements?
If so, I have the PdfTextArray working correctly (in that it's outputting text) but I can't figure out how to accurately calculate the positioning offset that needs to get put between each pair of characters (right now I'm just using the fixed value -200 just to prove that the function works).
I believe the positioning offset is the distance from the right edge of the previous character to the left edge of the new character, expressed in "thousandths of a unit of text space". That leaves me two problems:
1) How wide is the previous character (in points), as drawn in the specified font & height? (I know where its left edge is, since I drew it there)
2) How do I convert from points to "units of text space"?
I'm not doing any fancy scaling or rotating, so my transformation matrices should all be identity matrices, which should simplify the calculations ...
Thanks,
Chris

OpenXml and Word: How to Calculate WrapPolygon Coordinates?

I am creating a Microsoft Word document using the OpenXml library. Most of what I need is already working correctly. However, I can't for the life of me find the following bit of information.
I'm displaying an image in an anchor, which causes text to wrap around the image. I used WrapSquare but this seems to affect the last line of the previous paragraph as shown in the image below. The image is anchored to the second paragraph but causes the last line of the first paragraph to also indent around the image.
Word Screenshot http://www.softcircuits.com/Client/Word.jpg
Experimenting within Word, I can make the text wrap how I want by changing the wrapping to WrapTight. However, this requires a WrapPolygon with several coordinates. And I can't find any way to determine the polygon coordinates so that they match the size of the image, which is in pixels.
The documentation doesn't even seem to indicate what units are used for these coordinates, let alone how to calculate them from pixels. I can only assume the calculation would involve a DPI value, but I have no idea how to determine what DPI will be used when the user eventually loads the document into Word.
I would also be satisfied if someone can explain why the issues described above is happening in the first place. I can shift the image down and the previous paragraph is no longer affected. But why is this necessary? (The Distance from text setting for both Left and Top is 0".)
The WrapPolygon element has two possible child elements of LineTo and StartPoint that each take a x and y coordinate. According to 2.1.1331 Part 1 Section 20.4.2.9, lineTo (Wrapping Polygon Line End Position) and 2.1.1334 Part 1 Section 20.4.2.14, start (Wrapping Polygon Start) found in the [MS-OI29500: Microsoft Office Implementation Information for ISO/IEC-29500 Standard Compliance]:
The standard states that the x and y attributes are represented in
EMUs. Office interprets the x and y attributes in a fixed coordinate
space of 21600x21600.
As far as converting pixels to EMUs (English Metric Units), take a look at this blog post for an example.
I finally resolved this. Despite what the standard says, the WrapPolygon coordinates are not EMUs (English Metric Units). The coordinates are relative to the fixed coordinate space (21600 x 21600, as mentioned in the quote provided by amurra).
More specifically, this means 0,0 is at the top, left corner of the image, and 21600,21600 is at the bottom, right corner of the image. This is the case no matter what the size of the image is. Coordinates greater than 21600 extend outside the image.
According to this article, "The 21600 value is a legacy artifact from the drawing layer of early versions of the Microsoft Office."