2016-11-14 5 views
0

Ich würde gerne über Bibliothek APACHE POI fragen. Ich habe eine .pptx-Datei und mit dem Beispiel, das ich im Internet gefunden habe, habe ich jede Folie in separate Bilder aufgeteilt. Das funktioniert gut, wenn die Folie .png, .jpeg Bilder enthält, aber sobald ich .emf Dateien in der Folie habe, verschwindet dieses Bild. Also möchte ich die gleiche Kopie der Folie haben, aber auch mit der .emf-Datei. Ist das möglich?apache poi ppt zu png emf

Version: Apache POI 3.12

Vielen Dank

+0

Upgrade auf die neueste Version von Apache POI und versuchen Sie es erneut? – Gagravarr

+0

Ich habe es getan, aber ich nehme an, es ist nicht unterstützt diese Funktion – tralalaUlalal

+0

EMF wird derzeit nicht out-of-the-box unterstützt. Sie müssen Ihren eigenen ImageRenderer mithilfe der FreeHep-Bibliothek bereitstellen. siehe [ein Beispiel für die Verwendung von FreeHep] (http://apache-poi.1045710.n5.nabble.com/ImageRender-for-EMF-convert-PPTX-slides-include-EMF-images-into- PNG-td5717773.html) und auf [wie Sie Ihren eigenen ImageRenderer bereitstellen können] (http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/ImageRenderer.java ? view = markup) Ich könnte :) versuchen, eine detaillierte Antwort in Kürze zu kommen – kiwiwings

Antwort

0

Wie in den Kommentaren erwähnt, wird EMF nicht aus der Box unterstützt ... und als FreeHep beschlossen, eine LGPL license haben es unwahrscheinlich ist, dass wir include in our release.

In POI Sie haben grundsätzlich zwei Möglichkeiten einen Renderer eigenes Bild zur Verfügung zu stellen:

  • implementieren und Ihre ImageRenderer Umsetzung im Kontext über setRenderingHint(Drawable.IMAGE_RENDERER, new MyImageRendener()) Graphics2D registrieren. Der Nachteil ist, dass es für alle Bilder aufgerufen wird und Sie die Standardbehandlung für Bitmap/WMF-Bilder
  • verlieren oder eine benutzerdefinierte DrawFactory bereitstellen, die Ihrer eigenen DrawPictureShape Implementierung dient - wie im folgenden Beispiel - die nur auf die EMF umleitet Renderers, wenn nötig
    (bei diesem Beispiel sucht, wird die aktuelle POI ImageRenderer Handhabung nicht flexibel aussehen und stattdessen einen globalen Handler zu haben, könnte es besser sein, einen Handler pro Content-Typen registrieren ...)

Neben der usual POI component habe ich freehep-graphics2d, freehep-graphicsbase,enthalten, freehep-graphicsio-emf und freehep-io.

Das Beispiel ist noch lange nicht beendet, aber ich denke, man zumindest einen Kick-Start erhalten:

package org.apache.poi.xslf; 

import java.awt.Dimension; 
import java.awt.Graphics2D; 
import java.awt.Insets; 
import java.awt.RenderingHints; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Rectangle2D; 
import java.awt.image.BufferedImage; 
import java.io.ByteArrayInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

import javax.imageio.ImageIO; 

import org.apache.poi.sl.draw.DrawFactory; 
import org.apache.poi.sl.draw.DrawPictureShape; 
import org.apache.poi.sl.draw.Drawable; 
import org.apache.poi.sl.draw.ImageRenderer; 
import org.apache.poi.sl.usermodel.PictureData; 
import org.apache.poi.sl.usermodel.PictureData.PictureType; 
import org.apache.poi.sl.usermodel.PictureShape; 
import org.apache.poi.util.POILogFactory; 
import org.apache.poi.util.POILogger; 
import org.apache.poi.xslf.usermodel.XMLSlideShow; 
import org.apache.poi.xslf.usermodel.XSLFPictureShape; 
import org.apache.poi.xslf.usermodel.XSLFSlide; 
import org.freehep.graphicsio.emf.EMFInputStream; 
import org.freehep.graphicsio.emf.EMFRenderer; 
import org.junit.Test; 

public class TestEMFRender { 
    private final static POILogger LOG = POILogFactory.getLogger(TestEMFRender.class); 

    @Test 
    public void render() throws Exception { 
     XMLSlideShow ppt = getDummy(); 

     Dimension pgsize = ppt.getPageSize(); 
     BufferedImage img = new BufferedImage((int)pgsize.getWidth(), (int)pgsize.getHeight(), BufferedImage.TYPE_INT_ARGB); 
     Graphics2D graphics = initGraphicsCtx(img); 

     // draw stuff 
     ppt.getSlides().get(0).draw(graphics); 

     // save the result 
     File outfile = new File("bla.png"); 
     ImageIO.write(img, "PNG", outfile); 

     // cleanup 
     graphics.dispose(); 
     img.flush(); 
     ppt.close(); 
    } 

    static XMLSlideShow getDummy() throws IOException { 
     XMLSlideShow ppt = new XMLSlideShow(); 
     FileInputStream fis = new FileInputStream("kiwilogo.emf"); 
     PictureData pd = ppt.addPicture(fis, PictureType.EMF); 
     fis.close(); 
     XSLFSlide sl = ppt.createSlide(); 
     XSLFPictureShape ps = sl.createPicture(pd); 
     ps.setAnchor(new Rectangle2D.Double(100, 100, 100, 100)); 
     return ppt; 
    } 

    static Graphics2D initGraphicsCtx(BufferedImage img) { 
     Graphics2D graphics = img.createGraphics(); 
     // default rendering options 
     graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
     graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); 
     graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 

     // custom draw factory 
     DrawFactory df = new DrawFactory(){ 
      public DrawPictureShape getDrawable(PictureShape<?,?> shape) { 
       return new DrawPictureShapeEmf(shape); 
      } 
     }; 
     graphics.setRenderingHint(Drawable.DRAW_FACTORY, df); 

     df.fixFonts(graphics); 

     return graphics; 
    } 

    static class DrawPictureShapeEmf extends DrawPictureShape { 
     public DrawPictureShapeEmf(PictureShape<?,?> shape) { 
      super(shape); 
     } 


     @Override 
     public void drawContent(Graphics2D graphics) { 
      PictureData data = getShape().getPictureData(); 
      if(data == null) return; 

      Rectangle2D anchor = getAnchor(graphics, getShape()); 
      Insets insets = getShape().getClipping(); 

      try { 
       String contentType = data.getContentType(); 
       ImageRenderer renderer = 
        PictureType.EMF.contentType.equals(contentType) 
        ? new ImgRenderer() 
        : super.getImageRenderer(graphics, contentType); 

       renderer.loadImage(data.getData(), data.getContentType()); 
       renderer.drawImage(graphics, anchor, insets); 
      } catch (IOException e) { 
       LOG.log(POILogger.ERROR, "image can't be loaded/rendered.", e); 
      } 
     } 

    } 


    static class ImgRenderer implements ImageRenderer { 
     EMFRenderer emfRenderer; 

     public void loadImage(InputStream data, String contentType) throws IOException { 
      emfRenderer = new EMFRenderer(new EMFInputStream(data)); 
     } 

     public void loadImage(byte[] data, String contentType) throws IOException { 
      loadImage(new ByteArrayInputStream(data), contentType); 
     } 

     public Dimension getDimension() { 
      return emfRenderer.getSize(); 
     } 

     public void setAlpha(double alpha) { 
     } 

     public BufferedImage getImage() { 
      return null; 
     } 

     public BufferedImage getImage(Dimension dim) { 
      return null; 
     } 

     public boolean drawImage(Graphics2D ctx, Rectangle2D graphicsBounds) { 
      return drawImage(ctx, graphicsBounds, null); 
     } 

     public boolean drawImage(Graphics2D ctx, Rectangle2D graphicsBounds, Insets clip) { 
      AffineTransform at = ctx.getTransform(); 
      try { 
       Dimension emfDim = emfRenderer.getSize(); 
       // scale output bounds to image bounds 
       ctx.translate(graphicsBounds.getX(), graphicsBounds.getY()); 
       ctx.scale(graphicsBounds.getWidth()/emfDim.getWidth(), graphicsBounds.getHeight()/emfDim.getHeight()); 

       // TODO: handle clipping 

       emfRenderer.paint(ctx); 

       return true; 
      } catch (RuntimeException e) { 
       // TODO: logging 
       return false; 
      } finally { 
       ctx.setTransform(at); 
      } 
     } 

    } 
} 
+0

