Today, I was sorting out the articles to be read in Pocket and saw this article "Creating ASCII art in functional Swift", which explains how to use Swift to convert images into ASCII characters. The specific principle is explained in detail in the article, so I will not repeat it here, but the "in functional Swift" in the title made me very interested. I wanted to know where the functionality is reflected, so I downloaded the swift-ascii-art source code to find out. Pixel The image is composed of pixels, which are implemented by the Pixel struct in the code. Each pixel is allocated 4 bytes, which (2^8 = 256) are used to store the RBGA value. createPixelMatrix You can create a width * height pixel matrix using the static method createPixelMatrix:
intensityFromPixelPointer The intensityFromPixelPointer method calculates and returns the brightness value of a pixel. The code is as follows:
The calculateIntensity method obtains the intensity of a pixel based on Y'UV encoding:
YUV is a color encoding method, where Y represents brightness, UV represents color difference, and U and V are the two components that make up color. Its advantage is that it can use the characteristics of the human eye to reduce the storage capacity required for digital color images. The Y we get from this formula is the value of brightness. Offset There is actually only one value stored in Pixel: offset. The matrix created by Pixel.createPixelMatrix looks like this:
It does not store the relevant data of each pixel as you might imagine, but is more like a conversion tool that calculates the grayscale value of PixelPointer. AsciiArtist AsciiArtist encapsulates some methods for generating character paintings. createAsciiArt The createAsciiArt method is used to create character art:
The CFDataGetBytePtr function returns the pointer to the byte array of the image. Each element in the array is a byte, that is, an integer from 0 to 255. Every 4 bytes form a pixel, corresponding to the RGBA value. intensityMatrixFromPixelPointer intensityMatrixFromPixelPointer This method generates the corresponding brightness value matrix through PixelPointer:
First, an empty two-dimensional array is created through the Pixel.createPixelMatrix method to store values. Then two maps are nested to traverse all the elements in it and convert pixels into intensity values. symbolMatrixFromIntensityMatrix The symbolMatrixFromIntensityMatrix function converts an array of brightness values into an array of glyphs:
Map + reduce successfully implements string accumulation. Each reduce operation uses the symbolFromIntensity method to obtain the character corresponding to the brightness value. The symbolFromIntensity method is as follows:
Pass intensity, make sure the value is between 0 and 1, convert it to the corresponding character through AsciiPalette, and output sumbol. AsciiPalette AsciiPalette is a tool used to convert numerical values into characters, just like a palette in a character painting, generating characters based on different colors. loadSymbols loadSymbols loads all symbols:
As you can see, the character range we selected is 32 ~ 126 characters. The next step is to sort these characters by brightness through the symbolsSortedByIntensityForAsciiCodes method. For example, the & symbol definitely represents an area darker than ., so how is it compared? Please see the sorting method. symbolsSortedByIntensityForAsciiCodes The symbolsSortedByIntensityForAsciiCodes method implements string generation and sorting:
Among them, the sortByIntensity sorting method is as follows:
summary After a brief review of the project, I can vaguely feel some functional style, which is mainly reflected in the following aspects: The application of functions such as map reduce is just right, and can easily handle the conversion and concatenation of arrays. Data processing is performed through input and output, such as the sortByIntensity method and the symbolFromIntensity method. There are few states and attributes, but more direct function conversions. Function logic does not depend on external variables, but only on the parameters passed in. The code feels simple and light. Through this simple example, we can verify what we have learned from the functional features. It feels great! |
<<: Why is it difficult for domestic apps to dominate overseas markets?
>>: How to Become a Great JavaScript Programmer
[[161131]] 2016 has arrived. I wonder if you have...
The launch of mini programs has brought convenien...
Web games, which have always given people the imp...
If you were planning a sophisticated heist on one...
The hot weather in summer and the reduction of ou...
[[125989]] Last year, Apple released two large-sc...
What are the characteristics of information flow ...
Following the announcement of the list of “Top 50 ...
Ali health care products applet development price...
From launching the live streaming function to the...
1. Review of the national passenger car market in...
The pursuit of beauty by beauty lovers is endless...
Recently, many companies may be promoting the &qu...
How to apply for a 400 telephone number? How to a...
Every time a festival comes, many people will buy...