java - 如何使用 ASCII 符号绘制图像?
问题描述
我正在尝试从图像中制作 ASCII 艺术,但由于某种原因,输出总是旋转,我多次检查我的代码,但我根本找不到错误。我猜这与它有关imageWidth
,imageHeight
但对我来说一切都很好。
代码可以在github上找到
解决方案
从图像中绘制 ASCII 艺术作品
让我们假设一个字符占据一个21×8
像素区域。所以首先你得把原图按比例缩小,得到这个区域的平均颜色,然后得到这个颜色的平均亮度,然后再转换成一个字符。
原图:
ASCII图片:
此代码从文件中读取图像,将其缩小到高度的 1/21 和宽度的 1/8,计算缩放区域的平均颜色,然后计算每种颜色的平均亮度并选择一个字符相应的密度,然后将这些字符保存到文本文件中。
没有缩放scH=1
和scW=1
,字符数等于原始图像中的像素数。
public static void main(String[] args) throws IOException {
// assume that one character occupies an area of 21×8 pixels
char[][] chars = readImage("/tmp/image.jpg", 21, 8);
writeToFile("/tmp/image.txt", chars);
}
static char[][] readImage(String path, int scH, int scW) throws IOException {
BufferedImage image = ImageIO.read(new File(path));
int height = image.getHeight() / scH;
int width = image.getWidth() / scW;
char[][] chars = new char[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
// scaling image and accumulating colors
int colorRGB = 0;
for (int k = 0; k < scH; k++)
for (int p = 0; p < scW; p++)
colorRGB += image.getRGB(j * scW + p, i * scH + k);
// get the average color
Color color = new Color(colorRGB / (scH * scW));
// read the R, G, B values of the color and get the average brightness
int brightness = (color.getRed() + color.getGreen() + color.getBlue()) / 3;
// get a character depending on the brightness value
chars[i][j] = getDensity(brightness);
}
}
return chars;
}
static final String DENSITY =
"@QB#NgWM8RDHdOKq9$6khEPXwmeZaoS2yjufF]}{tx1zv7lciL/\\|?*>r^;:_\"~,'.-`";
static char getDensity(int value) {
// Since we don't have 255 characters, we have to use percentages
int charValue = (int) Math.round(DENSITY.length() / 255.0 * value);
charValue = Math.max(charValue, 0);
charValue = Math.min(charValue, DENSITY.length() - 1);
return DENSITY.charAt(charValue);
}
static void writeToFile(String path, char[][] chars) throws IOException {
FileWriter writer = new FileWriter(path);
for (char[] row : chars) {
String str = String.valueOf(row);
writer.append(str).write("\n");
System.out.println(str);
}
writer.flush();
writer.close();
}
输出:
***************************************
***************************************
*************o/xiz|{,/1ctx*************
************77L*```````*_1{j***********
**********?i```````````````FZ**********
**********l`````````````````7**********
**********x`````````````````L**********
**********m?i`````````````iz1**********
************]x```````````\x{***********
********?1w]c>```````````La{]}r********
******jSF~```````````````````^xv>******
*****l1,```````````````````````*Sj*****
****7t```````````````````````````v7****
***uL`````````````````````````````t]***
推荐阅读
- jquery - 如何在传递给 api 之前对 Excel 工作表数据进行编码
- python - 在 Django rest api 中缓慢的互联网连接时更新数据
- r - 将不同(连续和有序)绘图类型组合到一个绘图中的问题
- php - 按相同的列值对结果进行分组
- php - 为未登录的用户隐藏某个段落,避免 WP Cache 混乱
- php - SQL多表更新问题
- scala - Spark数据框列中连续值的总和
- sql - 每月数据量
- android - 创建新的 Flutter 插件:io.flutter.plugin.common 模块未解析
- javascript - 如何使用侧边栏嵌入 youtube 播放列表