I am trying to do some dynamic programming based on the number of characters in a sentence. Which letter of the English alphabet takes up the most pixels on the screen?
问题:
回答1:
Hmm, let's see:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccccccccccccccccccccccc
dddddddddddddddddddddddddddddddddddddddd
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
ffffffffffffffffffffffffffffffffffffffff
gggggggggggggggggggggggggggggggggggggggg
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
llllllllllllllllllllllllllllllllllllllll
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
oooooooooooooooooooooooooooooooooooooooo
pppppppppppppppppppppppppppppppppppppppp
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
ssssssssssssssssssssssssssssssssssssssss
tttttttttttttttttttttttttttttttttttttttt
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
W wins.
Of course, this is a silly empirical experiment. There is no single answer to which letter is widest. It depends on the font. So you'll have to do a similar empirical experiment to figure out the answer for your environment. But the fact is, most fonts follow the same conventions, and capital W will be the widest.
回答2:
Further to Ned Batchelder's awesomely practical answer, because I came here wondering about digits:
0000000000000000000000000000000000000000
1111111111111111111111111111111111111111
2222222222222222222222222222222222222222
3333333333333333333333333333333333333333
4444444444444444444444444444444444444444
5555555555555555555555555555555555555555
6666666666666666666666666666666666666666
7777777777777777777777777777777777777777
8888888888888888888888888888888888888888
9999999999999999999999999999999999999999
回答3:
How about a programmatic solution?
var capsIndex = 65;
var smallIndex = 97
var div = document.createElement('div');
div.style.float = 'left';
document.body.appendChild(div);
var highestWidth = 0;
var elem;
for(var i = capsIndex; i < capsIndex + 26; i++) {
div.innerText = String.fromCharCode(i);
var computedWidth = window.getComputedStyle(div, null).getPropertyValue("width");
if(highestWidth < parseFloat(computedWidth)) {
highestWidth = parseFloat(computedWidth);
elem = String.fromCharCode(i);
}
}
for(var i = smallIndex; i < smallIndex + 26; i++) {
div.innerText = String.fromCharCode(i);
var computedWidth = window.getComputedStyle(div, null).getPropertyValue("width");
if(highestWidth < parseFloat(computedWidth)) {
highestWidth = parseFloat(computedWidth);
elem = String.fromCharCode(i);
}
}
div.innerHTML = '<b>' + elem + '</b>' + ' won';
回答4:
I believe the letter W
is the widest.
回答5:
Capital "M" is conventionally the widest.
回答6:
Depending on your platform, there might be a way to "getWidth" from a string or DrawText() function somehow with a width property.
I would make a simple algortime that utilized the needed font and then ran through the alfabet and stored it in a small config or just calculated it at initialization as a loop from A to Z isnt that hard.
回答7:
It also depends on the font. I did this 1 or 2 years ago with Processing and Helvetica and it is ILJTYFVCPAXUZKHSEDORGNBQMW in order of increasing pixels. The idea is to draw the text on a canvas with the font you are looking at, count the pixels, then sort with a HashMap or Dictionary.
Of course, this might not be directly relavant to your use as this calculates pixel area rather than just width. Might be a little overkill too.
void setup() {
size(30,30);
HashMap hm = new HashMap();
fill(255);
PFont font = loadFont("Helvetica-20.vlw");
textFont(font,20);
textAlign(CENTER);
for (int i=65; i<91; i++) {
background(0);
text(char(i),width/2,height-(textDescent()+textAscent())/2);
loadPixels();
int white=0;
for (int k=0; k<pixels.length; k++) {
white+=red(pixels[k]);
}
hm.put(char(i),white);
}
HashMap sorted = getSortedMap(hm);
String asciiString = new String();
for (Iterator<Map.Entry> i = sorted.entrySet().iterator(); i.hasNext();) {
Map.Entry me = (Map.Entry)i.next();
asciiString += me.getKey();
}
println(asciiString); //the string in ascending pixel order
}
public HashMap getSortedMap(HashMap hmap) {
HashMap map = new LinkedHashMap();
List mapKeys = new ArrayList(hmap.keySet());
List mapValues = new ArrayList(hmap.values());
TreeSet sortedSet = new TreeSet(mapValues);
Object[] sortedArray = sortedSet.toArray();
int size = sortedArray.length;
// a) Ascending sort
for (int i=0; i<size; i++) {
map.put(mapKeys.get(mapValues.indexOf(sortedArray[i])), sortedArray[i]);
}
return map;
}
回答8:
Arial 30px in Chrome - W wins.
回答9:
A solution to calculate the widths of fonts a bit like the solution posted by xxx was posted by Alex Michael on his blog (which funnily enough linked me here).
Summary:
- For Helvetica, the top three letters are: M (2493 pixels), W (2414) and B (1909).
- For a set of fonts that shipped with his Mac, the results are more or less the same: M (2217.51 ± 945.19), W (2139.06 ± 945.29) and B (1841.38 ± 685.26).
Original Post: http://alexmic.net/letter-pixel-count/
Code:
# -*- coding: utf-8 -*-
from __future__ import division
import os
from collections import defaultdict
from math import sqrt
from PIL import Image, ImageDraw, ImageFont
# Make a lowercase + uppercase alphabet.
alphabet = 'abcdefghijklmnopqrstuvwxyz'
alphabet += ''.join(map(str.upper, alphabet))
def draw_letter(letter, font, save=True):
img = Image.new('RGB', (100, 100), 'white')
draw = ImageDraw.Draw(img)
draw.text((0,0), letter, font=font, fill='#000000')
if save:
img.save("imgs/{}.png".format(letter), 'PNG')
return img
def count_black_pixels(img):
pixels = list(img.getdata())
return len(filter(lambda rgb: sum(rgb) == 0, pixels))
def available_fonts():
fontdir = '/Users/alex/Desktop/English'
for root, dirs, filenames in os.walk(fontdir):
for name in filenames:
path = os.path.join(root, name)
try:
yield ImageFont.truetype(path, 100)
except IOError:
pass
def letter_statistics(counts):
for letter, counts in sorted(counts.iteritems()):
n = len(counts)
mean = sum(counts) / n
sd = sqrt(sum((x - mean) ** 2 for x in counts) / n)
yield letter, mean, sd
def main():
counts = defaultdict(list)
for letter in alphabet:
for font in available_fonts():
img = draw_letter(letter, font, save=False)
count = count_black_pixels(img)
counts[letter].append(count)
for letter, mean, sd in letter_statistics(counts):
print u"{0}: {1:.2f} ± {2:.2f}".format(letter, mean, sd)
if __name__ == '__main__':
main()
回答10:
It will depend on the font. I would create a small program in a programming language you're most comfortable with, where you draw each letter of the alphabet into a n times m sized bitmap. Initialize each pixel with white. Then count the number of white pixels after you've drawn each letter and save that number. The highest number you find is the one you're looking for.
EDIT: If you're in fact just interested in which one takes up the largest rectangle (but it looks like you're really after that, not the pixels), you can use various API calls to find the size, but that depends on your programming language. In Java, for example, you would use the FontMetrics class.
回答11:
I know the accepted answer here is W, W is for WIN.
However, in this case, W is also for Width. The case study used employed a simple width test to examine pixels, but it was only the width, not the total pixel count. As an easy counter example, the accepted answer assumes that O and Q take up the same amount of pixels, yet they only take up the same amount of space.
Thus, W takes up the most space. But, is it all the pixels it's cracked up to be?
Let's get some empirical data. I created imgur images from the following B, M and W. I then analyzed their pixel count (see below), here are the results:
B : 114 pixels
M : 150 pixels
W : 157 pixels
Here is how I fed them into canvas and analyzed the raw pixel data from the images.
var imgs = {
B : "//i.imgur.com/YOuEPOn.png",
M : "//i.imgur.com/Aev3ZKQ.png",
W : "//i.imgur.com/xSUwE7w.png"
};
window.onload = function(){
for(var key in imgs){(function(img,key){
var Out = document.querySelector("#"+key+"Out");
img.crossOrigin = "Anonymous";
img.src=imgs[key];
img.onload = function() {
var canvas = document.querySelector('#'+key);
(canvas.width = img.width,canvas.height = img.height);
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
var data = context.getImageData(0, 0, img.width, img.height).data;
Out.innerHTML = "Total Pixels: " + data.length/4 + "<br>";
var pixelObject = {};
for(var i = 0; i < data.length; i += 4){
var rgba = "rgba("+data[i]+","+data[i+1]+","+data[i+2]+","+data[i+3]+")";
pixelObject[rgba] = pixelObject[rgba] ? pixelObject[rgba]+1 : 1;
}
Out.innerHTML += "Total Whitespace: " + pixelObject["rgba(255,255,255,255)"] + "<br>";
Out.innerHTML += "Total Pixels In "+ key +": " + ((data.length/4)-pixelObject["rgba(255,255,255,255)"]) + "<br>";
};
})(new Image(),key)}
};
<table>
<tr>
<td>
<canvas id="B" width="100%" height="100%"></canvas>
</td>
<td id="BOut">
</td>
</tr>
<tr>
<td>
<canvas id="M" width="100%" height="100%"></canvas>
</td>
<td id="MOut">
</td>
</tr>
<tr>
<td>
<canvas id="W" width="100%" height="100%"></canvas>
</td>
<td id="WOut">
</td>
</tr>
</table>
回答12:
It depends on the font. Crossed zero for example takes up considerably more than a regular one.
But if one could put up a guess, I'd go with X or B.