如何为文本添加轮廓,然后将其添加到图像的中心?
How to add an outline to a text and then add it to the image's center?
我目前有一种方法可以根据模板、两个单独的头像和文本生成图像,然后 return 将其作为字节数组。
根据提供的 chance
整数的大小,显示的文本具有不同的颜色。
由于字体可以具有模板图像所具有的颜色,是否有可能(没有双关语意)文本在生成的图像上不可见,这就是我想应用黑色轮廓的原因显示的字体。
我已经找到 this answer here 虽然它实际上给出了两个示例,但它是否比实际帮助我更让我困惑。
first example有很多我自己不需要的步骤,我不确定哪些可以放弃,哪些是必须保留的。
我也不确定我将如何在此处将文本居中应用我的逻辑,因为该示例似乎应用了字体的轮廓并分别填充每个字母,这在我的情况下会非常烦人,而且不能保证每个字母都相同时间,因为文本可以是 #%
、##%
或 ###%
.
second example 似乎更多的是关于在 JPanel 中的使用?或者换句话说,我不确定这段代码是否也可以单独应用于图像,或者是否需要修改才能仅处理图像。
我基本上需要知道使用 fontColor
创建字体需要什么方法,为其添加黑色轮廓,然后在 returning 之前将其放置在图像本身的中心它作为一个字节数组。
这是我目前用于上下文的代码。
private final OkHttpClient CLIENT = new OkHttpClient();
private BufferedImage getAvatar(String url) throws IOException{
URL url = new URL(url);
URLConnection connection = url.openConnection();
connection.setRequestProperty("User-Agent", "ImageRenderer");
connection.connect();
return ImageIO.read(connection.getInputStream());
}
public byte[] getChance(String url1, String url2, int chance){
try{
BufferedImage template = ImageIO.read(new File("img/chance.png"));
BufferedImage avatar1 = getAvatar(url1);
BufferedImage avatar2 = getAvatar(url2);
// Create new BufferedImage with the template's sizes.
BufferedImage background = new BufferedImage(template.getWidth(), template.getHeight(), template.getType());
Graphics2D img = background.createGraphics();
Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 80);
img.setFont(font);
Color fontColor;
if(chance <= 100 && chance > 74){
fontColor = Color.GREEN;
}else
if(chance <= 74 && chance > 49){
fontColor = Color.ORANGE;
}else
if(chance <= 49 && chance > 24){
fontColor = Color.RED;
}else{
fontColor = Color.BLACK;
}
String text = chance + "%";
img.setColor(fontColor);
// Set the avatars followed by the template.
img.drawImage(avatar1, 0, 0, 320, 320, null);
img.drawImage(avatar2, 640, 0, 320, 320, null);
img.drawImage(template, 0, 0, null);
// Get the image's width and height
int imgWidth = template.getWidth();
int imgHeight = template.getHeight();
// Set X and Y position for the text to be centered.
int textX = (imgWidth / 2) - (img.getFontMetrics().stringWidth(text) / 2);
int textY = (imgHeight / 2) - 40;
// Draw the actual String
img.drawString(text, textX, textY);
img.dispose();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.setUseCache(false);
ImageIO.write(background, "png", baos);
return baos.toByteArray();
}catch(IOException ex){
return null;
}
}
找到解决方案。
第二个示例似乎是可以使用的,我设法让这个设置为我工作:
private final OkHttpClient CLIENT = new OkHttpClient();
private BufferedImage getAvatar(String url) throws IOException{
URL url = new URL(url);
URLConnection connection = url.openConnection();
connection.setRequestProperty("User-Agent", "ImageRenderer");
connection.connect();
return ImageIO.read(connection.getInputStream());
}
public byte[] getChance(String url1, String url2, int chance){
try{
BufferedImage template = ImageIO.read(new File("img/chance.png"));
BufferedImage avatar1 = getAvatar(url1);
BufferedImage avatar2 = getAvatar(url2);
// Create new BufferedImage with the template's sizes.
BufferedImage background = new BufferedImage(template.getWidth(), template.getHeight(), template.getType());
Graphics2D img = background.createGraphics();
Color outlineColor = Color.BLACK;
Color fontColor;
if(chance <= 100 && chance > 74){
fontColor = Color.GREEN;
}else
if(chance <= 74 && chance > 49){
fontColor = Color.ORANGE;
}else
if(chance <= 49 && chance > 24){
fontColor = Color.RED;
}else{
fontColor = Color.BLACK;
}
// Set the avatars followed by the template.
img.drawImage(avatar1, 0, 0, 320, 320, null);
img.drawImage(avatar2, 640, 0, 320, 320, null);
img.drawImage(template, 0, 0, null);
Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 80);
img.setColor(fontColor);
img.setFont(font);
String text = chance + "%";
img.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
img.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
FontRenderContext context = img.getFontRenderContext();
// Set X and Y position for the text to be centred.
int textX = (imgWidth / 2) - (img.getFontMetrics(font).stringWidth(text) / 2);
int textY = (imgHeight / 2) + 40;
// Draw the actual String
img.drawString(text, textX, textY);
// Get TextLayout and AffineTransform
TextLayout layout = new TextLayout(text, font, context);
AffineTransform transform = img.getTransform();
// Create the Shape of the outline
Shape outline = layout.getOutline(null);
// Move position
transform.translate(textX, textY);
// Apply the shape
img.transform(transform);
img.setColor(outlineColor);
img.draw(outline);
img.setClip(outline);
img.dispose();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.setUseCache(false);
ImageIO.write(background, "png", baos);
return baos.toByteArray();
}catch(IOException ex){
return null;
}
}
我目前有一种方法可以根据模板、两个单独的头像和文本生成图像,然后 return 将其作为字节数组。
根据提供的 chance
整数的大小,显示的文本具有不同的颜色。
由于字体可以具有模板图像所具有的颜色,是否有可能(没有双关语意)文本在生成的图像上不可见,这就是我想应用黑色轮廓的原因显示的字体。
我已经找到 this answer here 虽然它实际上给出了两个示例,但它是否比实际帮助我更让我困惑。
first example有很多我自己不需要的步骤,我不确定哪些可以放弃,哪些是必须保留的。
我也不确定我将如何在此处将文本居中应用我的逻辑,因为该示例似乎应用了字体的轮廓并分别填充每个字母,这在我的情况下会非常烦人,而且不能保证每个字母都相同时间,因为文本可以是 #%
、##%
或 ###%
.
second example 似乎更多的是关于在 JPanel 中的使用?或者换句话说,我不确定这段代码是否也可以单独应用于图像,或者是否需要修改才能仅处理图像。
我基本上需要知道使用 fontColor
创建字体需要什么方法,为其添加黑色轮廓,然后在 returning 之前将其放置在图像本身的中心它作为一个字节数组。
这是我目前用于上下文的代码。
private final OkHttpClient CLIENT = new OkHttpClient();
private BufferedImage getAvatar(String url) throws IOException{
URL url = new URL(url);
URLConnection connection = url.openConnection();
connection.setRequestProperty("User-Agent", "ImageRenderer");
connection.connect();
return ImageIO.read(connection.getInputStream());
}
public byte[] getChance(String url1, String url2, int chance){
try{
BufferedImage template = ImageIO.read(new File("img/chance.png"));
BufferedImage avatar1 = getAvatar(url1);
BufferedImage avatar2 = getAvatar(url2);
// Create new BufferedImage with the template's sizes.
BufferedImage background = new BufferedImage(template.getWidth(), template.getHeight(), template.getType());
Graphics2D img = background.createGraphics();
Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 80);
img.setFont(font);
Color fontColor;
if(chance <= 100 && chance > 74){
fontColor = Color.GREEN;
}else
if(chance <= 74 && chance > 49){
fontColor = Color.ORANGE;
}else
if(chance <= 49 && chance > 24){
fontColor = Color.RED;
}else{
fontColor = Color.BLACK;
}
String text = chance + "%";
img.setColor(fontColor);
// Set the avatars followed by the template.
img.drawImage(avatar1, 0, 0, 320, 320, null);
img.drawImage(avatar2, 640, 0, 320, 320, null);
img.drawImage(template, 0, 0, null);
// Get the image's width and height
int imgWidth = template.getWidth();
int imgHeight = template.getHeight();
// Set X and Y position for the text to be centered.
int textX = (imgWidth / 2) - (img.getFontMetrics().stringWidth(text) / 2);
int textY = (imgHeight / 2) - 40;
// Draw the actual String
img.drawString(text, textX, textY);
img.dispose();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.setUseCache(false);
ImageIO.write(background, "png", baos);
return baos.toByteArray();
}catch(IOException ex){
return null;
}
}
找到解决方案。
第二个示例似乎是可以使用的,我设法让这个设置为我工作:
private final OkHttpClient CLIENT = new OkHttpClient();
private BufferedImage getAvatar(String url) throws IOException{
URL url = new URL(url);
URLConnection connection = url.openConnection();
connection.setRequestProperty("User-Agent", "ImageRenderer");
connection.connect();
return ImageIO.read(connection.getInputStream());
}
public byte[] getChance(String url1, String url2, int chance){
try{
BufferedImage template = ImageIO.read(new File("img/chance.png"));
BufferedImage avatar1 = getAvatar(url1);
BufferedImage avatar2 = getAvatar(url2);
// Create new BufferedImage with the template's sizes.
BufferedImage background = new BufferedImage(template.getWidth(), template.getHeight(), template.getType());
Graphics2D img = background.createGraphics();
Color outlineColor = Color.BLACK;
Color fontColor;
if(chance <= 100 && chance > 74){
fontColor = Color.GREEN;
}else
if(chance <= 74 && chance > 49){
fontColor = Color.ORANGE;
}else
if(chance <= 49 && chance > 24){
fontColor = Color.RED;
}else{
fontColor = Color.BLACK;
}
// Set the avatars followed by the template.
img.drawImage(avatar1, 0, 0, 320, 320, null);
img.drawImage(avatar2, 640, 0, 320, 320, null);
img.drawImage(template, 0, 0, null);
Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 80);
img.setColor(fontColor);
img.setFont(font);
String text = chance + "%";
img.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
img.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
FontRenderContext context = img.getFontRenderContext();
// Set X and Y position for the text to be centred.
int textX = (imgWidth / 2) - (img.getFontMetrics(font).stringWidth(text) / 2);
int textY = (imgHeight / 2) + 40;
// Draw the actual String
img.drawString(text, textX, textY);
// Get TextLayout and AffineTransform
TextLayout layout = new TextLayout(text, font, context);
AffineTransform transform = img.getTransform();
// Create the Shape of the outline
Shape outline = layout.getOutline(null);
// Move position
transform.translate(textX, textY);
// Apply the shape
img.transform(transform);
img.setColor(outlineColor);
img.draw(outline);
img.setClip(outline);
img.dispose();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.setUseCache(false);
ImageIO.write(background, "png", baos);
return baos.toByteArray();
}catch(IOException ex){
return null;
}
}