问题描述
后台有两个业务:生成二维码、生成群聊头像,这两个使用的方法都是利用 Graphics2D
对图片进行裁剪拼接。最近测试发现,通过这个方法生成的图片锯齿问题很严重,在 App
端即便展示的是小图也能很明显的看出。为了方便展示,下面展示的图片是放大后的,如下:
这个情况只有圆形图片才会出现,方形图片不存在这个问题。作为对比,下面放上方形图片的展示效果:
优化记录
只有生成的圆形图片存在锯齿问题,那么首先定位到问题是由裁剪图片相关的代码引起的,因此下面对这一块的代码进行优化:
首先尝试了为生成的圆形图片增加抗锯齿的配置,但是没有任何效果。
1
2// 增加抗锯齿配置
graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);RenderingHints
的作用见文档:Class RenderingHints接着继续搜寻解决方案,在 JAVA 将图片剪裁成圆形,并在圆形外带有白边 中找到了相应的优化办法:图片裁剪成圆形后,在图片外面再绘制一层圆形边界。如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 绘制圆形图片
BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2 = bi2.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(), bi1.getHeight());
g2.setClip(shape);
g2.drawImage(bi1, 0, 0, bi1.getWidth(), bi1.getHeight(), null);
g2.dispose();
// 利用画笔在切割后的圆外面再画一个圆,这样画的圆不会有锯齿
g2 = bi2.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Stroke s = new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g2.setStroke(s);
g2.setColor(new Color(231, 231, 231));
g2.drawOval(0, 0, bi1.getWidth(), bi1.getHeight());
g2.dispose();
原理就是通过绘制一个边界来消除圆形的锯齿问题:
最终优化后的效果如下:( 注:左边是优化前的,右边是优化后的 )