有没有任何Java库可以将文本内容转换为图像文件?我只知道ImageMagick(在这种情况下是JMagick),但我不想安装任何外部二进制文件(我的应用程序将部署为Tomcat服务器上的.war文件,因此除了Java之外,我不想有任何其他依赖项)。
例如,从字符串“Hello”中,我想生成这个简单的图像:
例如,从字符串“Hello”中,我想生成这个简单的图像:
Graphics 2D API应该能够实现您所需的功能。它还具有一些复杂的文本处理能力。
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class TextToGraphics {
public static void main(String[] args) {
String text = "Hello";
/*
Because font metrics is based on a graphics context, we need to create
a small, temporary image so we can ascertain the width and height
of the final image
*/
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
Font font = new Font("Arial", Font.PLAIN, 48);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
int width = fm.stringWidth(text);
int height = fm.getHeight();
g2d.dispose();
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
try {
ImageIO.write(img, "png", new File("Text.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
请查看编写/保存图像。
警告:我使用这个工具生成了9万个PNG图像,结果发现它们可以在IE中查看,但无法在Chrome版本70.0.3538.77中查看。
上述代码对我来说运行正常(我将文本颜色更改为WHITE
,以便在Chrome中查看)。
我在Mac OS Mojave 10.14上使用Chrome 70.0.3538.77和Java 10.0.2。生成的图像大小为4778x2411像素...
在IE浏览器中是黑底白字,但在Chrome浏览器中是黑底黑字。尽管我将背景设置为白色。
所以你告诉我,在不同的浏览器上会以不同的方式显示透明PNG,因为浏览器使用不同的默认背景...你为什么会感到惊讶呢?
最初的解决方案故意使用了基于透明度的图像。这可以通过创建图像时使用BufferedImage.TYPE_INT_ARGB
来证明,它应用了基于Alpha(A
)的RGB
颜色模型。
这是出乎意料的,因为有g2d.setBackground(Color.white)。
实际上,如果您理解setBackground
的实际作用及其用法,这完全是预期的。
来自JavaDocs的说明:
设置Graphics2D上下文的背景颜色。背景颜色用于清除区域。当为组件构建Graphics2D时,背景颜色从组件继承。在Graphics2D上下文中设置背景颜色仅影响随后的clearRect调用,而不影响组件的背景颜色。要更改组件的背景,请使用组件的适当方法。img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
g2d = img.createGraphics();
//...
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
try {
ImageIO.write(img, "png", new File("Text.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
Font font = new Font("Serif", Font.PLAIN, 48);
FontRenderContext frc = g2.getFontRenderContext();
GlyphVector gv = font.createGlyphVector(frc, "JavaFX");
int x = 100;
int y = 100;
for (int i = 0; i < gv.getNumGlyphs(); i++) {
Shape glyph = gv.getGlyphOutline(i);
Rectangle bounds = glyph.getBounds();
g2.translate(x - bounds.x, y - bounds.y);
g2.fill(glyph);
g2.translate(bounds.x - x, bounds.y - y);
x += bounds.width;
}
上述代码使用了Serif字体,创建了一个包含字符串“JavaFX”的GlyphVector对象,并在屏幕上绘制出来。通过循环处理GlyphVector中的每个字形,我们将其填充到Graphics2D对象中。希望这篇文章对您有所帮助! - MadProgrammer不需要任何外部库,完成以下操作:
编辑-修复链接
考虑以下代码片段:
public static final HashMap<RenderingHints.Key, Object> RenderingProperties = new HashMap<>();
static{
RenderingProperties.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
RenderingProperties.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
RenderingProperties.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
}
public static BufferedImage textToImage(String Text, Font f, float Size){
//Derives font to new specified size, can be removed if not necessary.
f = f.deriveFont(Size);
FontRenderContext frc = new FontRenderContext(null, true, true);
//Calculate size of buffered image.
LineMetrics lm = f.getLineMetrics(Text, frc);
Rectangle2D r2d = f.getStringBounds(Text, frc);
BufferedImage img = new BufferedImage((int)Math.ceil(r2d.getWidth()), (int)Math.ceil(r2d.getHeight()), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHints(RenderingProperties);
g2d.setBackground(Color.WHITE);
g2d.setColor(Color.BLACK);
g2d.clearRect(0, 0, img.getWidth(), img.getHeight());
g2d.setFont(f);
g2d.drawString(Text, 0, lm.getAscent());
g2d.dispose();
return img;
}
使用Java Graphics API,基于渲染到BufferedImage上的字体创建图像。
演示# 对于多行文本 #
将文件作为参数传递给程序
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class TextToGraphics {
public static void main(String[] args){
System.out.println(args[0]);
File file = new File(args[0]);
try{
BufferedReader br = new BufferedReader(new FileReader(file));
StringBuilder sb = new StringBuilder();
String line;
while((line = br.readLine())!=null){
sb.append(line).append("\n");
}
convert(sb.toString(),args[0]+"_img");
System.out.println("Done.");
}
catch(FileNotFoundException e){
e.printStackTrace();
}
}
public static void convert(String text, String img_name) {
String[] text_array = text.split("[\n]");
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
Font font = new Font("Consolas", Font.BOLD, 12);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
int width = fm.stringWidth(getLongestLine(text_array));
int lines = getLineCount(text);
int height = fm.getHeight() * (lines + 4);
g2d.dispose();
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
for (int i = 1; i <= lines; ++i) {
g2d.drawString(text_array[i - 1], 0, fm.getAscent() * i);
}
g2d.dispose();
try {
String img_path = System.getProperty("user.dir") + "/" + img_name + ".png";
ImageIO.write(img, "png", new File(img_path));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static int getLineCount(String text) {
return text.split("[\n]").length;
}
private static String getLongestLine(String[] arr) {
String max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (max.length() < arr[i].length()) {
max = arr[i];
}
}
return max;
}
}
png
格式。import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.io.File;
import javax.imageio.ImageIO;
class ImageWriteEx extends JPanel{
public void paint(Graphics g){
Image img = createImageWithText();
g.drawImage(img, 20, 20, this);
}
private static BufferedImage createImageWithText(){
BufferedImage bufferedImage = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
Graphics g = bufferedImage.getGraphics();
g.drawString("www.stackoverflow.com", 20, 20);
g.drawString("www.google.com", 20, 40);
g.drawString("www.facebook.com", 20, 60);
g.drawString("www.youtube.com", 20, 80);
g.drawString("www.oracle.com", 20, 1000);
return bufferedImage;
}
public static void main(String[] args){
try{
BufferedImage bi = createImageWithText();
File outputfile = new File("save.png");
ImageIO.write(bi, "png", outputfile);
} catch(Exception e){
e.printStackTrace();
}
JFrame frame = new JFrame();
frame.getContentPane().add(new ImageWriteEx());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300,300);
frame.setVisible(true);
}
}
ImageWrite
? - yshahakImageWriteEx
(刚刚定义的类)。我已经修正了。 - Martin Carpenter如果有人想要多行文本图像,我制作了一些并用以下方式显示:
new ImageIcon(*here the image*)
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
public class TextImage
{
public static BufferedImage make(String...textrows)
{
BufferedImage helperImg = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = helperImg.createGraphics();
Font font = *here some font*;
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
String longestText = "";
for(String row: textrows)
{
if(row.length()>longestText.length())
{
longestText = row;
}
}
int width = fm.stringWidth(longestText);
int height = fm.getHeight()*textrows.length;
g2d.dispose();
BufferedImage finalImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
g2d = finalImg.createGraphics();
g2d.setColor(*here some Color*);
g2d.fillRect(0, 0, width, height);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2d.setFont(font);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
int y = fm.getAscent();
for(String row: textrows)
{
g2d.drawString(row, 0, y);
y += fm.getHeight();
}
g2d.dispose();
return finalImg;
}
}
GlyphVector
的示例,如文本形状图像和Unicode棋盘。以及使用标签包装文本的示例,如此处。 - Andrew Thompson