c# - iTextSharp 7 : Proper Way to Resize Stamps?

标签 c# pdf annotations itext7

我最近接触了 iText 的总体情况——在看过版本 5 和版本 7 后,我仍然对图章的实现方式感到困惑。我按照使用 iTextSharp 7 的示例代码之一添加注释:

 PdfReader reader = new PdfReader(source);
        PdfWriter writer = new PdfWriter(dest);
        PdfDocument pdfDoc = new PdfDocument(reader, writer);

        Rectangle crop = pdfDoc.GetPage(1).GetCropBox();
        Debug.WriteLine("CropBox Rectangle Dim "+crop);


        ImageData img = ImageDataFactory.Create(imgsrc);

        float iWidth = img.GetWidth();
        float iHeight = img.GetHeight();

        //Ignore the below statement
        if (crop.GetWidth() > crop.GetHeight())
        {
            w = crop.GetWidth();
            h = crop.GetHeight();
        }
        else
        {
            w = crop.GetHeight();
            h = crop.GetWidth();
        }


        Debug.WriteLine("Width = "+w+" and Height = "+h);


        Rectangle location = new Rectangle(crop.GetLeft(),crop.GetBottom(),iWidth,iHeight);

        //Creates a Stamp Bounding Box on "Location"
        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, false);
        stamp.SetNormalAppearance(xObj.GetPdfObject());



        stamp.SetFlags(PdfAnnotation.PRINT);

        pdfDoc.GetFirstPage().AddAnnotation(stamp);
        pdfDoc.Close();

首先,我注意到我正在使用 ImageData 对象来输入图像。但是,我找不到任何方法来“缩小”图像 - 类似于 Image.scaleAbsolute。输出的 PDF 最终正确地进行了标记,但尺寸完全过大。我想我明白 FormXObject 代表什么,但是 Canvas 是做什么用的?它在PDF中对应什么?任何澄清都可能对 future 的实现大有帮助。

谢谢

最佳答案

缩小规模

I can't find any method to "scale" the image down

正如评论中已经解释的那样,AddImage 方法的重载确实允许缩放图像,特别是:

/// <summary>Creates Image XObject from image and adds it to the specified position with specified width preserving aspect ratio.
///     </summary>
/// <param name="asInline">true if to add image as in-line.</param>
/// <returns>created XObject or null in case of in-line image (asInline = true).</returns>
public virtual PdfXObject AddImage(ImageData image, float x, float y, float width, bool asInline)

/// <summary>Creates Image XObject from image and adds it to canvas.</summary>
/// <param name="asInline">true if to add image as in-line.</param>
/// <returns>created XObject or null in case of in-line image (asInline = true).</returns>
public virtual PdfXObject AddImage(ImageData image, iText.Kernel.Geom.Rectangle rect, bool asInline)

/// <summary>Creates Image XObject from image and adds it to canvas.</summary>
/// <param name="image">
/// the
/// <c>PdfImageXObject</c>
/// object
/// </param>
/// <param name="a">an element of the transformation matrix</param>
/// <param name="b">an element of the transformation matrix</param>
/// <param name="c">an element of the transformation matrix</param>
/// <param name="d">an element of the transformation matrix</param>
/// <param name="e">an element of the transformation matrix</param>
/// <param name="f">an element of the transformation matrix</param>
/// <param name="asInline">true if to add image as in-line.</param>
/// <returns>created Image XObject or null in case of in-line image (asInline = true).</returns>
public virtual PdfXObject AddImage(ImageData image, float a, float b, float c, float d, float e, float f, 
    bool asInline)

这些重载中的第一个已经帮助了OP。

背景

I think I understand what the FormXObject represents, but what is the Canvas for? What does it correspond to in the PDF.

[...]

What is the difference between the "Location" rectangle and the PdfFormXObject rectangle

位置矩形

正如 PDF 规范 ISO 32000-1(第 2 部分将于今年发布)所述

An annotation associates an object such as a note, sound, or movie with a location on a page of a PDF document

(第 12.5.1 节注释 - 常规)

因此,注释首先要解决的问题之一就是这个位置,它是一个矩形,

The annotation rectangle, defining the location of the annotation on the page in default user space units.

(第 12.5.2 节注释字典)

此处使用的坐标系与为页面定义的 MediaBox 一致,其中 CropBox 是显示部分。

如果是 OP 代码,则在此处选择此注释矩形:

Rectangle location = new Rectangle(crop.GetLeft(),crop.GetBottom(),iWidth,iHeight);
PdfStampAnnotation stamp = new PdfStampAnnotation(location)...

即注释矩形location位于可见页面区域的左下角,宽度和高度为iWidth,iHeight

PdfFormXObject 矩形

但是注释是什么样子的呢?实际上注释可以有不同的外观,例如取决于光标是否悬停在它们上方。因此,每个注释对象可以在其外观字典中将一个或多个外观定义为单独的外观流:

Appearance streams enable the annotation to be presented visually in different ways to reflect its interactions with the user. Each appearance stream is a form XObject: a self-contained content stream that shall be rendered inside the annotation rectangle.

(第 12.5.5 节外观流)

因此,XObject 形式在这里成为故事的一部分:它们是自包含的,也可以从其他内容流引用,而不仅仅是从注释中引用。

它们实际上与注释如此独立,以至于它们有自己的坐标系(由其边界框 BBox 给出),并且仅在显示时(可能在仿射变换之后)适合注释矩形(由其矩阵矩阵给出):

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

(第 12.5.5 节外观流)

如果是 OP 代码,则在此处选择此边界框:

PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iWidth, iHeight));

该矩阵未明确给出,因此默认为单位矩阵。

即外观的边界框(PdfFormXObject 矩形)的宽度和高度为iWidth, iHeight,就像注释矩形一样,但其左下角是其坐标的原点 (0, 0)系统。

通过上面的算法,它将平滑地适合注释矩形,没有任何扭曲。

人们可能想知道为什么有这么多独立的坐标系使得这种转换成为必要。原因很简单:这使得 XObjects 表单可以轻松地重用,并且通过选择坐标系使其中的绘图指令变得尽可能简单。

Canvas

PdfCanvas 只是一个帮助程序类,在 iText 中提供统一的方式来为任何内容流创建内容指令,此处用于外观 XObject 内容流。

关于c# - iTextSharp 7 : Proper Way to Resize Stamps?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41985024/

相关文章:

java - 如何使用WebSocket在UWP客户端和Java服务器之间进行通信?

c# - 如何在 C# 中以编程方式查找项目文件夹

java - 如何在 Spring Web 应用程序中为同一 View 组合 GET 和 POST HTTP 方法?

swift - 使用 MapKit (Swift) 在 map 上显示带有图钉的自定义位置

linux - 缩放 pdf 以添加边框以打印全尺寸页面

java - 我可以从编译时注释向类添加方法吗?

c# - LINQ 返回数组,而不是列表对象的集合

c# - 如何阻止其他域指向我的域?

swift - PDFKit注释保存文本注释

java - PDFBox 设置覆盖特定页面