2013-12-20 66 views
0

我剛剛實現了創建PNG圖像,呈現文本文件的內容。在線搜索我發現了一些使用Android的實現,但沒有使用標準Java的多行文本的完整示例,所以認爲這將值得在此發佈我的解決方案。將多行多頁面格式化文本呈現到BufferedImage中(不在Android中)

的要求是:

一個字符串可能任意大小,並且呈現出來與格式正確的段落以適應PNG圖像,分割字符串轉換線和段落正常。如果渲染文檔不適合一個頁面,則生成多個BufferedImage,每個頁面一個。

回答

0

我發現呈現出一個段落,構建在Java文檔中的一些示例代碼,我提出以下幾點:

private static final Font FONT = new Font("Serif", Font.PLAIN, 14); 
private static final float PARAGRAPH_BREAK = 10; 
private static final float MARGIN = 20; 

private Graphics2D setupGraphics(BufferedImage img) { 
    Graphics2D g2d = img.createGraphics(); 
    g2d.setFont(FONT); 
    g2d.fillRect(0, 0, img.getWidth(), img.getHeight()); 
    g2d.setColor(Color.BLACK); 
    return g2d; 
} 

private List<BufferedImage> renderText(String str, int width, int height) { 
    String[] paragraphs = str.split("\n"); 

    List<BufferedImage> images = new ArrayList<>(); 

    BufferedImage img = new BufferedImage(width, 
      height, 
      BufferedImage.TYPE_3BYTE_BGR); 
    images.add(img); 
    Graphics2D g2d = setupGraphics(img); 

    float drawPosY = 0; 

    for (int paragraph=0;paragraph<paragraphs.length;paragraph++) { 

     drawPosY += PARAGRAPH_BREAK; 

     AttributedString attStr = new AttributedString(paragraphs[paragraph]); 
     AttributedCharacterIterator it = attStr.getIterator(); 
     LineBreakMeasurer measurer = new LineBreakMeasurer(it, g2d.getFontRenderContext()); 
     measurer.setPosition(it.getBeginIndex()); 

     while (measurer.getPosition() < it.getEndIndex()) { 
      TextLayout layout = measurer.nextLayout(img.getWidth()-MARGIN*2); 

      if (drawPosY > img.getHeight() - layout.getAscent() - layout.getDescent() - layout.getLeading()) { 
       drawPosY = 0; 
       img = new BufferedImage((int)(
         width, 
         height, 
         BufferedImage.TYPE_3BYTE_BGR); 
       images.add(img); 
       g2d.dispose(); 
       g2d = setupGraphics(img); 
      } 

      drawPosY += layout.getAscent(); 

      layout.draw(g2d, MARGIN, drawPosY); 

      drawPosY += layout.getDescent()+layout.getLeading(); 
     } 
    } 
    g2d.dispose(); 

    return images; 
} 

在我來說,我需要生成PNG在內存中,所以我創造了它,如下所示:

try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { 
     ImageIO.write(output, "png", baos); 
     ret.setImageData(baos.toByteArray()); 
    } catch (IOException ex) { 
     Logger.getLogger(ImageGenerationService.class.getName()).log(Level.SEVERE, null, ex); 
     return null; 
    } 

在本節中幾乎相同的代碼導致的ImageIO寫出來的文件不同的格式(例如,而不是「PNG」「JPG」)或圖像寫入到文件中(使用的FileOutputStream代替ByteArrayOutputStream) 。

我希望這可以幫助其他人解決同樣的問題。

相關問題