Unicode字符未从pptx转换为png

时间:2013-08-28 21:09:33

标签: java graphics fonts apache-poi powerpoint

我编写了一个将PPTX转换为PNG的程序。所有的转换都很好,唯一的问题是PPTX文件中有UNICODE字符 - 它将其转换为垃圾字符。这是代码。我试图添加字体,但没有帮助。这就是PPTX包含的内容 - “ /ˌinəvāSHən/ ”。它将字母i,n,v,a,S,H,n转换为精细但不是其他字母。

    FileInputStream is = new FileInputStream(strTempPath);
    XMLSlideShow pptx = new XMLSlideShow(is);
    is.close();
    double zoom = 2; // magnify it by 2
    AffineTransform at = new AffineTransform();
    at.setToScale(zoom, zoom);
    Dimension pgsize = pptx.getPageSize();             
    XSLFSlide[] slide = pptx.getSlides();

    }              
    // BufferedImage img = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_INT_RGB);
    BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_RGB);
    Graphics2D graphics = img.createGraphics();
    //graphics.setTransform(at);                
    graphics.setPaint(Color.white);
    graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
    slide[iPageNo].draw(graphics);             
    // FileOutputStream output = new ByteArrayOutputStream("C:/Temp/aspose/word/slide-" + (10 + 1) + ".png");        
    output = new ByteArrayOutputStream();
    javax.imageio.ImageIO.write(img, "png", output);

这就是我尝试添加字体但仍未转换的方式。

        Font customFont = Font.createFont(Font.TRUETYPE_FONT, new File("/usr/share/fonts/GEInspRg.ttf")).deriveFont(12f);
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        //register the font
        ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, new File("/usr/share/fonts/GEInspRg.ttf")));
        graphics.setFont(customFont);

这是我的代码:原始问题中也给出了:我的测试PPTX包含了这个词 - /ˌinəvāSHən/以及其他英文字母。

package foo;

import java.awt.Dimension; 
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;

public class PPTXToPNG {

public static void main(String[] args) throws Exception {

    FileInputStream is = new FileInputStream("C:/Temp/PPTXToImage/unicode_test.pptx");      

    XMLSlideShow ppt = new XMLSlideShow(is);
    is.close();
    double zoom = 2;
    AffineTransform at = new AffineTransform();
    at.setToScale(zoom, zoom);
    Dimension pgsize = ppt.getPageSize();
    XSLFSlide[] slide = ppt.getSlides();

    BufferedImage img = new BufferedImage((int)Math.ceil(pgsize.width*zoom),
            (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_INT_RGB);
    Graphics2D graphics = img.createGraphics();

    graphics.setTransform(at);
    graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));

    // Draw first page in the PPTX. First page starts at 0 position
    slide[0].draw(graphics);

    FileOutputStream out = new FileOutputStream("C:/Temp/PPTXToImage/ConvertedSlide.png");  
    javax.imageio.ImageIO.write(img, "png", out);
    out.close();
    System.out.println("DONE");

   }
}

1 个答案:

答案 0 :(得分:2)

正如Jongware上面指出的那样,字符不能以“GE Inspira”字体显示,正如您在下面的示例程序中看到的那样 - 所以你需要一些/ˌinəvāSHən/(创新)来到那;)

我可以考虑几种方法:

  • 我不确定用于设置代码的graphics.setFont(customFont);是否只是一个测试,但通常POI将使用(并设置)文档中指定的字体。因此最简单的方法是用支持语音的字体替换原始文档中的字体(有关合适的字体,请参阅wikipedia unicode article)。顺便说一句。如果您尝试在Libre Office中使用该字体并插入这些语音,您也将获得“垃圾”字符。

  • 您可以使用类似fontforge的内容将缺少的字符添加到您喜欢的字体中,使用不同的字体(但当然需要使用它 - 见上文)。它看起来有点奇怪,但比矩形更好......

  • 您可以事先检查指定字体的text-runs are supported中的某些字符,并为不支持的字符插入带有替代字体的新文本运行元素

  • 我知道PDF正在进行某种字体替换,如果找不到字体(甚至字符???),我还没有找到类似java的机制。简短搜索...也许还有这样的解决方案......

(用POI 3.10-beta1测试)

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.*;
import org.apache.poi.xslf.usermodel.*;

public class UnicodePPT {
    public static void main(String[] args) throws Exception {
        // create a sample pptx
        XMLSlideShow ss = new XMLSlideShow();
        Dimension pgsize = ss.getPageSize();             

        XSLFSlide slide = ss.createSlide();
        XSLFTextBox tb = slide.createTextBox();
        tb.setShapeType(XSLFShapeType.HEART);
        int shapeSize = 150;
        tb.setAnchor(new Rectangle2D.Double(pgsize.getWidth()/2-shapeSize/2, pgsize.getHeight()/2-shapeSize/2, shapeSize, shapeSize));
        tb.setLineWidth(2);
        tb.setLineColor(Color.BLACK);
        XSLFTextParagraph par = tb.addNewTextParagraph();
        tb.setVerticalAlignment(VerticalAlignment.DISTRIBUTED);
        par.setTextAlign(TextAlign.CENTER);
        XSLFTextRun run = par.addNewTextRun();
        run.setText("/\u02CCin\u0259\u02C8v\u0101SH\u0259n/");
        run.setFontFamily("DejaVu Serif");
        run.setFontSize(12);
        par.addLineBreak();
        run = par.addNewTextRun();
        run.setText("/\u02CCin\u0259\u02C8v\u0101SH\u0259n/");
        run.setFontFamily("GE Inspira");
        run.setFontSize(12);

        // set the font
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        InputStream is = new FileInputStream("src/main/resources/GEInspRg.TTF");
        Font font = Font.createFont(Font.TRUETYPE_FONT, is);
        is.close();
        ge.registerFont(font);  

        is = new FileInputStream("src/main/resources/DejaVuSerif.ttf");
        font = Font.createFont(Font.TRUETYPE_FONT, is);
        is.close();
        ge.registerFont(font);  

        // render it
        double zoom = 2; // magnify it by 2
        AffineTransform at = new AffineTransform();
        at.setToScale(zoom, zoom);

        BufferedImage img = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = img.createGraphics();
        graphics.setTransform(at);                
        graphics.setPaint(Color.white);
        graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
        slide.draw(graphics);             

        FileOutputStream fos = new FileOutputStream("unicodeppt.png");
        javax.imageio.ImageIO.write(img, "png", fos);       
        fos.close();
    }
}