Vielen Dank. aber ist diese lösung möglich? Mit der Funktion ppt.getPictureData() habe ich alle Bilder in Präsentation bekommen und dann finde ich nur Bild welche ha .emf Erweiterung. Ich konvertiere es in Svg mit Freehep und dann von Svg nach JPG, aber jetzt muss ich alte .emf durch neue .jpg mit Funktion picture.setData (newImageStream) ersetzen, aber ich bin mir nicht sicher, ob das funktioniert – tralalaUlalal

+0

Also in Ihrem neuen Problem Sie wollen EMF Bilder mit JPG ersetzen, oder? Also passen Sie einfach meinen Ansatz an, um JPGs von FreeHeps EMFRenderer zu erhalten und ändern Sie das Byte UND den Inhaltstyp - ich denke, Sie müssen alle Folien durchlaufen und die Referenzen dort auch ändern. Wenn das was du willst, dann öffne eine neue Frage und ich könnte den Code dazu übernehmen ... – kiwiwings

+0

Ja ich habs jetzt :) ... Aber das Problem in der Version apache po 3.15 ist, dass nach dieser Konvertierung ist funktioniert nicht Umwandlung von PPT -> Bilder in Bildern sind immer noch Dateien fehlen, aber mit Version 3.13 funktioniert alles OK :) ..Also danke für deine Zeit :) – tralalaUlalal