Попытка нарисовать изображение с помощью букв ASCII, но мое изображение получается повернутым
Я пытаюсь сделать ASCII Art из изображения, но по какой-то причине вывод всегда поворачивается, и я несколько раз просматривал свой код, и я просто не могу найти ошибку. Я предполагаю, что это как-то связано с imageWidth и imageHeight, но все это выглядит хорошо для меня..
Код можно найти на GitHub
4 ответа
Нарисуйте ASCII Art из изображения
Предположим, что один персонаж занимает площадь
21×8
пикселей. Итак, сначала вам нужно получить средний цвет этой области, затем получить среднюю яркость этого цвета, а затем преобразовать ее в символ.
Исходное изображение:
Изображение ASCII:
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 scaleH, int scaleW) throws IOException {
BufferedImage image = ImageIO.read(new File("/tmp/image.jpg"));
int height = image.getHeight() / scaleH;
int width = image.getWidth() / scaleW;
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 < scaleH; k++)
for (int p = 0; p < scaleW; p++)
colorRGB += image.getRGB(j * scaleW + p, i * scaleH + k);
// get the average color
Color color = new Color(colorRGB / (scaleH * scaleW));
// 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 =
"\"`^\\\",:;Il!i~+_-?][}{1)(|\\\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$\"";
static char getDensity(int value) {
// Since we don't have 255 characters, we have to get the char using 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();
}
Выход:
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
hhhhhhhhhhhhhfpCmQbU%pCZJJhhhhhhhhhhhhh
hhhhhhhhhhhh00qh"""""""hWLUuhhhhhhhhhhh
hhhhhhhhhhbw"""""""""""""""cthhhhhhhhhh
hhhhhhhhhhZ"""""""""""""""""Ohhhhhhhhhh
hhhhhhhhhhJ"""""""""""""""""whhhhhhhhhh
hhhhhhhhhh\bw"""""""""""""wQChhhhhhhhhh
hhhhhhhhhhhhzJ"""""""""""pCUhhhhhhhhhhh
hhhhhhhhkL|XZa"""""""""""wtYXYohhhhhhhh
hhhhhhnjz8"""""""""""""""""""*J0hhhhhhh
hhhhhZL%"""""""""""""""""""""""hruhhhhh
hhhh0U"""""""""""""""""""""""""""0Ohhhh
hhhuq"""""""""""""""""""""""""""""Jzhhh
Создание карт плотности и яркости символов
Вы можете создать собственную карту плотности символов из любого диапазона символов, а затем, поскольку плотности распределены неравномерно, преобразовать ее в карту яркости и далее вызыватьceilingEntry
а такжеfloorEntry
методы.
Сначала нарисуйте каждый символ как черно-белую картинку, используяjava.awt
упаковать и подсчитать количество пикселей — получится карта плотности . Затем для каждой записи с этой карты рассчитайте процент яркости на шкале
0-255
- вы получаете карту яркости .
Картинки:
Код:
public static void main(String[] args) {
Font font = new Font(Font.MONOSPACED, Font.PLAIN, 22);
// ASCII characters: 0 - 255
// Runic: 0x16A0 - 0x16FF
// Box Drawing: 0x2500 - 0x257F
// Block Elements: 0x2580 - 0x259F
// Geometric Shapes: 0x25A0 - 0x25FF
// Hiragana: 0x3040 - 0x309F
TreeMap<Integer, List<String>> density = getDensityMap(font,0x25A0,0x25FF,0);
// the map of brightness of pixels [0, 255]
TreeMap<Integer, List<String>> brightness = getBrightnessMap(density);
// output, geometric shapes
for (List<String> value : brightness.values()) System.out.print(value.get(0));
// ◙◘■▩●▦▣◚◛◕▨▧◉▤◐◒▮◍◑▼▪◤▬◗◭◖◈◎◮◊◫▰◄◯□▯▷▫▽◹△◁▸▭◅▵◌▱▹▿◠◃◦◟◞◜
}
/**
* @param density character density map
* @return the pixel brightness map [0, 255],
* based on percentages of character density
*/
static TreeMap<Integer, List<String>> getBrightnessMap(
TreeMap<Integer, List<String>> density) {
int max = density.lastKey(); // maximum density
TreeMap<Integer, List<String>> brightness = new TreeMap<>();
for (Map.Entry<Integer, List<String>> entry : density.entrySet()) {
// pixel brightness, based on the percentage of character density
int key = (int) Math.round(255.0 - entry.getKey() * 255.0 / max);
List<String> value = entry.getValue();
List<String> val = brightness.remove(key);
if (val == null) val = new ArrayList<>();
val.addAll(value);
brightness.put(key, val);
}
return brightness;
}
/**
* @param f font to render text
* @param min character codepoint range, lower bound
* @param max character codepoint range, upper bound
* @param pd padding as a precaution, in most cases 0
* @return the character density map:
* key - density, value - list of characters
*/
static TreeMap<Integer, List<String>> getDensityMap(
Font f, int min, int max, int pd) {
// key - density, value - list of characters
TreeMap<Integer, List<String>> density = new TreeMap<>();
for (int i = min; i <= max; i++) {
// printable characters
if (f.canDisplay(i) && Character.isDefined(i)
&& !Character.isISOControl(i)
&& !Character.isIdentifierIgnorable(i)) {
String str = String.valueOf(Character.toChars(i));
int key = getDensity(str, f, pd);
List<String> list = density.remove(key);
if (list == null) list = new ArrayList<>();
list.add(str);
density.put(key, list);
}
}
return density;
}
/**
* @param text source text to draw
* @param f font to render text
* @param pd padding as a precaution, in most cases 0
* @return the density of the characters in this text
*/
static int getDensity(String text, Font f, int pd) {
FontRenderContext ctx = new FontRenderContext(f.getTransform(), false, false);
Rectangle bounds = f.getStringBounds(text, ctx).getBounds();
int width = bounds.width + pd * 2;
int height = bounds.height + pd * 2;
BufferedImage image =
new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setFont(f);
graphics.drawString(text, pd + bounds.x, pd - bounds.y);
//ImageIO.write(image, "png", new File("text.png"));
int density = 0;
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
if (image.getRGB(j, i) == 0xFFFFFFFF)
density++;
return density;
}
В ImageWriting.java, строка 34:
this.writer.append(Density.DENSITY.getDensityFor(this.brightnessValues[j][i]));
Я сильно подозреваю, что вы проходите через одну координату в каком-то цикле, а другой цикл вложен внутрь. (Не буду гнаться за кодом на другом сайте.)
Попробуйте поменять местами вложение