java - PDFBOX 2.0+ java 拼合注释 freetext 由 Foxit 创建

标签 java pdf pdfbox

我遇到了一个非常棘手的问题。我们有应该填写的表单,但有些人在福昕阅读器中使用注释自由格式文本注释而不是填写表单字段,因此注释永远不会变平。当我们的渲染软件生成最终文档时,不包括注释。

我尝试的解决方案基本上是浏览文档,获取注释文本内容并将其写入pdf,以便它位于最终文档中,然后删除实际注释,但我遇到了一个我不知道的问题知道注释使用的字体、行距等,因此无法找到如何从 pdfbox 中获取它以准确地重新创建注释,就像注释在未展平的表单上看起来一样。 基本上我想展平在foxit中创建的自由格式的注释(打字机注释功能) 这是代码。它正在工作,但我再次努力弄清楚如何将注释写入我的最终 pdf 文档。再次在 acroform 上展平不起作用,因为这些不是 acroform 字段!实时代码过滤掉任何不是自由文本类型注释的内容,但下面的代码应该显示我的问题。

    public static void main(String [] args)
{
        String startDoc = "C:/test2/test.pdf";
     String  finalFlat = "C:/test2/test_FLAT.pdf";

    try {
        // for testing
        try {
            //BasicConfigurator.configure();
            File myFile = new File(startDoc);
            PDDocument pdDoc = PDDocument.load( myFile );
            PDDocumentCatalog pdCatalog = pdDoc.getDocumentCatalog();
            PDAcroForm pdAcroForm = pdCatalog.getAcroForm();

            // set the NeedApperances flag
            pdAcroForm.setNeedAppearances(false);

            // correct the missing page link for the annotations
            for (PDPage page : pdDoc.getPages()) {

                for (PDAnnotation annot : page.getAnnotations()) {
                    System.out.println(annot.getContents());
                    System.out.println(annot.isPrinted());
                    System.out.println(annot.isLocked());

                    System.out.println(annot.getAppearance().toString());
                    PDPageContentStream contentStream = new PDPageContentStream(pdDoc, page, PDPageContentStream.AppendMode.APPEND,true,true);
                    int fontHeight = 14; 
                    contentStream.setFont(PDType1Font.TIMES_ROMAN, fontHeight);

                    float height = annot.getRectangle().getLowerLeftY();

                    String s  = annot.getContents().replaceAll("\t", "    ");

                    String ss[] = s.split("\\r");
                    for(String sss : ss)
                    {
                        contentStream.beginText();  
                        contentStream.newLineAtOffset(annot.getRectangle().getLowerLeftX(),height );
                      contentStream.showText(sss);
                      height = height + fontHeight * 2 ;

                      contentStream.endText();
                    }
                      contentStream.close();
                    page.getAnnotations().remove(annot);                    
                }
            }               
            pdAcroForm.flatten();
            pdDoc.save(finalFlat);
            pdDoc.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }   

    }
    catch (Exception e) {
        System.err.println("Exception: " + e.getLocalizedMessage());
    }
}

最佳答案

这不是一件有趣的事情。经过一百万次不同的测试,我仍然不明白所有的细微差别,但这个版本似乎可以扁平化所有 pdf 文件和注释(如果它们在 PDF 上可见)。测试了大约六个 pdf 创建者,如果注释在页面上可见,则有望将其扁平化。我怀疑有更好的方法,通过拉动矩阵并对其进行转换等等,但这是我让它在任何地方工作的唯一方法。

