Estoy tratando de realizar OCR en archivos PDF. Hay 2 pasos en el código:
- Convertir pdf a archivos tiff
- Convertir tiff a texto
Usé ghost4j para el primer paso, y luego tess4j para el segundo. todo funcionó muy bien, hasta que comencé a ejecutarlo con varios subprocesos, y luego ocurrieron extrañas excepciones. Leí aquí: https://sourceforge.net/p/tess4j/discussion/1202293/thread/44cc65c5/ que ghost4j no es adecuado para multihilo, así que cambié el primer paso para trabajar con PDFBox.
Entonces ahora mi código se ve así:
PDDocument doc = PDDocument.load(this.bytes);
PDFRenderer pdfRenderer = new PDFRenderer(doc);
BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(0, 300);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "tiff", os);
os.flush();
os.close();
bufferedImage.flush();
Estoy tratando de ejecutar este código con un archivo pdf de 800 kb, y cuando verifico la memoria después de
BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(0, 300);
¡Se eleva a más de 500 MB! si estoy guardando esta imagen Buffered en el disco, la salida es de 1 MB de tamaño ... así que cuando intento ejecutar este código con 8 hilos, también obtengo la excepción de tamaño de almacenamiento dinámico de Java ...
¿Que me estoy perdiendo aqui? ¿Por qué un archivo de 1 MB da como resultado un archivo de imagen de 500 MB? Traté de jugar con el DPI y reducir la calidad, pero el archivo sigue siendo muy grande ... ¿Hay alguna otra biblioteca que pueda procesar PDF en TIFF y que pueda ejecutar 10 hilos sin problemas de memoria?
Pasos para reproducir:
- Descargue el archivo de currículum de Linkedin CEO desde aquí: https://gofile.io/?c=TtA7XQ
Yo que usé este código:
private static void test() throws IOException { printUsedMemory("App started..."); File file = new File("linkedinceoresume.pdf"); try (PDDocument doc = PDDocument.load(file)) { PDFRenderer pdfRenderer = new PDFRenderer(doc); printUsedMemory("Before"); for (int page = 0; page < 1; ++page) { BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(page, 76, ImageType.GRAY); ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "tiff", os); os.flush(); os.close(); bufferedImage.flush(); } } finally { printUsedMemory("BufferedImage"); } } private static void printUsedMemory(String text) { long freeMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); long mb = freeMemory / 1000000; System.out.println(text + "....Used memory: " + mb + " MB"); }
y la salida es:
Aplicación iniciada ....... Memoria usada: 42 MB
Antes .... Memoria usada: 107 MB
BufferedImage .... Memoria usada: 171 MB
En este ejemplo, no son 500 MB, sino un pdf de 70 kb, cuando intento renderizar solo una página, la memoria aumenta en aproximadamente 70 MB ... no es proporcional ...
BufferedImage
después de renderizar?