在 Graphics 对象中的屏幕截图上方添加白色矩形 (java)
Add white rectangle above a screenshot in a Graphics object (java)
我有一个方法可以在屏幕截图中添加一些文本。屏幕截图作为 File 对象输入到此方法中,如下所示:
private void modifyScreenshot(File file) throws Exception {
String textToAdd = "Something something";
BufferedImage image = ImageIO.read(file);
Graphics g = image.getGraphics();
此时,通过g.drawString添加文本就很容易了。但是,我希望文本不覆盖任何实际屏幕截图,而是在屏幕截图的白色区域 "above"。
我的意思是,此时,这就是 Graphics 对象保存到文件时的样子:
但是,我希望它看起来像这样,"Some text some text" 是我在代码中指定的字符串。
那么,我怎样才能在可以写入文本的图像上方添加白色矩形?
编辑:请注意,这不仅仅是向图像添加字符串。这涉及 "enlarging" canvas 为字符串设置白色 space,以便字符串不会超过实际图像。
大致思路如下:
BufferedImage image = ImageIO.read(file);
int whiteSpaceHeight = 20;
BufferedImage result = new BufferedImage(image.getWidth(),
image.getHeight()+whiteSpaceHeight, image.getType());
Graphics graphics = result.getGraphics();
graphics.drawImage(image, 0, whiteSpaceHeight, null);
graphics.drawString(textToAdd, 0, whiteSpaceHeight/2);
(编辑:答案已重写 - 详情请参阅历史记录)
示例图像中指示的任务实际上可能有点棘手:即具有 multi-line 文本。但是这里一个简单的解决方案是使用 JLabel
和 CellRendererPane
来渲染文本,因为它也支持 HTML。所以对于像
这样的标题
String title =
"<html><font size=4>This <font color=#FF0000><b>Text</b></font><br>" +
"with line breaks<br>" +
"will be the title</font></html>");
使用换行符和颜色以及专用字体大小,可以获得合适的图像:
这是一个展示如何实现这一点的例子:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.swing.CellRendererPane;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TitleAdder
{
public static void main(String[] args)
{
addTitle("yS2aQ.png", "output.png",
"<html><font size=4>This <font color=#FF0000><b>Text</b></font><br>" +
"with line breaks<br>" +
"will be the title</font></html>");
}
private static void addTitle(
String inputFileName, String outputFileName, String title)
{
try (InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFileName))
{
BufferedImage sourceImage = ImageIO.read(in);
BufferedImage targetImage =
addTitle(sourceImage, title);
ImageIO.write(targetImage, "png", out);
// Show the image, for testing
show(targetImage);
}
catch (IOException e)
{
e.printStackTrace();
}
}
private static BufferedImage addTitle(
BufferedImage sourceImage, String title)
{
JLabel label = new JLabel(title);
label.setBackground(Color.WHITE);
label.setForeground(Color.BLACK);
label.setOpaque(true);
int titleHeight = label.getPreferredSize().height;
int height = sourceImage.getHeight() + titleHeight;
BufferedImage targetImage = new BufferedImage(
sourceImage.getWidth(), height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = targetImage.createGraphics();
SwingUtilities.paintComponent(g, label, new CellRendererPane(),
0, 0, sourceImage.getWidth(), titleHeight);
g.drawImage(sourceImage, 0, titleHeight, null);
g.dispose();
return targetImage;
}
private static void show(final BufferedImage image)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame f = new JFrame();
f.getContentPane().add(new JLabel(new ImageIcon(image)));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
我有一个方法可以在屏幕截图中添加一些文本。屏幕截图作为 File 对象输入到此方法中,如下所示:
private void modifyScreenshot(File file) throws Exception {
String textToAdd = "Something something";
BufferedImage image = ImageIO.read(file);
Graphics g = image.getGraphics();
此时,通过g.drawString添加文本就很容易了。但是,我希望文本不覆盖任何实际屏幕截图,而是在屏幕截图的白色区域 "above"。
我的意思是,此时,这就是 Graphics 对象保存到文件时的样子:
但是,我希望它看起来像这样,"Some text some text" 是我在代码中指定的字符串。
那么,我怎样才能在可以写入文本的图像上方添加白色矩形?
编辑:请注意,这不仅仅是向图像添加字符串。这涉及 "enlarging" canvas 为字符串设置白色 space,以便字符串不会超过实际图像。
大致思路如下:
BufferedImage image = ImageIO.read(file);
int whiteSpaceHeight = 20;
BufferedImage result = new BufferedImage(image.getWidth(),
image.getHeight()+whiteSpaceHeight, image.getType());
Graphics graphics = result.getGraphics();
graphics.drawImage(image, 0, whiteSpaceHeight, null);
graphics.drawString(textToAdd, 0, whiteSpaceHeight/2);
(编辑:答案已重写 - 详情请参阅历史记录)
示例图像中指示的任务实际上可能有点棘手:即具有 multi-line 文本。但是这里一个简单的解决方案是使用 JLabel
和 CellRendererPane
来渲染文本,因为它也支持 HTML。所以对于像
String title =
"<html><font size=4>This <font color=#FF0000><b>Text</b></font><br>" +
"with line breaks<br>" +
"will be the title</font></html>");
使用换行符和颜色以及专用字体大小,可以获得合适的图像:
这是一个展示如何实现这一点的例子:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.swing.CellRendererPane;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TitleAdder
{
public static void main(String[] args)
{
addTitle("yS2aQ.png", "output.png",
"<html><font size=4>This <font color=#FF0000><b>Text</b></font><br>" +
"with line breaks<br>" +
"will be the title</font></html>");
}
private static void addTitle(
String inputFileName, String outputFileName, String title)
{
try (InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFileName))
{
BufferedImage sourceImage = ImageIO.read(in);
BufferedImage targetImage =
addTitle(sourceImage, title);
ImageIO.write(targetImage, "png", out);
// Show the image, for testing
show(targetImage);
}
catch (IOException e)
{
e.printStackTrace();
}
}
private static BufferedImage addTitle(
BufferedImage sourceImage, String title)
{
JLabel label = new JLabel(title);
label.setBackground(Color.WHITE);
label.setForeground(Color.BLACK);
label.setOpaque(true);
int titleHeight = label.getPreferredSize().height;
int height = sourceImage.getHeight() + titleHeight;
BufferedImage targetImage = new BufferedImage(
sourceImage.getWidth(), height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = targetImage.createGraphics();
SwingUtilities.paintComponent(g, label, new CellRendererPane(),
0, 0, sourceImage.getWidth(), titleHeight);
g.drawImage(sourceImage, 0, titleHeight, null);
g.dispose();
return targetImage;
}
private static void show(final BufferedImage image)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame f = new JFrame();
f.getContentPane().add(new JLabel(new ImageIcon(image)));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}