java 使用Graphics2D在图片上写字
作者:咸鱼太咸
使用Graphics2D在图片上写字
首先jsp页面:src是一个方法地址
然后在Controller如下:写一个生成方法,用流进行读写
生成方法,(关键):
注意:这种方法可行,但是需要计算文字的位置,感觉不太灵活,如果谁有更好的方法请分享一下。
Graphics2D 的使用
1、Graphics2D和Graphics的区别
此 Graphics2D 类扩展Graphics 类,以提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制。它是用于在Java(tm) 平台上呈现二维形状、文本和图像的基础类。
tips:总而言之Graphics2D是Graphics的加强版,增强了一些高级操作。
2、setRenderingHint的具体用处
为呈现算法设置单个首选项的值。提示类别包括对呈现过程中的呈现质量和总时间/质量折衷的控制。
tips:对呈现图像效果处理方式进行设置,例如抗锯齿、颜色、差值等各种效果的处理算法。(我现在主要觉得抗锯齿有用,以后会有不同的感受吧。)下面是两个对比图。
未开启抗锯齿
开启抗锯齿
下面是代码实现:
BufferedImage image = new BufferedImage(260, 80, BufferedImage.TYPE_INT_BGR); //获取Graphics2D对象 Graphics2D graphics = image.createGraphics(); //开启文字抗锯齿 graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); //设置字体 Font font = new Font("Algerian", Font.ITALIC, 40); graphics.setFont(font); //向画板上写字 graphics.drawString("This is test!", 10, 60); graphics.dispose();
3、Stroke的使用方法
描绘一个 Shape 如同使用一支具有适当大小和形状的画笔描绘其轮廓。
tips:相当于画笔头,用来定义画出来的线条的特征;通过设置不同的参数来表现出各种不同的线条类型。更多详细介绍可以观看BasicStroke的用法这篇文章,里面有详细叙述。
下面是我自己写的一个小例子(指定背景图,并画一个树):
package com.msw.test; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Polygon; import java.awt.RenderingHints; import java.awt.Stroke; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import javax.imageio.ImageIO; public class MyTest { public static void main(String[] args) throws IOException { BufferedImage image = new BufferedImage(400, 500, BufferedImage.TYPE_INT_BGR); BufferedImage image2 = ImageIO.read(new FileInputStream(new File("F:\\2.jpg"))); // 获取Graphics2D对象 Graphics2D graphics = image.createGraphics(); graphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); //把image2设置为背景图片 graphics.drawImage(image2, 0, 0, 400, 500,null); // 设置画笔 Stroke stroke = new BasicStroke(5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); graphics.setStroke(stroke); // 设置颜色--绿色 graphics.setColor(Color.GREEN); //画树 graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Polygon polygon = new Polygon(); polygon.addPoint(200, 100); polygon.addPoint(180, 150); polygon.addPoint(220, 150); graphics.draw(polygon); polygon.reset(); polygon.addPoint(200, 150); polygon.addPoint(160, 200); polygon.addPoint(240, 200); graphics.draw(polygon); polygon.reset(); polygon.addPoint(200, 200); polygon.addPoint(140, 250); polygon.addPoint(260, 250); graphics.draw(polygon); polygon.reset(); polygon.addPoint(180, 250); polygon.addPoint(180, 300); polygon.addPoint(220, 300); polygon.addPoint(220, 250); graphics.draw(polygon); graphics.dispose(); File file = new File("F:\\1.jpg"); file.createNewFile(); FileOutputStream fos = new FileOutputStream(file); ImageIO.write(image, "jpg", fos); fos.close(); } }
使用Graphics2D图片上写字,计算宽和高 以及字体的位置
如上图,这个是一个有中文与英文的字符串。 中文与英文字符的宽高是不一样的,如果想要生成一张宽高刚的图片,这样我就需要计算每一个字符的宽度,及合适的高;
java.awt.FontMetrics 这个类对文字的宽高位置有详细的介绍;
计算使用字体的一段字符串的宽
public static int getWordWidth(Font font, String content) { FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font); int width = 0; for (int i = 0; i < content.length(); i++) { width += metrics.charWidth(content.charAt(i)); } return width; }
计算使用字体的最大的高度
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font); int height = metrics.getHeight();
在图片是写文字时最合适的位置
Ascent是从基线到顶部最大的高,也可以当做一个种字体画图时最有可以点用的高度
graphics.drawString(content, 0, metrics.getAscent());
测试代码
import sun.font.FontDesignMetrics; import javax.imageio.ImageIO; import java.awt.*; import java.awt.font.LineMetrics; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; /** * Created by zengrenyuan on 18/5/11. */ public class ImageTest { public static void main(String[] args) throws IOException { Font font = new Font("微软雅黑", Font.BOLD, 32); String content = "你好Java!"; FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font); int width = getWordWidth(font, content);//计算图片的宽 int height = metrics.getHeight();//计算高 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = bufferedImage.createGraphics(); graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //设置背影为白色 graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); graphics.setFont(font); graphics.setColor(Color.BLACK); graphics.drawString(content, 0, metrics.getAscent());//图片上写文字 graphics.dispose(); write(bufferedImage, "/data/test.png"); } public static int getWordWidth(Font font, String content) { FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font); int width = 0; for (int i = 0; i < content.length(); i++) { width += metrics.charWidth(content.charAt(i)); } return width; } public static void write(BufferedImage bufferedImage, String target) throws IOException { File file = new File(target); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } try (OutputStream os = new FileOutputStream(target)) { ImageIO.write(bufferedImage, "PNG", os); } } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。