更改PDF中所有链接目标的缩放级别

时间:2017-04-07 16:47:48

标签: c# itext

使用iText中的Java更改缩放级别的代码位于iText home page。我想将其转换为C#。经过无数个小时,我终于重写了代码,发现它并没有改变任何链接。这意味着我一定是犯了错误。

编辑:

根据要求,请查看simple PDF example

我的代码如下:

using (var reader = new PdfReader(input))
{
    using (var stamper = new PdfStamper(reader, ms))
    {
        for (int i = 1; i <= reader.NumberOfPages; i++)
        {
            // Get a page of a PDF page
            PdfDictionary page = reader.GetPageN(i);

            // Get all the annotations of page i
            PdfArray annotsArray = page.GetAsArray(PdfName.ANNOTS);

            // If page does not have annotations
            if (annotsArray == null)
            {
                continue;
            }

            // For each annotation
            for (int j = 0; j < annotsArray.Size; j++)
            {
                // for current annotation
                PdfDictionary annotation = annotsArray.GetAsDict(j);

                // test if it is LINK
                PdfDictionary annotationAction = annotation.GetAsDict(PdfName.A);
                if ( annotationAction == null || PdfName.LINK.Equals(annotationAction.Get(PdfName.S)) )
                {
                    PdfArray d = annotation.GetAsArray(PdfName.DEST);
                    if (d != null && d.Length == 5 && PdfName.XYZ.Equals(d.GetAsName(1)))
                    {
                        d[4] = new PdfNumber(150);
                    }
                }

            }
        }
    }
}

Java中的原始代码要短得多:

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfDictionary page = reader.getPageN(11);
        PdfArray annots = page.getAsArray(PdfName.ANNOTS); 
        for (int i = 0; i < annots.size(); i++) {
            PdfDictionary annotation = annots.getAsDict(i);
            if (PdfName.LINK.equals(annotation.getAsName(PdfName.SUBTYPE))) {
                PdfArray d = annotation.getAsArray(PdfName.DEST);
                if (d != null && d.size() == 5 && PdfName.XYZ.equals(d.getAsName(1)))
                    d.set(4, new PdfNumber(0));
            }
        }
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        stamper.close();
    }

更新编辑2

感谢@mkl,我提出了解决方案。

for (int i = 1; i <= reader.NumberOfPages; i++)
{
    PdfDictionary page = reader.GetPageN(i);

    PdfArray annotsArray = page.GetAsArray(PdfName.ANNOTS);

    if (annotsArray == null)
    {
        continue;
    }

    for (int j = 0; j < annotsArray.Size; j++)
    {
        PdfDictionary annotation = annotsArray.GetAsDict(j);

        PdfDictionary annotationAction = annotation.GetAsDict(PdfName.A);
        if (PdfName.GOTO.Equals(annotationAction.Get(PdfName.S)))
        {
            PdfArray d = annotationAction.GetAsArray(PdfName.D);
            if (d != null)
            {
                Console.WriteLine(d[4]);
                d[4] = new PdfNumber(1.20);
            }

        }

    }
}    

2 个答案:

答案 0 :(得分:1)

不确定您是否使用其他PDF作为输入,但使用the source PDF from the iText web site作为问题中链接的示例,这对我有用,并将所有链接的缩放级别更改为文档缩放级别:

using (reader)
{
    PdfDictionary page = reader.GetPageN(11);
    PdfArray annots = page.GetAsArray(PdfName.ANNOTS);
    for (int i = 0; i < annots.Size; i++)
    {
        PdfDictionary annotation = annots.GetAsDict(i);
        if (PdfName.LINK.Equals(annotation.GetAsName(PdfName.SUBTYPE)))
        {
            PdfArray d = annotation.GetAsArray(PdfName.DEST);
            if (d != null && d.Size == 5 && PdfName.XYZ.Equals(d.GetAsName(1)))
                d.Set(4, new PdfNumber(0));
        }
    }
    using (var stream = new MemoryStream())
    {
        using (var stamper = new PdfStamper(reader, stream)) { }
        File.WriteAllBytes(outputFile, stream.ToArray());
    }
}

答案 1 :(得分:1)

如果你看一下链接注释的规范,你会看到

  

<强> A   字典   (可选; PDF 1.1)激活链接注释时应执行的操作(参见12.6,“操作”)。

     

<强>目的地   数组,名称或   字节串   (可选;如果存在 A 条目,则不允许)激活注释时应显示的目的地(见12.3.2,“目的地”)。

(表173 - 特定于链接注释的附加条目 - ISO 32000-1)

即。原始Java代码和您的端口只处理一种链接注释,使用 Dest 条目。

检查您的示例PDF,可以使用 A 条目找到链接注释,例如

/A <<
    /D  [ 1 /XYZ 0.000001 842 0.724 ]   
    /S  /GoTo   
>>

因此,您的代码必须考虑所有可能的选项。特别是如果你操作的PDF有一个 A ction而不是 Dest ination,它必须正确处理 D 的< strong> A ction,而不仅仅是不存在的链接 Dest