当前位置: 首页 > 知识库问答 >
问题:

复制时在PDFBox中的新文档中裁剪页面

万浩淼
2023-03-14

我正在尝试将单个PDF拆分为多个。将10页文档转换为10页单页文档。

PDDocument source = PDDocument.load(input_file);
PDDocument output = new PDDocument();
PDPage page = source.getPages().get(0);
output.addPage(page);
output.save(file);
output.close();

这里的问题是,新文档的页面大小与原始文档不同。因此,一些文本在新文档中被裁剪或丢失。我正在使用PDFBox 2.0,如何避免这种情况?

更新:感谢@mkl。

斯普利特变魔术了。这是更新后的工作部件,

public static void extractAndCreateDocument(SplitMeta meta, PDDocument source)
      throws IOException {

    File file = new File(meta.getFilename());

    Splitter splitter = new Splitter();
    splitter.setStartPage(meta.getStart());
    splitter.setEndPage(meta.getEnd());
    splitter.setSplitAtPage(meta.getEnd());

    List<PDDocument> docs = splitter.split(source);
    if(docs.size() > 0){
      PDDocument output = docs.get(0);
      output.save(file);
      output.close();
    }
  }

public class SplitMeta {

  private String filename;
  private int start;
  private int end;

  public SplitMeta() {
  }
}

共有1个答案

高森
2023-03-14

遗憾的是,OP没有提供复制该问题的示例文档。因此,我不得不猜测。

我假设问题是基于没有直接链接到页面对象但从其父对象继承的对象。

在这种情况下,请使用PDDocument。addPage是错误的选择,因为此方法只将给定的page对象添加到目标文档页面树中,而不考虑继承的内容。

相反,应该使用PDDocument。导入页面,记录如下:

/**
 * This will import and copy the contents from another location. Currently the content stream is stored in a scratch
 * file. The scratch file is associated with the document. If you are adding a page to this document from another
 * document and want to copy the contents to this document's scratch file then use this method otherwise just use
 * the {@link #addPage} method.
 * 
 * Unlike {@link #addPage}, this method does a deep copy. If your page has annotations, and if
 * these link to pages not in the target document, then the target document might become huge.
 * What you need to do is to delete page references of such annotations. See
 * <a href="http://stackoverflow.com/a/35477351/535646">here</a> for how to do this.
 *
 * @param page The page to import.
 * @return The page that was imported.
 * 
 * @throws IOException If there is an error copying the page.
 */
public PDPage importPage(PDPage page) throws IOException

实际上,即使是这种方法也可能不够,因为它不考虑所有继承的属性,但查看拆分器实用程序类,您会对必须执行的操作有一个印象:

PDPage imported = getDestinationDocument().importPage(page);
imported.setCropBox(page.getCropBox());
imported.setMediaBox(page.getMediaBox());
// only the resources of the page will be copied
imported.setResources(page.getResources());
imported.setRotation(page.getRotation());
// remove page links to avoid copying not needed resources 
processAnnotations(imported);

使用helper方法

private void processAnnotations(PDPage imported) throws IOException
{
    List<PDAnnotation> annotations = imported.getAnnotations();
    for (PDAnnotation annotation : annotations)
    {
        if (annotation instanceof PDAnnotationLink)
        {
            PDAnnotationLink link = (PDAnnotationLink)annotation;   
            PDDestination destination = link.getDestination();
            if (destination == null && link.getAction() != null)
            {
                PDAction action = link.getAction();
                if (action instanceof PDActionGoTo)
                {
                    destination = ((PDActionGoTo)action).getDestination();
                }
            }
            if (destination instanceof PDPageDestination)
            {
                // TODO preserve links to pages within the splitted result  
                ((PDPageDestination) destination).setPage(null);
            }
        }
        // TODO preserve links to pages within the splitted result  
        annotation.setPage(null);
    }
}

