iTextsharp 7:旋转图章或注释
iTextsharp 7: Rotating a Stamp or Annotation
我发现很多关于旋转的问题都与页面旋转有关 - 充其量是图像旋转。矩形和图章注释等对象究竟是如何通过 iText 旋转的?
我最初预计会有一个高级方法,例如 Rectangle.SetRotation(), 但那并不存在。尝试只使用 Image.SetRotation (float) 对图章的方向没有影响——这让我相信这一切都是关于旋转 FormXObject 矩形.
上下文相关的戳记代码:
ImageData img = ImageDataFactory.Create(imgsrc);
float iWidth = img.GetWidth();
float iHeight = img.GetHeight();
if (crop.GetWidth() > crop.GetHeight())
{
w = crop.GetWidth();
h = crop.GetHeight();
}
else
{
w = crop.GetHeight();
h = crop.GetWidth();
}
//Adjust to Page in Future Code
Rectangle location = new Rectangle(crop.GetLeft(),crop.GetBottom(),iWidth/4,iHeight/4);
PdfStampAnnotation stamp = new PdfStampAnnotation(location).SetStampName(new PdfName("#Logo"));
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iWidth, iHeight));
PdfCanvas canvas = new PdfCanvas(xObj, pdfDoc);
canvas.AddImage(img, 0, 0,iWidth, false);
stamp.SetNormalAppearance(xObj.GetPdfObject());
stamp.SetFlags(PdfAnnotation.PRINT);
stamp.SetFlags(PdfAnnotation.INVISIBLE);
pdfDoc.GetFirstPage().AddAnnotation(stamp);
pdfDoc.Close();
提前致谢...
我使用 Java 和 iText 7 为 Java 创建了测试方法;不过,将它们移植到 C# 和 iText 7 for .Net 应该是微不足道的,主要是用大写字母而不是小写字母开始方法。
基本上有两种方法可以创建内容旋转的图章注释:
- 在外观流中设置当前变换矩阵以旋转您添加的所有内容。
- 给注解的外观XObject添加一个旋转矩阵入口
使用 CTM
由于您的注释内容仅包含位图图像,因此可以使用 PdfCanvas.addImage
重载,允许设置 CTM 以插入图像:
ImageData imageData = ImageDataFactory.create(ByteStreams.toByteArray(imageStream));
float iWidth = imageData.getWidth();
float iHeight = imageData.getHeight();
Rectangle crop = pdfDocument.getFirstPage().getCropBox();
// The content image of the annotation shall be rotated, so switch width and height
Rectangle location = new Rectangle(crop.getLeft(), crop.getBottom(), iHeight/4, iWidth/4);
PdfStampAnnotation stamp = new PdfStampAnnotation(location).setStampName(new PdfName("#Logo"));
// The content image in the appearance shall be rotated, so switch width and height
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iHeight, iWidth));
PdfCanvas canvas = new PdfCanvas(xObj, pdfDocument);
// Insert image using rotation transformation matrix
canvas.addImage(imageData, 0, iWidth, -iHeight, 0, iHeight, 0);
stamp.setNormalAppearance(xObj.getPdfObject());
stamp.put(PdfName.Type, PdfName.Annot);
stamp.setFlags(PdfAnnotation.PRINT);
pdfDocument.getFirstPage().addAnnotation(stamp);
(AddRotatedAnnotation 测试 testRotateImage
)
使用外观矩阵
这个比上面的还要简单:
ImageData imageData = ImageDataFactory.create(ByteStreams.toByteArray(imageStream));
float iWidth = imageData.getWidth();
float iHeight = imageData.getHeight();
Rectangle crop = pdfDocument.getFirstPage().getCropBox();
// The appearance (with the upright image) of the annotation shall be rotated, so switch width and height
Rectangle location = new Rectangle(crop.getLeft(), crop.getBottom(), iHeight/4, iWidth/4);
PdfStampAnnotation stamp = new PdfStampAnnotation(location).setStampName(new PdfName("#Logo"));
// The content image in the appearance shall be upright, so don't switch width and height
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iWidth, iHeight));
// The appearance shall be rotated
xObj.put(PdfName.Matrix, new PdfArray(new int[]{0, 1, -1, 0, 0, 0}));
PdfCanvas canvas = new PdfCanvas(xObj, pdfDocument);
// Insert upright image
canvas.addImage(imageData, 0, 0, iWidth, false);
stamp.setNormalAppearance(xObj.getPdfObject());
stamp.put(PdfName.Type, PdfName.Annot);
stamp.setFlags(PdfAnnotation.PRINT);
pdfDocument.getFirstPage().addAnnotation(stamp);
(AddRotatedAnnotation 测试 testRotateMatrix
)
背景:外观矩阵
在您所说的评论中
it works so beautifully with the annotation matrix. If you don't mind, would you care to explain the significance of the Put method?
那个 put
调用实际上只添加一个带有键 Matrix 的条目和给定的矩阵作为注释外观字典的值。
但这足以满足 PDF 规范的要求
The algorithm outlined in this sub-clause shall be used to map from the coordinate system of the appearance XObject (as defined by its Matrix entry; see Table 97) to the annotation’s rectangle in default user space:
Algorithm: Appearance streams
a) 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.
b) 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.
c) 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:
AA = Matrix * A
(ISO 32000-1,第 12.5.5 节“外观流”)
因此,无论何时呈现带有外观流的注释,外观都会通过 Matrix 进行变换,其结果会被压缩 and/or 拉伸以适合注释矩形。
我发现很多关于旋转的问题都与页面旋转有关 - 充其量是图像旋转。矩形和图章注释等对象究竟是如何通过 iText 旋转的?
我最初预计会有一个高级方法,例如 Rectangle.SetRotation(), 但那并不存在。尝试只使用 Image.SetRotation (float) 对图章的方向没有影响——这让我相信这一切都是关于旋转 FormXObject 矩形.
上下文相关的戳记代码:
ImageData img = ImageDataFactory.Create(imgsrc);
float iWidth = img.GetWidth();
float iHeight = img.GetHeight();
if (crop.GetWidth() > crop.GetHeight())
{
w = crop.GetWidth();
h = crop.GetHeight();
}
else
{
w = crop.GetHeight();
h = crop.GetWidth();
}
//Adjust to Page in Future Code
Rectangle location = new Rectangle(crop.GetLeft(),crop.GetBottom(),iWidth/4,iHeight/4);
PdfStampAnnotation stamp = new PdfStampAnnotation(location).SetStampName(new PdfName("#Logo"));
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iWidth, iHeight));
PdfCanvas canvas = new PdfCanvas(xObj, pdfDoc);
canvas.AddImage(img, 0, 0,iWidth, false);
stamp.SetNormalAppearance(xObj.GetPdfObject());
stamp.SetFlags(PdfAnnotation.PRINT);
stamp.SetFlags(PdfAnnotation.INVISIBLE);
pdfDoc.GetFirstPage().AddAnnotation(stamp);
pdfDoc.Close();
提前致谢...
我使用 Java 和 iText 7 为 Java 创建了测试方法;不过,将它们移植到 C# 和 iText 7 for .Net 应该是微不足道的,主要是用大写字母而不是小写字母开始方法。
基本上有两种方法可以创建内容旋转的图章注释:
- 在外观流中设置当前变换矩阵以旋转您添加的所有内容。
- 给注解的外观XObject添加一个旋转矩阵入口
使用 CTM
由于您的注释内容仅包含位图图像,因此可以使用 PdfCanvas.addImage
重载,允许设置 CTM 以插入图像:
ImageData imageData = ImageDataFactory.create(ByteStreams.toByteArray(imageStream));
float iWidth = imageData.getWidth();
float iHeight = imageData.getHeight();
Rectangle crop = pdfDocument.getFirstPage().getCropBox();
// The content image of the annotation shall be rotated, so switch width and height
Rectangle location = new Rectangle(crop.getLeft(), crop.getBottom(), iHeight/4, iWidth/4);
PdfStampAnnotation stamp = new PdfStampAnnotation(location).setStampName(new PdfName("#Logo"));
// The content image in the appearance shall be rotated, so switch width and height
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iHeight, iWidth));
PdfCanvas canvas = new PdfCanvas(xObj, pdfDocument);
// Insert image using rotation transformation matrix
canvas.addImage(imageData, 0, iWidth, -iHeight, 0, iHeight, 0);
stamp.setNormalAppearance(xObj.getPdfObject());
stamp.put(PdfName.Type, PdfName.Annot);
stamp.setFlags(PdfAnnotation.PRINT);
pdfDocument.getFirstPage().addAnnotation(stamp);
(AddRotatedAnnotation 测试 testRotateImage
)
使用外观矩阵
这个比上面的还要简单:
ImageData imageData = ImageDataFactory.create(ByteStreams.toByteArray(imageStream));
float iWidth = imageData.getWidth();
float iHeight = imageData.getHeight();
Rectangle crop = pdfDocument.getFirstPage().getCropBox();
// The appearance (with the upright image) of the annotation shall be rotated, so switch width and height
Rectangle location = new Rectangle(crop.getLeft(), crop.getBottom(), iHeight/4, iWidth/4);
PdfStampAnnotation stamp = new PdfStampAnnotation(location).setStampName(new PdfName("#Logo"));
// The content image in the appearance shall be upright, so don't switch width and height
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iWidth, iHeight));
// The appearance shall be rotated
xObj.put(PdfName.Matrix, new PdfArray(new int[]{0, 1, -1, 0, 0, 0}));
PdfCanvas canvas = new PdfCanvas(xObj, pdfDocument);
// Insert upright image
canvas.addImage(imageData, 0, 0, iWidth, false);
stamp.setNormalAppearance(xObj.getPdfObject());
stamp.put(PdfName.Type, PdfName.Annot);
stamp.setFlags(PdfAnnotation.PRINT);
pdfDocument.getFirstPage().addAnnotation(stamp);
(AddRotatedAnnotation 测试 testRotateMatrix
)
背景:外观矩阵
在您所说的评论中
it works so beautifully with the annotation matrix. If you don't mind, would you care to explain the significance of the Put method?
那个 put
调用实际上只添加一个带有键 Matrix 的条目和给定的矩阵作为注释外观字典的值。
但这足以满足 PDF 规范的要求
The algorithm outlined in this sub-clause shall be used to map from the coordinate system of the appearance XObject (as defined by its Matrix entry; see Table 97) to the annotation’s rectangle in default user space:
Algorithm: Appearance streams
a) 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.
b) 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.
c) 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:
AA = Matrix * A
(ISO 32000-1,第 12.5.5 节“外观流”)
因此,无论何时呈现带有外观流的注释,外观都会通过 Matrix 进行变换,其结果会被压缩 and/or 拉伸以适合注释矩形。