Be serious about writing, not clickbait.

The article is available at Github.com/niumoo/Java… And program ape Alang’s blog, point attention, don’t get lost.

The use of Springboot on the above pattern is certainly not unfamiliar, Springboot boot will print the above pattern, and with a version number. Check the official documentation for a description of the banner

The banner that is printed on start up can be changed by adding a banner.txt file to your classpath or by setting the spring.banner.location property to the location of such a file. If the file has an encoding other than UTF-8, you can set spring.banner.charset. In addition to a text file, you can also add a banner.gif, banner.jpg, or banner.png image file to your classpath or set the spring.banner.image.location property. Images are converted into an ASCII art representation and printed above any text banner.

You can change the banner printed on start up by adding a banner.txt file to the classpath or setting spring.banner. Property points to the location of such a file. If the encoding of the file is not UTF-8, you can set spring.banner.charset. In addition to text files, you can also add banners. Save the GIF, banner.jpg, or banner.png image file to the classpath or set spring.banner.image. Location properties. The image is converted to ASCII art form and printed on any text banner.

1. Customize banners

According to the official description, we can customize the banner pattern in the classpath. We try to create a file named banner.txt in the resouce directory and write the content (online character generation).

(_) _ __ _ _ _ _ __ ___ ___ ___ | '_ \ | | | | |' _ ` _ \ / _ \ _ \ | | | | | | _ | | | | | | | | (_) (_) | | _ | | _ _ - | | \ __, _ _ - | | | _ | | _ | \ ___ / \ ___ / version: ${spring - the boot. Formatted version} -Copy the code

Start Springboot on the console and see the following output.

(_) _ __ _ _ _ _ __ ___ ___ ___ | '_ \ | | | | |' _ ` _ \ / _ \ _ \ | | | | | | _ | | | | | | | | (_) (_) | | _ | | _ _ - | | \ __, _ _ - | | | _ | | _ | \ ___ / \ ___ / version: (v2.1.3. RELEASE) the 2019-02-25 14:00:31. 12312-289 the INFO [main] net. Codingme. Banner. BannerApplication: Starting BannerApplication on LAPTOP-L1S5MKTA with PID 12312 (D:\IdeaProjectMy\springboot-git\springboot-banner\target\classes started by Niu in D:\IdeaProjectMy\springboot-git\springboot-banner) 2019-02-25 14:00:31.291 INFO 12312 -- [main] net.codingme.banner.BannerApplication : No active profile set, falling back to default profiles: The default 14:00:32 2019-02-25. 12312-087 the INFO [main] O.S.B.W.E mbedded. Tomcat. TomcatWebServer: Tomcat initialized with port(s): 8080 (http)Copy the code

Found that the custom banner has taken effect, the introduction of the official document said that you can also place pictures, the following place image banner. JPG test. I found a random picture on the Internet.Start the observation output again.Springboot converted the pattern to ASCII.

2. Principle of ASCII pattern generation

Looking at the above example, Springboot can convert images to ASCII patterns, so how does it do this? We can probably imagine a general process.

  1. Get the picture.
  2. Iterate over the image pixels.
  3. The pixels are analyzed, and each pixel gives a value based on color depth, matching different characters based on shade.
  4. Output patterns.

Does Springboot handle the image banner as we thought above? Go directly to the source code to find the answer.

/ * * position: org. Springframework. Boot. SpringApplicationBannerPrinter * /
// Method 1:
public Banner print(Environment environment, Class
        sourceClass, Log logger) {
	    // get the banner call method as 2
		Banner banner = getBanner(environment);
		try {
			logger.info(createStringFromBanner(banner, environment, sourceClass));
		}
		catch (UnsupportedEncodingException ex) {
			logger.warn("Failed to create String for banner", ex);
		}
		/ / print the banner
		return new PrintedBanner(banner, sourceClass);
}
2 / / method
private Banner getBanner(Environment environment) {
		Banners banners = new Banners();
		// Get image banner, we only care about this, call method called 3
		banners.addIfNotNull(getImageBanner(environment));
		banners.addIfNotNull(getTextBanner(environment));
		if (banners.hasAtLeastOneBanner()) {
			return banners;
		}
		if (this.fallbackBanner ! =null) {
			return this.fallbackBanner;
		}
		return DEFAULT_BANNER;
	}
3 / / method
/** Get the information about the custom banner file */
private Banner getImageBanner(Environment environment) {
	// BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location";
		String location = environment.getProperty(BANNER_IMAGE_LOCATION_PROPERTY);
		if (StringUtils.hasLength(location)) {
			Resource resource = this.resourceLoader.getResource(location);
			return resource.exists() ? new ImageBanner(resource) : null;
		}
		// IMAGE_EXTENSION = { "gif", "jpg", "png" };
		for (String ext : IMAGE_EXTENSION) {
			Resource resource = this.resourceLoader.getResource("banner." + ext);
			if (resource.exists()) {
				return newImageBanner(resource); }}return null;
}
Copy the code

Above is looking for custom image banner file source, if the image into ASCII pattern to continue to follow up, trace method 1 PrintedBanner(banner, sourceClass) method. Finally find the main method of output pattern.

