java uses Graphics2D to draw and drawing mode
- 2021-12-12 04:28:48
- OfStack
1. The author encountered the need to generate shared posters in the development process
Need the back-end to dynamically generate the sharing diagram (finally, the front-end realizes it itself, haha); Record some problems and solutions encountered in the process.
2. Graphics2D Common API
First get the Graphics2D instance
BufferedImage bi = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = bi.createGraphics();
// Turn on anti-aliasing
RenderingHints renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// Use high quality compression
renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHints(renderingHints);
1. graphics. drawImage (). Add a picture to the canvas. The parameters are position and width and height of the picture
BufferedImage bgmImage = ImageIO.read(new ByteArrayInputStream(FileUtils.readFileToByteArray(new File("filePath"))));
graphics.drawImage(bgmImage, x, y, width, height, null);
2. graphics. drawString (), add text to the canvas (word wrap needs to be implemented by yourself)
graphics.setFont(new Font("PingFangSC-Regular", Font.PLAIN, 24));
graphics.setColor(Color.WHITE);
graphics.drawString(title, x, y);
3. graphics. fillRoundRect (), rounded rectangle with background color (used to draw background color for words, pay attention to drawing rectangular background first, and then drawing words), and the last two parameters are to set rounded radian
// Background color rectangle
graphics.setColor(new Color(254, 68, 82));
graphics.fillRoundRect(x, y, width, height, 4, 4);
3. Talent
1. The automatic line wrap of painting text just mentioned needs to be realized by itself. Here, I will briefly talk about the realization principle; In fact, according to the set line width and the string to be drawn, do a calculation. The line width of each text can be obtained, so that you can calculate how many words can be displayed in each line, and then you can calculate how many lines are displayed in total. Finally, just call the graphics. drawString () method to draw it; The following is the core code for line wrapping:
private static int drawStringAutoLineFeed(Graphics g, String strContent, int rowWidth, int x, int y) {
String[] split = strContent.split("\n");
int total = 0;
for (String str : split) {
int height = drawStringAutoLine(g, str, rowWidth, x, y);
total += height;
y += height;
}
return total;
}
/**
* Wrap lines according to the specified width
*
* @param g
* @param rowWidth
* @param strContent
* @param x
* @param y
*/
private static int drawStringAutoLine(Graphics g, String strContent, int rowWidth, int x, int y) {
// Get String Total width of characters
int strWidth = getStringLength(g, strContent);
// Get character height
int strHeight = getStringHeight(g);
// Total number of strings
int rows = 0;
if (strWidth > rowWidth) {
int rowStrNum = getRowStrNum(strContent.length(), rowWidth, strWidth);
rows = getRows(strWidth, rowWidth);
String temp = "";
for (int i = 0; i < rows; i++) {
// Object for each row String
if (i == rows - 1) {
// Finally 1 Row
temp = strContent.substring(i * rowStrNum, strContent.length());
} else {
temp = strContent.substring(i * rowStrNum, i * rowStrNum + rowStrNum);
}
if (i > 0) {
// No. 1 1 Line does not need to increase character height, and every subsequent 1 When a line wraps, it needs to increase the character height
y = y + strHeight;
}
g.drawString(temp, x, y);
}
} else {
// Direct rendering
g.drawString(strContent, x, y);
}
return strHeight * rows;
}
private static int getDrawStringAutoLineHeight(Graphics g, String strContent, int rowWidth) {
String[] split = strContent.split("\n");
int height = 0;
for (String str : split) {
// Get String Total width of characters
int strWidth = getStringLength(g, str);
// Get character height
height += getStringHeight(g) * getRows(strWidth, rowWidth);
}
return height;
}
private static int getStringLength(Graphics g, String str) {
char[] strChar = str.toCharArray();
return g.getFontMetrics().charsWidth(strChar, 0, str.length());
}
// Every 1 Number of line characters
private static int getRowStrNum(int strNum, int rowWidth, int strWidth) {
int rowsNum = 0;
rowsNum = (rowWidth * strNum) / strWidth;
return rowsNum;
}
// Character lines
private static int getRows(int strWidth, int rowWidth) {
int rows = 0;
if (strWidth % rowWidth > 0) {
rows = strWidth / rowWidth + 1;
} else {
rows = strWidth / rowWidth;
}
return rows;
}
// Character height
private static int getStringHeight(Graphics g) {
return g.getFontMetrics().getHeight();
}
Usage:
graphics.setFont(new Font("PingFangSC-Regular", Font.PLAIN, 12));
graphics.setColor(Color.GRAY);
drawStringAutoLineFeed(graphics, strContent, rowWidth, x, y);
4. Output pictures
1. Output picture byte array
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(bi, "jpg", outputStream);
return outputStream.toByteArray();
2. Output picture files directly
ImageIO.write(bi, "jpg", new File("outFilePath"));
STEP 5 Summarize
1. Simple scenes with fixed size and style pictures are better
2. The debugging process is very disgusting, and pictures are constantly generated to see the effect
3. The recommendation of more responsible style makes the front-end html2image, which has been realized by my front-end colleagues, and the effect is much better than the back-end drawing!