竖排文字生成图片

来自随意问技术百科
跳转至: 导航搜索
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.TextLayout;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.Character.UnicodeBlock;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.commons.lang.StringUtils;

import sun.text.normalizer.UnicodeSet;

public class DrawImageDemo {

public static void main(String[] args) {
String fileName = "STKAITI.TTF";// 楷体
int bold = 0; // 是否加粗
int italic = 0; // 是否斜体
int size = 200;
// String text = "春眠不觉晓,\n处处闻啼鸟。 夜来风雨声,\n花落知多少。";
String text = "I'm a little  bird, want to fly!\n春(眠)不觉晓,\n处处闻啼鸟。

夜来风雨声,\n花落知多少。

测试1234567890数字\nHadoop框架中最核心设计就是:HDFS和MapReduce.\n()《》「」『』【】〔〕〖〗〈〉-…“”‘’";
int rgb = 125; // 颜色
// 设置字体
Font font = getFont(fileName);
font = deriveFont(font, bold, italic, size);
// generate font image
BufferedImage img = CreateFontImgWithGraphics(text, rgb, true, font);
// 图片生成路径
File file = new File("F:\\test.jpg");
try {
ImageIO.write(img, "JPEG", file);
// Iterator iter = ImageIO.getImageWritersByFormatName("JPEG");
// ImageWriter writer = (ImageWriter) iter.next();
// ImageWriteParam iwp = writer.getDefaultWriteParam();
// iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
// iwp.setCompressionQuality(1); // best quality
// FileImageOutputStream output = new FileImageOutputStream(file);
// writer.setOutput(output);
// IIOImage image = new IIOImage(img, null, null);
// writer.write(null, image, iwp);
// writer.dispose();
} catch (IOException e) {
e.printStackTrace();
}
}

private static Font deriveFont(Font font, int bold, int italic, int size) {
int style = Font.PLAIN;
if (bold > 0) {
style = style | Font.BOLD;
}
if (italic > 0) {
style = style | Font.ITALIC;
}
return font.deriveFont(style, size);
}

// 获取字体
private static Font getFont(String fileName) {
File file = new File("C:\\windows\\Fonts\\" + fileName);
InputStream fi = null;
BufferedInputStream fb = null;
Font nf = null;
try {
// 字体文件
fi = new FileInputStream(file);
fb = new BufferedInputStream(fi);
// 生成字体
nf = Font.createFont(Font.TRUETYPE_FONT, fb);

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (FontFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return nf;
}

private static BufferedImage CreateFontImgWithGraphics(String text, int rgb, boolean isVertical, Font font) {

// 字体大小
int fontSize = font.getSize();
// 横排字高、宽比例
float ratio = 1.25f;
// 竖排字高、宽比例
float vertical_ratio = 1.4f;
// 文字图片边框
float border = (float) (fontSize * 0.1);
// 设置每行的固定高度,用于横排
int line_height = Math.round(fontSize * ratio);
// 设置每行的固定宽度度,用于竖排
int line_width = Math.round(fontSize * vertical_ratio);
// 文字
String lines[] = text.split("\n");
String line;
TextLayout layout;
// 计算图片的width,height
BufferedImage tmp = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D gtmp = (Graphics2D) tmp.getGraphics();
// dwh用于根据实际文件来计算图片某一边的长度,dx用于对图片水平方向的空白补齐,dy用于对图片垂直方向的空白补齐
float dwh = 0, dx = 0, dy = 0;
for (int i = 0; i < lines.length; i++) {
line = lines[i];
if (StringUtils.isNotBlank(line)) {
layout = new TextLayout(line, font, gtmp.getFontRenderContext());
dwh = Math.max(layout.getAdvance(), dwh);
}
}
System.out.println("isVertical=" + isVertical + ", dy=" + dy + ", font=" + font.getName());
// 横排文字:width不固定,height固定; 竖排文字:width固定,height不固定
// 文字图片的宽
int width = Math.round((isVertical ? line_width * lines.length : dwh) + 2 * border);
// 文字图片的高
int height = Math.round((isVertical ? dwh : line_height * lines.length) + 2 * border);
// 创建文字图片
BufferedImage image = new BufferedImage(width < 1 ? 1 : width, // width
height < 1 ? 1 : height, // height
BufferedImage.TYPE_4BYTE_ABGR);// RGB mode
// get graphics context
Graphics2D g = (Graphics2D) image.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(new Color(rgb));
g.setFont(font);
// 初始化第一个字的坐标
float xpos = isVertical ? width : border + dx, ypos = dy;
// 每行字
for (int i = 0; i < lines.length; i++) {
line = lines[i];
if (isVertical) {
xpos -= line_width;
ypos = dy;
} else {
xpos = border + dx;
ypos += i == 0 ? fontSize : line_height;
}
// 如果该行为空行,直接跳过
if (StringUtils.isBlank(lines[i])) {
continue;
}
// 每个字符
for (int j = 0; j < line.length(); j++) {
char c = line.charAt(j);
// 用于获取字的该advance
layout = new TextLayout(String.valueOf(c), font, g.getFontRenderContext());
g.scale(1.0, 1.0); // 比例
// 如果是竖排,ascii码在32-126
if (c > 32 && c <= 126 && isVertical) {
g.rotate(Math.PI / 2, xpos + layout.getAdvance() / 2, ypos + layout.getAdvance() / 2);
g.drawString(String.valueOf(c), xpos + layout.getAdvance() / 4, ypos + layout.getAdvance() - (line_width - fontSize) / 2);
g.rotate(-Math.PI / 2, xpos + layout.getAdvance() / 2, ypos + layout.getAdvance() / 2);
} else {
g.drawString(String.valueOf(c), xpos, isVertical ? ypos + layout.getAdvance() : ypos);
}
// System.out.println(c + ", type:" + Character.getType(c) +
// ", asccii:" + (int) c + ", xy:xpos =" + xpos + ",ypos=" +
// (ypos + layout.getAdvance()));

if (isVertical) {
ypos += layout.getAdvance();
} else {
xpos += layout.getAdvance();
}
}
}
g.dispose();
return image;
}