当您尝试将单个PDF拆分为多个时,例如将10页文档拆分为10页文档,您可能希望按原样使用此Splitter实用程序类。

为了测试这些方法,我使用了PDF小丑示例输出AnnotationSample的输出。标准pdf,因为该库严重依赖于页面树值的继承。因此,我使用PDDocument将其唯一页面的内容复制到新文档中。添加页面,PDDocument。导入页面,或拆分器,如下所示:

PDDocument source = PDDocument.load(resource);
PDDocument output = new PDDocument();
PDPage page = source.getPages().get(0);
output.addPage(page);
output.save(new File(RESULT_FOLDER, "PageAddedFromAnnotationSample.Standard.pdf"));
output.close();

(CopyPages.javatesttestSusAddPage

PDDocument source = PDDocument.load(resource);
PDDocument output = new PDDocument();
PDPage page = source.getPages().get(0);
output.importPage(page);
output.save(new File(RESULT_FOLDER, "PageImportedFromAnnotationSample.Standard.pdf"));
output.close();

(CopyPages.java测试testWithImportPage)

PDDocument source = PDDocument.load(resource);
Splitter splitter = new Splitter();
List<PDDocument> results = splitter.split(source);
Assert.assertEquals("Expected exactly one result document from splitting a single page document.", 1, results.size());
PDDocument output = results.get(0);
output.save(new File(RESULT_FOLDER, "PageSplitFromAnnotationSample.Standard.pdf"));
output.close();

(CopyPages.java测试用剥离器测试)

只有最后的测试才忠实地复制了页面。

 类似资料:
  • 我想删除PDF中每个页面的底部部分,但不改变页面大小,什么是推荐的方式在PDFBOX中的java中做到这一点?如何删除页脚从PDF中的每个页面? 是否有可能使用PDRectgle删除其中的所有文本/图像? 我所尝试的片段,使用setCropBox矩形似乎失去页面大小,也许cropBox不打算这样做? 在pdfbox cookbook示例中,我能找到的最接近的例子是如何删除整个页面,但这不是我想要的

  • Apache PDFBox 是一个开源 Java 库,支持 PDF 文档的开发和转换。在本教程中,我们将学习如何使用 PDFBox 开发可以创建,转换和操作 PDF 文档的 Java 程序。

  • 我正在使用Python和Opencv。我现在正在做一个车牌识别项目。我现在可以像这样认出这个盘子: 我得到了这样一个“数组”: 问题是:如何用这些坐标裁剪出边界区域? 因为这四个对应项是排列的,它不是一个矩形,所以我不知道如何才能裁剪出来。

  • 我使用imageJ对活细胞进行自动显微镜检查。 显微镜将工作台置于所需细胞的中心,取一个Z形叠层,并将该叠层传递给imageJ。 然后我想使用“分析粒子”输出每个Z切片中的单元面积。(这很有效) 为此,我使用执行以下操作的宏: 选择一个区域 这一切都很好,除了复制步骤对于管道来说太慢。我需要以某种方式避免重复步骤。 有没有办法在不首先复制的情况下裁剪堆栈?(目前这会丢失除一个切片之外的所有切片的信

  • 我需要对matlab中的图像执行以下操作: 加载图像 计算图像的FFT(快速傅立叶变换) 将频率分量移到中心 像follow一样裁剪图像(如果图像分辨率为1000x1000,则图像所需的部分类似于以下坐标:100100800800。这是一个较小的图像。(应用过滤器去除高频的想法) 反向移位 傅里叶逆变换 . . . 我的代码如下所示: 问题是,当我想裁剪图像时,我的功能无法裁剪类型为“复杂双”的图

  • 问题内容: 我想用PHP裁剪图像并保存文件。我知道您应该使用GD库,但我不确定如何使用。有任何想法吗? 谢谢 问题答案: 您可以用来裁剪图像的必需部分。该命令如下所示: 来自PHP.net的代码- 从源图像中裁剪出一个80x40像素的图像