preface
Here, it’s a picture, oh no, it’s actually a million-word novel!
You might think, is it small?
No, if we zoom in, we can only see pixels
In fact, this piece of color is a character, did not think of it.
How do colors represent characters
We know that the color value is RGB, which can be combined into any color by 3 numbers in 255. We only need to convert the Chinese character into a specific color value, so how can the Chinese character be converted into an integer?
For example, the Unicode code for “nugget” is “\u6398\u91d1”. Next, we divide a Unicode code into two parts, the first part is the green value, and the second part is the blue value. For example, “nugget” is divided into 63 and 98. Then we can specify that the RGB color value is RGB (255,63,98). Yes, we can choose not to use red, and set a fixed value for red, if 255, then the whole color will be red.
With the color values, we can create a canvas and set the values for each pixel.
So, how big should this canvas be? So here’s the question, if I have 20 characters, and I have an n by n canvas, what’s the n?
The answer is at least 5 to hold 20 pixels. The formula is to take the 0.5 power of the number of characters, and then round up the number.
RGB to integer
For example, if we want to convert RGB (255,63,98) to an integer, or if we want to reverse the calculation, how do we calculate the blue and green values from the integer?
private static int getIntFromColor(int r, int g, int b) {
r = (r << 16) & 0x00FF0000;
g = (g << 8) & 0x0000FF00;
b = b & 0x000000FF;
return 0xFF000000 | r | g | b;
}
Copy the code
// Get green
(rgb >> 8) & 0xff)
// Get blue
(rgb >> 0) & 0xff)
Copy the code
Generated picture novel
The following is to encode the novel into the image, and there are two bit operations, ((value & 0xFF00) >> 8), (value & 0xff), which are used to obtain the g and B color parts of the Unicode code corresponding to the characters.
Set RGB colors from left to right and top to bottom to form the opening image.
private static void encrypt(a){
try {
String str = readFileByLines("/home/HouXinLin/test/src.txt");
int width = (int) Math.ceil(Math.pow(str.length(), 0.5));
int x = 0, y = 0;
BufferedImage renderedImage = new BufferedImage(width, width, BufferedImage.TYPE_INT_RGB);
for (char c : str.toCharArray()) {
int value = c;
int intFromColor = getIntFromColor(255, ((value & 0xff00) > >8), (value & 0xff));
renderedImage.setRGB(x, y, intFromColor);
if (y == width - 1) {
y = 0;
x += 1;
} else {
y += 1;
}
}
ImageIO.write(renderedImage, "BMP".new FileOutputStream("/home/HouXinLin/test/target.bmp"));
} catch(IOException e) { e.printStackTrace(); }}Copy the code
decoding
When decoding, the color value of the pixel is obtained respectively, and the green and blue values are taken out. Finally, it is spliced into a four-digit hexadecimal value and converted to char type.
private static void decode(a) {
try {
BufferedImage bufferedImage = ImageIO.read(new File("/home/HouXinLin/test/target.bmp"));
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int rgb = bufferedImage.getRGB(i, j);
String hex = Integer.toHexString((rgb >> 8) & 0xff) + "" + zero(Integer.toHexString(((rgb >> 0) & 0xff)));
char c = (char) Integer.valueOf(hex, 16).intValue();
stringBuffer.append(c);
}
}
Files.write(Paths.get("/ home/HouXinLin/test/rebirth 2. TXT"), stringBuffer.toString().getBytes(StandardCharsets.UTF_8));
} catch(IOException e) { e.printStackTrace(); }}private static String zero(String str) {
if (str.length() == 1) {
return "0" + str;
}
return str;
}
Copy the code