PDFBOX 2.0+由Foxit创建的Java扁平化注释自由文本 [英] PDFBOX 2.0+ java flatten annotations freetext created by foxit

查看:197
本文介绍了PDFBOX 2.0+由Foxit创建的Java扁平化注释自由文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I ran into a very tough issue. We have forms that were supposed to be filled out, but some people used annotation freeform text comments in foxit instead of filling the form fields, so the annotations never flatten. When our render software generates the final document annotations are not included.

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

The solution I tried is to basically go through the document, get the annotation text content and write it to the pdf so it is on the final document then remove the actual annotation, but I run into an issue where I don't know the font the annotation is using, line space, etc so cannot find out how to get it from a pdfbox to recreate exacactly as the annotation looks on the unflattened form. Basically I want to flatten annotatations that are freeform created in foxit (The typewriter comment feature) Here is the code. It is working, but again I am struggling with figuring out how to get the annotations to write to my final pdf document. Again flatten on the acroform is not working because these are not acroform fields! The live code filters out anything that is not a freetext type annotation, but below code should show my issue.

    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创建者进行了测试,如果注释在页面上可见,则可以使注释变平.我怀疑有一个更好的方法是提取矩阵并对其进行转换,而没有进行转换,但这是我使它在任何地方都可以工作的唯一方法.

This was not a fun one. After a million different tests, and I STILL do not understand all the nuances, but this is the version that appeas to flatten all pdf files and annotations if they are visible on PDF. Tested about half a dozen pdf creators and if an annotation is visible on a page this hopefully flattens it. I suspect there is a better way by pulling the matrix and transforming it and what not, but this is the only way I got it to work everywhere.

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());
  }
 }

}

这篇关于PDFBOX 2.0+由Foxit创建的Java扁平化注释自由文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