【问题标题】:Extract Image from PDF using Java使用Java从PDF中提取图像
【发布时间】:2015-07-01 02:11:56
【问题描述】:

我只需要从 PDF 中提取条形码(使用矩形),而不是将整个 PDF 转换为图像。

图片格式可以是jpg/png。

【问题讨论】:

    标签: java image pdf itext pdfbox


    【解决方案1】:

    使用 PDFBox 从 pdf 文件中提取图像

    import org.apache.pdfbox.contentstream.PDFStreamEngine;
    import org.apache.pdfbox.contentstream.operator.Operator;
    import org.apache.pdfbox.cos.COSBase;
    import org.apache.pdfbox.cos.COSName;
    import org.apache.pdfbox.pdmodel.PDDocument;
    import org.apache.pdfbox.pdmodel.PDPage;
    import org.apache.pdfbox.pdmodel.graphics.PDXObject;
    import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
    import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
    
    import javax.imageio.ImageIO;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    import java.util.UUID;
    
    public class ExtractImagesUseCase extends PDFStreamEngine{
        private final String filePath;
        private final String outputDir;
    
        // Constructor
        public ExtractImagesUseCase(String filePath,
                                    String outputDir){
            this.filePath = filePath;
            this.outputDir = outputDir;
        }
    
        // Execute
        public void execute(){
            try{
                File file = new File(filePath);
                PDDocument document = PDDocument.load(file);
    
                for(PDPage page : document.getPages()){
                    processPage(page);
                }
    
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    
        @Override
        protected void processOperator(Operator operator, List<COSBase> operands) throws IOException{
            String operation = operator.getName();
    
            if("Do".equals(operation)){
                COSName objectName = (COSName) operands.get(0);
                PDXObject pdxObject = getResources().getXObject(objectName);
    
                if(pdxObject instanceof PDImageXObject){
                    // Image
                    PDImageXObject image = (PDImageXObject) pdxObject;
                    BufferedImage bImage = image.getImage();
    
                    // File
                    String randomName = UUID.randomUUID().toString();
                    File outputFile = new File(outputDir,randomName + ".png");
    
                    // Write image to file
                    ImageIO.write(bImage, "PNG", outputFile);
    
                }else if(pdxObject instanceof PDFormXObject){
                    PDFormXObject form = (PDFormXObject) pdxObject;
                    showForm(form);
                }
            }
    
            else super.processOperator(operator, operands);
        }
    }
    

    演示

    public class ExtractImageDemo{
        public static void main(String[] args){
            String filePath = "C:\\Users\\John\\Downloads\\Documents\\sample-file.pdf";
            String outputDir = "C:\\Users\\John\\Downloads\\Documents\\Output";
    
            ExtractImagesUseCase useCase = new ExtractImagesUseCase(
                    filePath,
                    outputDir
            );
            useCase.execute();
        }
    }
    

    【讨论】:

      【解决方案2】:

      你可以使用 Pdfbox

      List pages = document.getDocumentCatalog().getAllPages();
      Iterator iter = pages.iterator();
      while( iter.hasNext() )
      {
          PDPage page = (PDPage)iter.next();
          PDResources resources = page.getResources();
          Map images = resources.getImages();
          if( images != null )
          {
              Iterator imageIter = images.keySet().iterator();
              while( imageIter.hasNext() )
              {
                  String key = (String)imageIter.next();
                  PDXObjectImage image = (PDXObjectImage)images.get( key );
                  String name = getUniqueFileName( key, image.getSuffix() );
                  System.out.println( "Writing image:" + name );
                  image.write2file( name );
              }
          }
      }
      

      Reference source code

      【讨论】:

      【解决方案3】:

      PDF Box,不带编码:

      "$JAVA_HOME/bin/java" -jar pdfbox-app-1.8.2.jar PDFToImage foo.pdf
      

      要进行批处理:

      import java.io.File;
      import java.io.FilenameFilter;
      import java.util.Arrays;
      import java.util.List;
      import java.util.Observer;
      
      import org.apache.pdfbox.PDFToImage;
      
      public class Main {
      
         static {
            System.setProperty(
               "org.apache.commons.logging.Log",
               "org.apache.commons.logging.impl.NoOpLog" );
         }
      
         public static int extract( List< File > files, File jpegDir, Observer observer ) {
            jpegDir.mkdirs();
            int done = 0;
            for( final File file : files ) {
               try {
                  final File   target   = new File( jpegDir, file.getName());
                  final String trgtPath = target.getPath();
                  final String prefix   = trgtPath.substring( 0, trgtPath.lastIndexOf( '.' ));
                  PDFToImage.main( new String[]{ "-outputPrefix", prefix, file.getPath() });
                  final double percent  = (100.0 * ++done ) / files.size();
                  System.out.printf( "%6.2f %%: %s\n", percent, file.getName());
                  if( observer != null ) {
                     observer.update( null, file );
                  }
               }
               catch( final Throwable t ) {
                  System.err.println( file.getPath());
                  t.printStackTrace();
               }
            }
            return done;
         }
      
         public static void main( String[] args ) {
            if( args.length != 2 ) {
               System.err.println(
                  "usage: java -jar pdf2img.jar <PDF directory> <JPEG directory>" );
               System.exit(1);
            }
            final File   pdfDir  = new File( args[0] );
            final File   jpegDir = new File( args[1] );
            final File[] files   = pdfDir.listFiles( new FilenameFilter() {
               @Override public boolean accept( File dir, String name ) {
                  return name.toLowerCase().endsWith( ".pdf" );
               }});
            if( files != null ) {
               final int done = extract( Arrays.asList( files ), jpegDir, null );
               System.out.printf(
                  "\n%d file%s processed.", done, ( done > 1 ) ? "s" : "" );
            }
         }
      }
      

      此实用程序可能与 GUI 相关联(法语本地化):

      public final class GUI extends Application {
      
         @Override
         public void start( Stage primaryStage ) throws Exception {
            final BorderPane        pane      = new BorderPane();
            final HBox              topPane   = new HBox();
            final Label             lbl       = new Label( "Répertoire des images : " );
            final TextField         jpegDir   = new TextField();
            final Button            browseBtn = new Button( "Parcourir..." );
            final TableView< File > filesVw   = new TableView<>();
            lbl.setAlignment( Pos.CENTER_LEFT );
            lbl      .setStyle( "-fx-padding:8px; -fx-margin:8px;" );
            jpegDir  .setStyle( "-fx-padding:8px; -fx-margin:8px;" );
            browseBtn.setStyle( "-fx-padding:8px; -fx-margin:8px;" );
            topPane.getChildren().addAll( lbl, jpegDir, browseBtn );
            pane.setTop( topPane );
            pane.setCenter( filesVw );
            jpegDir.setPrefColumnCount( 40 );
            jpegDir.setEditable( false );
            final ObservableList< TableColumn< File, ? >> columns = filesVw.getColumns();
            final TableColumn< File, String > name = new TableColumn<>( "Nom" );
            name.setCellValueFactory(
               new Callback< CellDataFeatures< File, String >, ObservableValue< String >>(){
                  @Override public ObservableValue< String > call( CellDataFeatures< File, String > p ){
                     return new SimpleStringProperty( p.getValue().getName()); }});
            name.setSortable( false );
            name.setPrefWidth( 400 );
            columns.add( name );
            final TableColumn< File, String > size = new TableColumn<>( "Taille" );
            size.setCellValueFactory(
               new Callback< CellDataFeatures< File, String >, ObservableValue< String >>(){
                  @Override public ObservableValue< String > call( CellDataFeatures< File, String > p ){
                     return new SimpleStringProperty( String.format( "%,12d", p.getValue().length())); }});
            size.setSortable( true );
            size.setPrefWidth( 80 );
            columns.add( size );
            final TableColumn< File, String > date = new TableColumn<>( "Date" );
            final SimpleDateFormat sdf = new SimpleDateFormat( "dd/MM/YYYY HH:mm" );
            date.setCellValueFactory(
               new Callback< CellDataFeatures< File, String >, ObservableValue< String >>(){
                  @Override public ObservableValue< String > call( CellDataFeatures< File, String > p ){
                     return new SimpleStringProperty(
                        sdf.format( new Date( p.getValue().lastModified()))); }});
            date.setSortable( true );
            date.setPrefWidth( 120 );
            columns.add( date );
            final Map< File, SimpleBooleanProperty > dones = new HashMap<>();
            final TableColumn< File, Boolean > done = new TableColumn<>( "Traité" );
            done.setCellValueFactory(
               new Callback< CellDataFeatures< File, Boolean >, ObservableValue< Boolean >>(){
                  @Override public ObservableValue< Boolean > call( CellDataFeatures< File, Boolean > p ){
                     return dones.get( p.getValue()); }});
            done.setCellFactory(
               new Callback<TableColumn<File,Boolean>,TableCell<File,Boolean>>(){
                  @Override public TableCell<File,Boolean> call( TableColumn<File,Boolean> p ){
                     return new CheckBoxTableCell<>(); }});
            done.setSortable( true );
            done.setPrefWidth( 40 );
            columns.add( done );
            jpegDir.setOnDragOver(new EventHandler <DragEvent>() {
               @Override public void handle(DragEvent event) {
                  if (event.getGestureSource() != jpegDir ) {
                     event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                  }
                  event.consume();
               }});
            jpegDir.setOnDragDropped(new EventHandler <DragEvent>() {
               @Override public void handle(DragEvent event) {
                  final Dragboard db = event.getDragboard();
                  boolean success = false;
                  if( db.hasFiles()) {
                     jpegDir.setText( db.getFiles().get( 0 ).getPath());
                     success = true;
                  }
                  event.setDropCompleted( success );
                  event.consume();
               }});
            filesVw.setOnDragOver(new EventHandler <DragEvent>() {
               @Override public void handle(DragEvent event) {
                  if( event.getGestureSource() != filesVw && ! jpegDir.getText().isEmpty()) {
                     event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
                  }
                  event.consume();
               }});
            filesVw.setOnDragDropped(new EventHandler <DragEvent>() {
               @Override public void handle(DragEvent event) {
                  final Dragboard db = event.getDragboard();
                  boolean success = false;
                  if( db.hasFiles()) {
                     final List< File > files  = db.getFiles();
                     final File         target = new File( jpegDir.getText());
                     for( final File f : files ) {
                        dones.put( f, new SimpleBooleanProperty( false ));
                     }
                     filesVw.getItems().addAll( files );
                     filesVw.setDisable( true );
                     new Thread(){@Override public void run() {
                        Main.extract(
                           files, target,
                           new Observer(){ @Override public void update( Observable o, final Object file ) {
                              Platform.runLater( new Runnable() { @Override public void run() {
                                 dones.get( file ).setValue( Boolean.TRUE );
                              }});
                           }});
                        Platform.runLater( new Runnable() { @Override public void run() {
                           filesVw.setDisable( false );
                        }});
                     }}.start();
                     success = true;
                  }
                  event.setDropCompleted( success );
                  event.consume();
               }});
            primaryStage.setScene( new Scene( pane ));
            primaryStage.setX( 0 );
            primaryStage.setY( 0 );
            primaryStage.show();
         }
      
         public static void main( String[] args ) {
            launch();
         }
      }
      

      【讨论】:

        【解决方案4】:

        JPedal 的 PDFDecoder API 将帮助您提取单词。

        // Decode the page              
        decodePdf.decodePage(page);
        
        // Create the grouping object to apply grouping to the data
        PdfGroupingAlgorithms currentGrouping = decodePdf.getGroupingObject();
        
        // Bounding box for the whole page
        PdfPageData currentPageData = decodePdf.getPdfPageData();
        int x1 = currentPageData.getMediaBoxX(page);
        int x2 = currentPageData.getMediaBoxWidth(page)+x1;
        int y2 = currentPageData.getMediaBoxX(page);
        int y1 = currentPageData.getMediaBoxHeight(page)-y2;
        
        // Extract words
        List words = currentGrouping.extractTextAsWordlist(x1, y1, x2, y2, page, true, "&:=()!;.,\\/\"\"\'\'");
        

        现在,遍历 PDF 中的单词列表。希望它有效。谢谢!

        【讨论】:

          【解决方案5】:

          试试 jpedal,它会起作用。它可以提取几乎任何类型的对象(图像、文本..)

          jpedal-Java developer library

          【讨论】:

          • THX 很多...但是它可以提取具有特定位置(坐标)的图像吗?
          • 似乎有点困难,因为pdf文件由不同的媒体框组成,这会导致相对位置。
          • 为什么不通过部分键名来获取它们?
          • 扫描成PDF后,文件就像图片一样。我可以根据给定的坐标提取部分“图片”吗?
          猜你喜欢
          • 2012-02-01
          • 2013-12-22
          • 2011-08-22
          • 2019-10-15
          • 1970-01-01
          • 2023-03-05
          • 2011-01-29
          相关资源
          最近更新 更多