/ / position: org. Springframework. Boot. ImageBanner# printBanner
private void printBanner(BufferedImage image, int margin, boolean invert,
			PrintStream out) {
		AnsiElement background = invert ? AnsiBackground.BLACK : AnsiBackground.DEFAULT;
		out.print(AnsiOutput.encode(AnsiColor.DEFAULT));
		out.print(AnsiOutput.encode(background));
		out.println();
		out.println();
		AnsiColor lastColor = AnsiColor.DEFAULT;
		// Image height traversal
		for (int y = 0; y < image.getHeight(); y++) {
			for (int i = 0; i < margin; i++) {
				out.print("");
			}
			// Image width traversal
			for (int x = 0; x < image.getWidth(); x++) {
				// Get each pixel
				Color color = new Color(image.getRGB(x, y), false);
				AnsiColor ansiColor = AnsiColors.getClosest(color);
				if(ansiColor ! = lastColor) { out.print(AnsiOutput.encode(ansiColor)); lastColor = ansiColor; }// The pixel is converted to character output, and the calling method is denoted as 2
				out.print(getAsciiPixel(color, invert));
			}
			out.println();
		}
		out.print(AnsiOutput.encode(AnsiColor.DEFAULT));
		out.print(AnsiOutput.encode(AnsiBackground.DEFAULT));
		out.println();
	}
// Method 2, pixels are converted to characters
	private char getAsciiPixel(Color color, boolean dark) {
		// Calculate a brightness value according to color
		double luminance = getLuminance(color, dark);
		for (int i = 0; i < PIXEL.length; i++) {
			// Find the character that matches the brightness value
			if (luminance >= (LUMINANCE_START - (i * LUMINANCE_INCREMENT))) {
				// PIXEL = { ' ', '.', '*', ':', 'o', '&', '8', '#', '@' };
				returnPIXEL[i]; }}return PIXEL[PIXEL.length - 1];
	}
Copy the code

By looking at the source code, found Springboot picture banner conversion and we expected roughly the same, so interesting function we can write a?

3. Convert pictures to ASCII characters by themselves

According to the above analysis, to sum up the idea, we can also manually write a picture to ASCII character pattern. Here’s the idea:

  1. Zoom in and resize the image to fit.
  2. Traverse image pixels.
  3. Gets the brightness of the image pixels (RGB colors can be calculated by the formula).
  4. Match character.
  5. Output patterns.

The above 5 steps directly using Java code can be completed, the source code prepared below.

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

/** * <p> * Generate a character pattern based on the image * 1. Traverse image pixel * 3. Get image pixel brightness * 4. Match character * 5. Output pattern * *@author  niujinpeng
 * @website www.codingme.net
 * @dateThe 2019-02-25 23:03:01 * /
public class GeneratorTextImage {
    private static final char[] PIXEL = {The '@'.The '#'.'8'.'&'.'o'.':'.The '*'.'. '.' '};
    public static void main(String[] args) throws Exception {
        // Image zoom
        BufferedImage bufferedImage = makeSmallImage("src/main/resources/banner.jpg");
        / / output
        printImage(bufferedImage);
    }

    public static void printImage(BufferedImage image) throws IOException {
        int width = image.getWidth();
        int height = image.getHeight();
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int rgb = image.getRGB(j, i);
                Color color = new Color(rgb);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                // a formula for calculating the brightness of RGB pixels
                Double luminace = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
                double index = luminace / (Math.ceil(255 / PIXEL.length) + 0.5);
                System.out.print(PIXEL[(int)(Math.floor(index))]); } System.out.println(); }}public static BufferedImage makeSmallImage(String srcImageName) throws Exception {
        File srcImageFile = new File(srcImageName);
        if (srcImageFile == null) {
            System.out.println("File does not exist");
            return null;
        }
        FileOutputStream fileOutputStream = null;
        BufferedImage tagImage = null;
        Image srcImage = null;
        try {
            srcImage = ImageIO.read(srcImageFile);
            int srcWidth = srcImage.getWidth(null);// Width of the original image
            int srcHeight = srcImage.getHeight(null);// Height of the original image
            int dstMaxSize = 90;// The maximum width/height of the target thumbnail. The width and height will be scaled
            int dstWidth = srcWidth;// Thumbnail width
            int dstHeight = srcHeight;// Thumbnail height
            float scale = 0;
            // Calculate the width and height of the thumbnail
            if (srcWidth > dstMaxSize) {
                dstWidth = dstMaxSize;
                scale = (float)srcWidth / (float)dstMaxSize;
                dstHeight = Math.round((float)srcHeight / scale);
            }
            srcHeight = dstHeight;
            if (srcHeight > dstMaxSize) {
                dstHeight = dstMaxSize;
                scale = (float)srcHeight / (float)dstMaxSize;
                dstWidth = Math.round((float)dstWidth / scale);
            }
            // Generate thumbnails
            tagImage = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_RGB);
            tagImage.getGraphics().drawImage(srcImage, 0.0, dstWidth, dstHeight, null);
            return tagImage;
        } finally {
            if(fileOutputStream ! =null) {
                try {
                    fileOutputStream.close();
                } catch (Exception e) {
                }
                fileOutputStream = null;
            }
            tagImage = null;
            srcImage = null; System.gc(); }}}Copy the code

Again take the above Google log picture as the experimental object, run to get the character pattern output.The article code has been uploaded to GitHubSpring Boot.

After < >

Hello world 🙂

I am a lang, lang of the moon, a technical tool person who moves bricks every day. Personal website: www.wdbyte.com If you want to subscribe, you can follow the public account of “Procedural Ape Alang”, or the blog of procedural ape Alang, or add me on wechat (WN8398).

This article has also been compiled at GitHub.com/niumoo/Java… Welcome Star.