【问题标题】:iTextsharp 7: Rotating a Stamp or AnnotationiTextsharp 7:旋转图章或注释
【发布时间】:2017-04-12 16:10:53
【问题描述】:

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

提前谢谢...

【问题讨论】:

    标签: c# pdf rotation itext7 stamp


    【解决方案1】:

    我使用 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,该矩阵将缩放和平移转换后的外观框以与注释矩形的边缘对齐(由 Rect 条目指定)。 A 映射左下角(具有最小 xy 坐标的角)和右上角(具有变换后的外观框的最大 xy 坐标)到注解矩形的相应角。

    c) Matrix 应与 A 连接形成一个矩阵 AA,默认从外观坐标系映射到注解的矩形用户空间:

    AA = 矩阵 * A

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

    因此,每当一个带有外观流的注解被渲染时,外观会被Matrix变换,其结果被压缩和/或拉伸以适应注解矩形。

    【讨论】:

    • 很高兴能尽快试用!我只是碰巧迫切需要它来纠正PDF旋转问题!一如既往的感谢,会告诉你进展如何。
    • 好吧,经过一些故障排除后,我设法将您的代码适合我的程序上下文 - 我不敢相信它与注释矩阵一起工作得如此出色。如果您不介意,您愿意解释一下 Put 方法的意义吗?我以前从未使用过它,我无法想象您将如何应用旋转操作。我一开始以为只是把它加到了注解字典里,但是错过了会有什么后果呢?
    猜你喜欢
    • 1970-01-01
    • 2015-06-18
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多