Creating character density and brightness maps
You can create your own character density map from any range of characters, and then, since the densities are not evenly distributed, convert it to a brightness map and further call the ceilingEntry
and floorEntry
methods.
First draw each character as a black-and-white picture using java.awt
package and count the number of pixels - you get a density map. Then for each entry from this map, calculate the percentage of brightness on the scale 0-255
- you get a brightness map.
Pictures:
Original picture |
ASCII: 0 - 255 0x0000 - 0x00FF |
Runic: 0x16A0 - 0x16FF |
Box Drawing: 0x2500 - 0x257F |
Block Elements: 0x2580 - 0x259F |
Geometric Shapes: 0x25A0 - 0x25FF |
Hiragana: 0x3040 - 0x309F |
 |
 |
 |
 |
 |
 |
 |
Density scales:
Unicode block |
Range of characters |
Density scale |
ASCII |
0-255 |
¶@ØÆMåBNÊßÔR#8Q&mÃ0À$GXZA5ñk2S%±3Fz¢yÝCJf1t7ªLc¿+?(r/¤²!*;"^:,'.` |
Runic |
0x16A0-0x16FF |
ᛥᛤᛞᚥᚸᛰᛖᚻᚣᛄᚤᛒᚢᚱᛱᚷᚫᛪᚧᚬᚠᛏᚨᚰᚩᚮᚪᚳᚽᚿᛊᛁᛵᛍ᛬ᚲᛌ᛫ |
Box Drawing |
0x2500-0x257F |
╬╠╫╋║╉╩┣╦╂╳╇╈┠╚┃╃┻╅┳┡┢┹╀╧┱╙┗┞┇┸┋┯┰┖╲╱┎╘━┭┕┍┅╾│┬┉╰╭╸└┆╺┊─╌┄┈╴╶ |
Block Elements |
0x2580-0x259F |
█▉▇▓▊▆▅▌▚▞▀▒▐▍▃▖▂░▁▏ |
Geometric Shapes |
0x25A0-0x25FF |
◙◘■▩●▦▣◚◛◕▨▧◉▤◐◒▮◍◑▼▪◤▬◗◭◖◈◎◮◊◫▰◄◯□▯▷▫▽◹△◁▸▭◅▵◌▱▹▿◠◃◦◟◞◜ |
Hiragana |
0x3040-0x309F |
ぽぼゑぜぬあおゆぎゐはせぢがきぱびほげばゟぁたかぞぷれひずどらさでけぉちごえすゎにづぇとょついこぐうぅぃくっしへゞゝ゚゙ |
Code:
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;
}