PDFBox TextPosition x,y和width,高度偏离系数2

时间:2014-09-10 17:27:42

标签: java pdfbox

我写了一个简短的库来从PDF文档中提取锚文本的位置,以便稍后我可以将图像渲染为BufferedImage并在其上层叠HTML表单。它工作,但我必须缩放x,y和宽度和高度2,以使其正常工作。我目前通过将图像渲染为BufferedImage然后用红色绘制边界框来测试它。基本上......为什么它被2的这个因子关闭......我可以依靠这个因子来保持不变吗?当然,我意识到如果图像的大小改变了x,y坐标和宽度,高度将适当地缩放。是转换为图像可能缩放它?

这是我的代码:

AnchorTextRipper.java

import java.awt.Rectangle;
import java.io.IOException;
import java.util.HashMap;

import org.apache.pdfbox.util.PDFTextStripper;
import org.apache.pdfbox.util.TextPosition;

public class AnchorTextRipper extends PDFTextStripper {
    protected enum ScanState {
        INIT,
        SEARCHING,
        FOUND_POSSIBLE,
        SCANNING_ANCHOR,
        DONE
    }

    protected HashMap<String, Rectangle> anchors = new HashMap<String, Rectangle>();

    // Scanning variables
    protected ScanState state = ScanState.INIT;
    protected TextPosition lastFoundAnchor;
    protected StringBuilder lastFoundAnchorText;
    protected Double lastWidth;
    protected Rectangle lastFoundAnchorRect;

    public AnchorTextRipper() throws IOException {
        super();
        this.setSortByPosition(true);
    }

    /**
     * A method provided as an event interface to allow a subclass to perform
     * some specific functionality when text needs to be processed.
     *
     * @param text
     *            The text to be processed
     */
    @Override
    protected void processTextPosition(TextPosition text) {
        switch(state) {
        case INIT:
            state = ScanState.SEARCHING;
            lastFoundAnchor = null;
            lastFoundAnchorText = new StringBuilder();
            lastWidth = 0.0;
            lastFoundAnchorRect = null;
            break;
        case SEARCHING:
            if (text.getCharacter().equals("$")) {
                state = ScanState.FOUND_POSSIBLE;
                lastFoundAnchor = text;
            }
            break;
        case FOUND_POSSIBLE:
            if (text.getCharacter().equals("{")) {
                state = ScanState.SCANNING_ANCHOR;
            }
            break;
        case SCANNING_ANCHOR:
            if (text.getCharacter().equals("}")) {
                state = ScanState.DONE;
                break;
            }

            lastFoundAnchorText.append(text.getCharacter());
            break;
        case DONE:
            System.out.println(String.format("%f, %f (%f, %f) [%f, %f]", lastFoundAnchor.getX(), lastFoundAnchor.getY(), lastFoundAnchor.getXScale(), lastFoundAnchor.getYScale(), lastFoundAnchor.getWidth(), lastFoundAnchor.getHeight()));

            lastFoundAnchorRect = new Rectangle((int)Math.round(lastFoundAnchor.getX() * 2) , (int)Math.round((lastFoundAnchor.getY() * 2) - lastFoundAnchor.getHeight() * 2), (int)Math.round(lastWidth) * 2, (int)Math.round(lastFoundAnchor.getHeight() * 2));
            anchors.put(lastFoundAnchorText.toString(), lastFoundAnchorRect);
            state = ScanState.INIT;
            break;
        }

        if (state != ScanState.SEARCHING) {
            lastWidth += text.getWidth();
        }
    }
}

AnchorTextLocatorService.java

import org.apache.pdfbox.exceptions.CryptographyException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDStream;

public class AnchorTextLocatorService {
    protected AnchorTextRipper ripper = new AnchorTextRipper();

    public AnchorTextLocatorService(String filename) throws IOException {
        PDDocument document = null;

        try {
            document = PDDocument.load(filename);
            if (document.isEncrypted()) {
                document.decrypt("");
            }

            @SuppressWarnings("unchecked")
            List<PDPage> allPages = document.getDocumentCatalog().getAllPages();

            for (int i = 0; i < allPages.size(); i++) {
                PDPage page = (PDPage) allPages.get(i);
                PDStream contents = page.getContents();
                if (contents != null) {
                    ripper.processStream(page, page.findResources(), page.getContents().getStream());
                }
            }
        } catch (CryptographyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (document != null) {
                document.close();
            }
        }
    }



    public HashMap<String, Rectangle> getAnchors() {
        return ripper.anchors;
    }

    public Rectangle getAnchorRect(String anchorText) {
        return ripper.anchors.get(anchorText);
    }
}

Application.java

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Map.Entry;

import javax.imageio.ImageIO;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;

public class Application {


    /**
     * This will print the documents data.
     *
     * @param args
     *            The command line arguments.
     *
     * @throws Exception
     *             If there is an error parsing the document.
     */
    public static void main(String[] args) throws Exception {
        PDDocument document = PDDocument.load("test.pdf");
        if (document.isEncrypted()) {
            document.decrypt("");
        }

        PDPage page = (PDPage)document.getDocumentCatalog().getAllPages().get(0);
        BufferedImage bi = page.convertToImage();

        AnchorTextLocatorService ats = new AnchorTextLocatorService("test.pdf");

        for (Entry<String, Rectangle> anchor : ats.getAnchors().entrySet()) {
            System.out.println(anchor.getKey() + " => " + anchor.getValue());

            Graphics2D g = (Graphics2D)bi.getGraphics();
            g.setColor(Color.RED);
            g.drawRect(anchor.getValue().x, anchor.getValue().y, anchor.getValue().width, anchor.getValue().height);
        }

        ImageIO.write(bi, "png", new File("test.png"));
    }
}

1 个答案:

答案 0 :(得分:1)

https://pdfbox.apache.org/apidocs/org/apache/pdfbox/pdmodel/PDPage.html

对不起......我刚刚阅读了文档......本应该先做的。 PDPage :: convertToImage()以双倍分辨率输出它。希望这可能对其他人有所帮助。