打印一个兔子

302 阅读1分钟

我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛

0 引子

我们在启动一些软件时,在启动界面总能看到相关由字符组成的各种软件图案,比如SpringBoot的

image.png

那么,如果我们要使用图片来做成字符图案,做为项目启动LOGO,这样看起来会不会更酷呢?

我们的原图是下边这只可爱的小兔子

abc.png

1 使用自定义字符,打印图像

操作步骤:

  • 把这只兔子读取到图像对象中
  • 获取图像对象中的像素数据
  • 解析像素数据为RGB值
  • 将RGB值转为单一灰度值
  • 定义我们想要组成图案的字符列表,将单一灰度值替换为我们定义的字符并输出
/**
* 支持 import Java 标准库 (JDK 1.8)
*/
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
/**
* 注意:目前 Java 代码的入口类名称必须为 Main(大小写敏感)
*/
public class Main {
   public static void main(final String[] args) {
        //声明图片路径
        String path = "/home/faas/abc.png";
        String base = "!@#$%^&*()+=<>"; //定义组成图案的字符列表
        try {
            //读取图片文件
            BufferedImage image = ImageIO.read(new File(path));
            //遍历纵坐标像素点
            for (int y = 0; y < image.getHeight(); y += 2) {
                //遍历横坐标像素点
                for (int x = 0; x < image.getWidth(); x += 1) {
                    //获取像素值
                    int rgb = image.getRGB(x, y);
                    //分别计算像素值中的RGB数据
                    int red = (rgb >> 16 ) & 0xff;
                    int green = (rgb >> 8) & 0xff;
                    int black = rgb & 0xff;
                    //将RGB数据转为灰度值
                    float gray = 0.299f * red + 0.578f * green + 0.114f * black;
                    int index = Math.round(gray * (base.length() + 1) / 255);
                    System.out.print(index >= base.length() ? " " : String.valueOf(base.charAt(index)));
                }
                System.out.println();
            }
        } catch (final IOException e) {
            e.printStackTrace();
        }
    }
}

打印效果如下

image.png

2 水墨图风格的兔子

2.1 首先将彩色图片转为黑白水墨

public static void main(String[] args) {
    String path = "d:/data/abc.png";

    try {
        //读取图片文件
        BufferedImage image = ImageIO.read(new File(path));
        int width = image.getWidth();
        int height = image.getHeight();

        //使用灰度模式,创建新的图像对象
        BufferedImage grayImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
        for(int i= 0 ; i < width ; i++){
            for(int j = 0 ; j < height; j++){
                int rgb = image.getRGB(i, j);
                //将像素数据存入缓冲区中
                grayImage.setRGB(i, j, rgb);
            }
        }
        File newFile = new File(path + "bak1.png");

        ImageIO.write(grayImage, "png", newFile);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

转换后的效果为

abc.pngbak2.png

2.2 将图片转为字符图案

还是使用 1 中的方法,只是图像文件的名称有变化

public static void main(final String[] args) {
    String path = "d:/data/abc.pngbak1.png";
    String base = "!@#$%^&*()+=<>"; //定义组成图案的字符列表
    try {
        //读取图片文件
        BufferedImage image = ImageIO.read(new File(path));
        //遍历纵坐标像素点
        for (int y = 0; y < image.getHeight(); y += 2) {
            //遍历横坐标像素点
            for (int x = 0; x < image.getWidth(); x += 1) {
                //获取像素值
                int rgb = image.getRGB(x, y);
                //分别计算像素值中的RGB数据
                int red = (rgb >> 16 ) & 0xff;
                int green = (rgb >> 8) & 0xff;
                int black = rgb & 0xff;
                //将RGB数据转为灰度值
                float gray = 0.299f * red + 0.578f * green + 0.114f * black;
                int index = Math.round(gray * (base.length() + 1) / 250);
                System.out.print(index >= base.length() ? " " : String.valueOf(base.charAt(index)));
            }
            System.out.println();
        }
    } catch (final IOException e) {
        e.printStackTrace();
    }
}

转换后的效果如下

image.png

注意

需要注意的是,用来做字符图案的图片不宜过大,上边转换后的图案都是在notepad++上极限缩小的情况下展示出来的。