View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.media.services;
20  
21  import java.awt.Graphics;
22  import java.awt.image.BufferedImage;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.nio.file.Files;
26  import java.util.Optional;
27  import java.util.regex.Pattern;
28  
29  import org.apache.pdfbox.pdmodel.PDDocument;
30  import org.apache.pdfbox.pdmodel.PDPage;
31  import org.apache.pdfbox.pdmodel.common.PDDestinationOrAction;
32  import org.apache.pdfbox.pdmodel.interactive.action.PDActionGoTo;
33  import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDDestination;
34  import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
35  import org.apache.pdfbox.rendering.PDFRenderer;
36  import org.mycore.datamodel.niofs.MCRPath;
37  
38  public class MCRPdfThumbnailGenerator implements MCRThumbnailGenerator {
39  
40      private static final Pattern MATCHING_MIMETYPE = Pattern.compile("^application/pdf");
41  
42      @Override
43      public boolean matchesFileType(String mimeType, MCRPath path) {
44          return MATCHING_MIMETYPE.matcher(mimeType).matches();
45      }
46  
47      @Override
48      public Optional<BufferedImage> getThumbnail(MCRPath path, int size) throws IOException {
49          try (InputStream fileIS = Files.newInputStream(path); PDDocument pdf = PDDocument.load(fileIS)) {
50              final PDPage page = resolveOpenActionPage(pdf);
51              float pdfWidth = page.getCropBox().getWidth();
52              float pdfHeight = page.getCropBox().getHeight();
53              final int newWidth = pdfWidth > pdfHeight ? (int) Math.ceil(size * pdfWidth / pdfHeight) : size;
54              final float scale = newWidth / pdfWidth;
55  
56              PDFRenderer pdfRenderer = new PDFRenderer(pdf);
57              BufferedImage pdfRender = pdfRenderer.renderImage(pdf.getPages().indexOf(page), scale);
58              int imageType = MCRThumbnailUtils.getImageType(pdfRender);
59              if (imageType == BufferedImage.TYPE_BYTE_BINARY || imageType == BufferedImage.TYPE_BYTE_GRAY) {
60                  BufferedImage thumbnail = new BufferedImage(pdfRender.getWidth(), pdfRender.getHeight(),
61                      imageType);
62                  Graphics g = thumbnail.getGraphics();
63                  g.drawImage(pdfRender, 0, 0, null);
64                  g.dispose();
65                  return Optional.of(thumbnail);
66              }
67              return Optional.of(pdfRender);
68          }
69      }
70  
71      private PDPage resolveOpenActionPage(PDDocument pdf) throws IOException {
72          PDDestinationOrAction openAction = pdf.getDocumentCatalog().getOpenAction();
73  
74          if (openAction instanceof PDActionGoTo) {
75              final PDDestination destination = ((PDActionGoTo) openAction).getDestination();
76              if (destination instanceof PDPageDestination) {
77                  openAction = destination;
78              }
79          }
80  
81          if (openAction instanceof PDPageDestination) {
82              final PDPageDestination namedDestination = (PDPageDestination) openAction;
83              final PDPage pdPage = namedDestination.getPage();
84              if (pdPage != null) {
85                  return pdPage;
86              } else {
87                  int pageNumber = namedDestination.getPageNumber();
88                  if (pageNumber != -1) {
89                      return pdf.getPage(pageNumber);
90                  }
91              }
92          }
93  
94          return pdf.getPage(0);
95      }
96  }