1

我发现很多关于旋转的问题都与页面旋转有关 - 充其量是图像旋转。通过 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();

提前致谢...

4

1 回答 1

3

我使用 Java 和 iText 7 for Java 创建了测试方法;不过,它们应该很容易移植到 .Net 的 C# 和 iText 7,主要是用大写字母而不是小写字母开头的方法。

基本上有两种方法可以创建内容显示为旋转的图章注释:

  • 在外观流中设置当前转换矩阵以旋转您添加的所有内容。
  • 将旋转矩阵条目添加到注释的外观 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)

背景:外观矩阵

在你所说的评论中

它与注释矩阵配合得非常好。如果您不介意,您愿意解释一下 Put 方法的意义吗?

put调用实际上仅将具有键Matrix和给定矩阵的条目作为值添加到注释外观字典中。

但这足以满足 PDF 规范的要求

本子条款中概述的算法将用于从外观 XObject(由其Matrix条目定义;参见表 97)的坐标系映射到默认用户空间中的注释矩形:

算法:外观流

a) 外观的边界框(由其BBox条目指定)应使用Matrix进行转换,以生成具有任意方向的四边形。转换后的外观框是包含此四边形的最小直立矩形。

b)应计算一个矩阵A ,该矩阵 A 缩放和平移转换后的外观框,以与注释矩形的边缘(由Rect条目指定)对齐。A将变换后的外观框的左下角( xy坐标最小的角)和右上角(xy坐标最大的角)映射到注释矩形的相应角。

c)矩阵应与A连接以形成矩阵AA,该矩阵从外观坐标系映射到默认用户空间中的注释矩形:

AA =矩阵* A

(ISO 32000-1,第 12.5.5 节“外观流”)

因此,每当呈现带有外观流的注释时,外观都会由Matrix转换,并且其结果会被压缩和/或拉伸以适合注释矩形。

于 2017-04-16T22:09:44.317 回答