Петля медленная - Java - PullRequest
       9

Петля медленная - Java

0 голосов
/ 06 декабря 2018

Я в основном хочу загрузить pdf с использованием Apache pdfbox и преобразовать его в список base64 для каждой страницы.

Я попробовал следующий код, но он очень медленный.Мне не нужно конвертировать в изображение, я просто хочу конвертировать в base64, чтобы перейти к интерфейсу

PDDocument document = PDDocument.loadNonSeq(new File("Random.pdf"), null);
@SuppressWarnings("unchecked")
List<PDPage> pdPages = document.getDocumentCatalog().getAllPages();
int page = 0;
List<String> base64DocumentPages = new ArrayList<>();
for (PDPage pdPage : pdPages)
{ 
    ++page;           
    BufferedImage img = pdPage.convertToImage(BufferedImage.TYPE_INT_RGB, 300); // this is slow
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    ImageIOUtil.writeImage(img, ".png", os);
    String base64Page = Base64.getEncoder().encodeToString(os.toByteArray());
    base64DocumentPages.add(URLEncoder.encode(base64Page, "UTF-8"));
}
document.close();

Я использую PDFBOX для зацикливания страниц, но я могу использовать что угодно, если вы знаете что-то лучше.

PS: мне действительно нужны данные Base64 страниц, разделенных в какой-то массив

1 Ответ

0 голосов
/ 07 декабря 2018

Вы уверены, что это метод convertToImage?В нашем случае это был метод writeIamge, который требует наибольшего времени.Проблема в том, что вы используете стандартный PNGWriter.У этого есть недостаток / ошибка, потому что он всегда использует лучшее сжатие по стоимости времени.Это было исправлено для Java 9, но до этого времени доступна версия backported .Итак, что вам нужно сделать?

(1) Добавьте следующую зависимость в ваш проект maven (или вручную, если вы не используете maven)

<dependency>
    <groupId>net.gredler</groupId>
    <artifactId>jdk9-png-writer-backport</artifactId>
    <version>1.0.0</version>
</dependency>

(2) Убедитесь, чтоВы используете PdfBox 2.X

(3) Измените код конверсии:

private static void convertMethod2(File pdf) {
        try (final PDDocument document = PDDocument.load(pdf)) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            List<String> base64DocumentPages = new ArrayList<>();               

            for (int page = 0; page < document.getNumberOfPages(); ++page) {
                BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 150, ImageType.RGB);

                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                PNGImageWriterBackport writer = chosePngWriter();

                if(writer!=null) {
                    try (ImageOutputStream stream = new MemoryCacheImageOutputStream(baos)) {
                        writer.setOutput(stream);
                        writer.write(null,new IIOImage(bim, null, null), getImageParams(writer));
                    }
                    finally {
                        writer.dispose();
                    }
                }
                else {
                    System.err.println("PNGImageWriterBackport not found! Aborting");
                }
                String base64Page = Base64.getEncoder().encodeToString(os.toByteArray());
                base64DocumentPages.add(URLEncoder.encode(base64Page, "UTF-8"));
            }
            document.close();
        }
        catch (IOException e) {
            //handle exception
        }
    }

    private static PNGImageWriterBackport chosePngWriter() {
        Iterator<ImageWriter> imageWriters = ImageIO.getImageWritersByFormatName("png");

        ImageWriter writer = null;
        while(imageWriters.hasNext()) {

            writer = imageWriters.next();
            if (writer instanceof PNGImageWriterBackport) {
                return (PNGImageWriterBackport)writer;
            }
        }
        return null;
    }

    private static ImageWriteParam getImageParams(PNGImageWriterBackport writer) {
        ImageWriteParam writeParam = writer.getDefaultWriteParam();
        //set compression mode which wasn't possible before
        writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        //0.0f highest compression, slowest
        //1.0f lowest compression, fastest
        writeParam.setCompressionQuality(0.9f);

        return writeParam;
    }

(4) Конечно, если возможно уменьшить DPI до, например, 150, это также ускоритпроцесс.Но я знаю, что это не всегда возможно ...

Это будет намного быстрее при цене минимально увеличенного размера файла png ...

...