211116-Java实现图片转字符图片示例demo

文章目录
  1. 一灰灰的联系方式

前面介绍了一篇java实现图片灰度化处理的小demo,接下来再介绍一个有意思的东西,将一个图片转换成字符图片

借助前面图片灰度化处理的知识点,若我们希望将一张图片转成字符图片,同样可以遍历每个像素点,然后将像素点由具体的字符来替换,从而实现字符化处理

基于上面这个思路,具体的实现就很清晰了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Test
public void testRender() throws IOException {
String file = "http://i0.download.fd.52shubiao.com/t_960x600/g1/M00/10/17/oYYBAFWvR5-IeXHuAAd5kPb8eSgAACm0QF50xIAB3mo414.jpg";
// 从网络上下载图片
BufferedImage img = ImageIO.read(FileReadUtil.getStreamByFileName(file));


int w = img.getWidth(), h = img.getHeight();
// 创建新的字符图片画板
BufferedImage gray = new BufferedImage(w, h, img.getType());
Graphics2D g2d = gray.createGraphics();
g2d.setColor(null);
g2d.fillRect(0, 0, w, h);

Font font = new Font("宋体", Font.BOLD, 1);
g2d.setFont(font);
for (int x = 0; x < w; x ++) {
for (int y = 0; y < h; y ++) {
g2d.setColor(ColorUtil.int2color(img.getRGB(x, y)));
g2d.drawString("灰", x, y);
}
}
g2d.dispose();
System.out.printf("渲染完成");
}

注意上面的实现,在会字符的时候,先取出源像素点的色彩,然后重新设置给g2d,这个int转color也比较简单,实现如下

1
2
3
4
5
6
7
public static Color int2color(int color) {
int a = (0xff000000 & color) >>> 24;
int r = (0x00ff0000 & color) >> 16;
int g = (0x0000ff00 & color) >> 8;
int b = (0x000000ff & color);
return new Color(r, g, b, a);
}

这样就实现了一个基础版的转字符图了,实际跑一下看看效果

这下尴尬了,输出的并不是我们预期的字符图,那么问题出在哪呢?

仔细看上面的文字大小为1,文字太小,导致即使是有字符组件的图,最终肉眼看起来和原图也没啥区别

那么我们就试一下将这个文字搞大点,将n*n个像素点作为一个文字渲染区域,这样我们需要调整一下遍历的步长;其次就是这个区域的颜色怎么定

  • 直接取均值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 求取多个颜色的平均值
*
* @return
*/
Color getAverage(BufferedImage image, int x, int y, int w, int h) {
int red = 0;
int green = 0;
int blue = 0;

int size = 0;
for (int i = y; (i < h + y) && (i < image.getHeight()); i++) {
for (int j = x; (j < w + x) && (j < image.getWidth()); j++) {
int color = image.getRGB(j, i);
red += ((color & 0xff0000) >> 16);
green += ((color & 0xff00) >> 8);
blue += (color & 0x0000ff);
++size;
}
}

red = Math.round(red / (float) size);
green = Math.round(green / (float) size);
blue = Math.round(blue / (float) size);
return new Color(red, green, blue);
}

另外的就是改一下遍历的步长

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Test
public void testRender() throws IOException {
String file = "http://i0.download.fd.52shubiao.com/t_960x600/g1/M00/10/17/oYYBAFWvR5-IeXHuAAd5kPb8eSgAACm0QF50xIAB3mo414.jpg";
// 从网络上下载图片
BufferedImage img = ImageIO.read(FileReadUtil.getStreamByFileName(file));


int w = img.getWidth(), h = img.getHeight();
// 创建新的灰度图片画板
BufferedImage gray = new BufferedImage(w, h, img.getType());
Graphics2D g2d = gray.createGraphics();
g2d.setColor(null);
g2d.fillRect(0, 0, w, h);

int size = 12;
Font font = new Font("宋体", Font.BOLD, size);
g2d.setFont(font);
for (int x = 0; x < w; x += size) {
for (int y = 0; y < h; y += size) {
Color avgColor = getAverage(img, x, y, size, size);
g2d.setColor(avgColor);
g2d.drawString("灰", x, y);
}
}
g2d.dispose();
System.out.printf("渲染完成");
}

再次执行之后结果如下,实现了我们的预期效果

最后再介绍一个更好用的姿势,直接使用开源项目 https://github.com/liuyueyi/quick-media 来实现图片字符画

使用这个项目的 image-plugins 之后,生成一个灰度图就很简单了

1
2
3
4
5
6
7
8
9
public void testCharImg() throws IOException {
String img = "http://hbimg.b0.upaiyun.com/2b79e7e15883d8f8bbae0b1d1efd6cf2c0c1ed1b10753-cusHEA_fw236";
BufferedImage out = ImgPixelWrapper.build().setSourceImg(img).setBlockSize(2)
.setPixelType(PixelStyleEnum.CHAR_COLOR)
.setChars("小灰灰blog")
.build()
.asBufferedImg();
System.out.println(out);
}

注意这个ImgPixelWrapper封装类,处理基础的字符处理之外,还支持生成灰度图,gif图转字符动画,图片像素化(如马赛克…)

至于quick-media这个项目就更有意思了,java侧若想生成酷炫的二维码,选择它绝对不会让你失望;有兴趣的小伙伴可以瞅一瞅

一灰灰的联系方式

尽信书则不如无书,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

QrCode

# JDK

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×