public static void flattenv3(String startDoc, String endDoc) {

  org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.INFO);
  String finalFlat = endDoc;


  try {

   try {
    //BasicConfigurator.configure();
    File myFile = new File(startDoc);
    PDDocument pdDoc = PDDocument.load(myFile);
    PDDocumentCatalog pdCatalog = pdDoc.getDocumentCatalog();
    PDAcroForm pdAcroForm = pdCatalog.getAcroForm();

    if (pdAcroForm != null) {
     pdAcroForm.setNeedAppearances(false);
     pdAcroForm.flatten();
    }

    // set the NeedApperances flag

    boolean isContentStreamWrapped;
    int ii = 0;

    for (PDPage page: pdDoc.getPages()) {
     PDPageContentStream contentStream;
     isContentStreamWrapped = false;
     List < PDAnnotation > annotations = new ArrayList < > ();

     for (PDAnnotation annotation: page.getAnnotations()) {



      if (!annotation.isInvisible() && !annotation.isHidden() && annotation.getNormalAppearanceStream() != null)

      {
       ii++;
       if (ii > 1) {
        // contentStream.close();
        // continue;

       }


       if (!isContentStreamWrapped) {
        contentStream = new PDPageContentStream(pdDoc, page, AppendMode.APPEND, true, true);
        isContentStreamWrapped = true;
       } else {
        contentStream = new PDPageContentStream(pdDoc, page, AppendMode.APPEND, true);
       }

       PDAppearanceStream appearanceStream = annotation.getNormalAppearanceStream();

       PDFormXObject fieldObject = new PDFormXObject(appearanceStream.getCOSObject());

       contentStream.saveGraphicsState();


       boolean needsTranslation = resolveNeedsTranslation(appearanceStream);



       Matrix transformationMatrix = new Matrix();
       boolean transformed = false;

        float lowerLeftX = annotation.getNormalAppearanceStream().getBBox().getLowerLeftX();
        float lowerLeftY = annotation.getNormalAppearanceStream().getBBox().getLowerLeftY();
        PDRectangle bbox = appearanceStream.getBBox();
        PDRectangle fieldRect = annotation.getRectangle();

        float xScale = fieldRect.getWidth() - bbox.getWidth();

        transformed = true;

        lowerLeftX = fieldRect.getLowerLeftX();
        lowerLeftY = fieldRect.getLowerLeftY();
        if (bbox.getLowerLeftX() <= 0 && bbox.getLowerLeftY() < 0 && Math.abs(xScale) < 1) //BASICALLY EQUAL TO 0 WITH ROUNDING
        {


         lowerLeftY = fieldRect.getLowerLeftY() - bbox.getLowerLeftY();
         if (bbox.getLowerLeftX() < 0 && bbox.getLowerLeftY() < 0) //THis is for the o
         {

          lowerLeftX = lowerLeftX - bbox.getLowerLeftX(); 

         }

        } else if (bbox.getLowerLeftX() == 0 && bbox.getLowerLeftY() < 0 && xScale >= 0) {

         lowerLeftX = fieldRect.getUpperRightX();

        } else if (bbox.getLowerLeftY() <= 0 && xScale >= 0) {

         lowerLeftY = fieldRect.getLowerLeftY() - bbox.getLowerLeftY() - xScale;

        } else if (bbox.getUpperRightY() <= 0) {

         if (annotation.getNormalAppearanceStream().getMatrix().getShearY() < 0) {
          lowerLeftY = fieldRect.getUpperRightY();
          lowerLeftX = fieldRect.getUpperRightX();

         }

        } else {

        }



        transformationMatrix.translate(lowerLeftX,
         lowerLeftY);
        contentStream.transform(transformationMatrix);


       contentStream.drawForm(fieldObject);
       contentStream.restoreGraphicsState();
       contentStream.close();
      }
     }
     page.setAnnotations(annotations);
    }


    pdDoc.save(finalFlat);
    pdDoc.close();
    File file = new File(finalFlat);

    // Desktop.getDesktop().browse(file.toURI());


   } catch (Exception e) {
    e.printStackTrace();
   }

  } catch (Exception e) {
   System.err.println("Exception: " + e.getLocalizedMessage());
  }
 }

}

关于java - PDFBOX 2.0+ java 拼合注释 freetext 由 Foxit 创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61112832/

相关文章:

java - PDF框错误: "org.apache.pdfbox.rendering.PDFRenderer not found" when it is present

java - 我想使用 pdfbox 显示 pdf 中的阿拉伯语文本?

java - 如何使用 PROJ.4 将坐标从 WGS84 转换为投影坐标?

java - 为什么我的代码填充了所有值

java - 如何使用 iText 在 pdf 最后一页添加图像?

pdf - 如何获取 acroform 中的字体信息?

c++ - 使用 libharu 在 pdf 中打印日文字符

未检测到 Java 套接字已关闭

java - 请求 header 中存在多个 JSESSIONID

java - 无法读取Java中pdf文件生成的文本