iTextSharp 7:调整邮票大小的正确方法?

时间:2017-02-01 16:40:41

标签: 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中的内容相对应。任何澄清都可以帮助未来的实施。

由于

1 个答案:

答案 0 :(得分:1)

缩小

  

我无法找到任何方法来缩放"图像向下

正如评论中已经解释的那样,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。

背景

  

我想我理解FormXObject代表什么,但Canvas是什么用的?它与PDF中的对应内容。

     

[...]

     

&#34;位置&#34;有什么区别?矩形和PdfFormXObject矩形

location矩形

PDF规范ISO 32000-1(第2部分将于今年出版)说

  

注释将对象(如笔记,声音或电影)与PDF文档页面上的位置相关联

(第12.5.1节注释 - 一般)

因此,要修复注释的第一件事就是这个位置是一个矩形,

  

注释矩形,以默认用户空间单位定义页面上注释的位置。

(第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矩形

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

  

外观流使注释能够以不同的方式以可视方式呈现,以反映其与用户的交互。每个外观流都是一个XObject形式:一个独立的内容流,应该在注释矩形内呈现。

(第12.5.5节“外观流”)

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

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

  

算法:外观流

     

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

     

b)应计算矩阵 A ,以缩放和平移变换后的外观框,使其与注释矩形的边缘对齐(由 Rect 条目指定)。 A 映射左下角(具有最小 x y 坐标的角落)和右上角(带有变换后的外观框的最大 x y 坐标)到注释矩形的相应角落。

     

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

     

AA = 矩阵 * A

(第12.5.5节“外观流”)

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

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

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

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

通过上面的算法,它可以平滑地适应注释矩形而不会有任何失真。

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

画布

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