Estoy tratando de extraer texto con coordenadas de un archivo pdf usando PDFBox.
Mezclé algunos métodos/información que se encuentra en Internet (también stackoverflow), pero el problema que tengo con las coordenadas no parece ser correcto. Cuando trato de usar coordenadas para dibujar un rectángulo encima de tex, por ejemplo, el rect se pinta en otro lugar.
Este es mi código (no juzgues el estilo, fue escrito muy rápido solo para probar)
TextLine.java
import java.util.List;
import org.apache.pdfbox.text.TextPosition;
/**
*
* @author samue
*/
public class TextLine {
public List<TextPosition> textPositions = null;
public String text = "";
}
myStripper.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author samue
*/
public class myStripper extends PDFTextStripper {
public myStripper() throws IOException
{
}
@Override
protected void startPage(PDPage page) throws IOException
{
startOfLine = true;
super.startPage(page);
}
@Override
protected void writeLineSeparator() throws IOException
{
startOfLine = true;
super.writeLineSeparator();
}
@Override
public String getText(PDDocument doc) throws IOException
{
lines = new ArrayList<TextLine>();
return super.getText(doc);
}
@Override
protected void writeWordSeparator() throws IOException
{
TextLine tmpline = null;
tmpline = lines.get(lines.size() - 1);
tmpline.text += getWordSeparator();
super.writeWordSeparator();
}
@Override
protected void writeString(String text, List<TextPosition> textPositions) throws IOException
{
TextLine tmpline = null;
if (startOfLine) {
tmpline = new TextLine();
tmpline.text = text;
tmpline.textPositions = textPositions;
lines.add(tmpline);
} else {
tmpline = lines.get(lines.size() - 1);
tmpline.text += text;
tmpline.textPositions.addAll(textPositions);
}
if (startOfLine)
{
startOfLine = false;
}
super.writeString(text, textPositions);
}
boolean startOfLine = true;
public ArrayList<TextLine> lines = null;
}
haga clic en evento en el botón AWT
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
try {
File file = new File("C:\\Users\\samue\\Desktop\\mwb_I_201711.pdf");
PDDocument doc = PDDocument.load(file);
myStripper stripper = new myStripper();
stripper.setStartPage(1); // fix it to first page just to test it
stripper.setEndPage(1);
stripper.getText(doc);
TextLine line = stripper.lines.get(1); // the line i want to paint on
float minx = -1;
float maxx = -1;
for (TextPosition pos: line.textPositions)
{
if (pos == null)
continue;
if (minx == -1 || pos.getTextMatrix().getTranslateX() < minx) {
minx = pos.getTextMatrix().getTranslateX();
}
if (maxx == -1 || pos.getTextMatrix().getTranslateX() > maxx) {
maxx = pos.getTextMatrix().getTranslateX();
}
}
TextPosition firstPosition = line.textPositions.get(0);
TextPosition lastPosition = line.textPositions.get(line.textPositions.size() - 1);
float x = minx;
float y = firstPosition.getTextMatrix().getTranslateY();
float w = (maxx - minx) + lastPosition.getWidth();
float h = lastPosition.getHeightDir();
PDPageContentStream contentStream = new PDPageContentStream(doc, doc.getPage(0), PDPageContentStream.AppendMode.APPEND, false);
contentStream.setNonStrokingColor(Color.RED);
contentStream.addRect(x, y, w, h);
contentStream.fill();
contentStream.close();
File fileout = new File("C:\\Users\\samue\\Desktop\\pdfbox.pdf");
doc.save(fileout);
doc.close();
} catch (Exception ex) {
}
}
¿cualquier sugerencia? ¿Qué estoy haciendo mal?
No he entendido tu código (debo irme a la cama ahora). Tenga en cuenta que en PDF, y = 0 es inferior, no superior. Aquí hay un ejemplo que puede ayudar a entender cómo usar las coordenadas de extracción de texto: svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/…
–Tilman Hausherr
6 sep 2017 a las 20:17
¿Has probado a usar el
PDPageContentStream
constructor con otro argumento booleanoresetContext
y poniéndolo entrue
?– mkl
06/09/2017 a las 23:32
sí, sé que 0 es la parte inferior, esta es la razón por la que usé .getTextMatrix().getTranslateY() en lugar de getY() o getYDirAdj(). He intentado usar resetContext pero sin ayuda. ahora voy a ver ese código fuente, lo actualizaré, gracias
– Samuel Diella
7 sep 2017 a las 14:07
Acabo de probar su código y funcionó correctamente en un PDF de muestra (bueno, solo cubrió el texto desde la línea de base hacia arriba, pero eso es de esperar). Por lo tanto, hay algo diferente en los archivos PDF en los que los rectángulos están pintado en otro lugar. Supongo que eso se arreglaría si usaras el
PDPageContentStream
Señalé hacia en mi comentario anterior. Sin embargo, no puedo estar seguro sin un PDF de muestra en el que haya observado el problema. Por lo tanto, comparta un PDF de muestra.– mkl
7 sep 2017 a las 14:50
Probé el código en tu enlace. Está funcionando, pero está pintando formas en un PNG, no rectángulos en la transmisión. Estoy tratando de convertir formas en rectángulos, pero tengo algunas dificultades ^^” de todos modos, el PDF es este: descargar-a.akamaihd.net/files/media_mwb/b7/mwb_I_201711.pdf supongo que es algo sobre fuentes o transformación de fuentes
– Samuel Diella
7 sep 2017 a las 23:07