Java Unicode字符未从pptx转换为png

Java Unicode字符未从pptx转换为png,java,graphics,fonts,apache-poi,powerpoint,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 XMLSlide

我已经写了一个程序,将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");

   }
}

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

我可以考虑以下几种方法:

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

  • 您可以使用类似的方法将缺少的字符从不同的字体添加到首选字体中(当然需要使用它-请参见上文)。这看起来有点奇怪,但比矩形好

  • 您可以事先检查中的某些字符是否适用于指定的字体,并插入一个新的文本运行元素,为不支持的字符使用另一种字体

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

(用POI 3.10-beta1测试)


您是否尝试过调试它,即在
org.apache.poi.xslf.usermodel.TextFragment.draw()
中设置断点?检查AttributedCharacterIterator,如果它确实包含对字体的引用-有时字体对象被克隆,fontfamily会突然切换回“对话框”类型“垃圾字符”--任何垃圾,或者此字体的默认“不可用”字符?后者表示此字体不包含请求的字符。另一方面,随机垃圾表示您的工作流不支持从一种字符编码到另一种字符编码的必要转换(UTF8?Unicode?)。问题似乎在于POI无法正确转换Unicode字符。它正在将unicode字符转换为方形框。因此,POI使用的编码存在问题。在这里看不到任何与字体相关的内容,这是您在上面的示例中指定的。我不认为POI使用UTF-8编码,否则这些unicode字符会正确转换。有什么想法吗?我已经编写了这个示例代码来测试它是否与UTF-8编码有关!您将看到一行带有“垃圾”字符,使用GE Inspira字体。下一行使用包含拼音的字体并显示在右侧。正如Shervin在你的文章中指出的那样,亚洲字符可能有问题,但低范围字符作为语音可能没有问题。你真的试过使用DejaVu Sans字体和上面的例子吗???kiwiwings-太棒了。所以你的上述计划奏效了。我看到第一行已正确转换。那么这将如何帮助我。在我的情况下,我有一个程序,从文件管理器读取pptx文件,并将其转换为图像,每次一页。这些PPTX文件可能包含unicode、中文、阿拉伯文或任何其他国际字母。当转换为图像时,它们应该保持各自的字母,而不是垃圾或正方形。让我再告诉你一件事——我把所有这些字体都放在一个目录中。当我使用aspose时,我能够指定字体目录,但不知道如何在poi情况下做到这一点。请注意,在我的情况下,我不会从代码中创建新的pptx,但我将从磁盘读取已创建的pptx,然后将其转换为png。1)您可以注册所有字体,因此,POI或更好的java图形渲染器可以找到它。2) 由于您没有提供测试文件,我必须创建自己的测试文件,以向您展示这不是Unicode问题,而是GE Inspira的字体问题。3) 当然,您可以打开和修改文件,因此第三种修改pptx的方法(即替换此字体不支持的字符字体)将是一种解决方法。如果你不能在这段时间内规划这样一个解决方案,我会在假期后考虑(9.9之后)。。。
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();
    }
}