0

我编写了一个将 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");

   }
}
4

1 回答 1

2

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

我可以想到几种方法:

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

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

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

  • 我知道 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();
    }
}
于 2013-08-31T15:34:40.660 回答