235

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?

7
  • 18
    most pixels over all? Widest? Tallest? Which font? Can you specify? Commented Oct 16, 2010 at 15:10
  • 10
    Doesn't that depend on the font used? Commented Oct 16, 2010 at 15:11
  • 2
    Which font? Lowercase, upper? Commented Oct 16, 2010 at 15:16
  • yeah, guess it would have made sense to specify font!!! Arial in this case, but with Ned's patented test, I can figure it out with any font type! Commented Oct 16, 2010 at 16:17
  • 10
    Traditional typesetting wisdom is M or W for uppercase and m for lowercase. Depends on the font, but this works acceptably in the majority of cases. Commented Sep 5, 2012 at 19:54

15 Answers 15

863

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 most fonts follow the same conventions, and capital W will be the widest.

Gist with these character widths in a ratio form (W = 100) captured here using this particular example font:

https://gist.github.com/imaurer/d330e68e70180c985b380f25e195b90c

Sign up to request clarification or add additional context in comments.

7 Comments

In monospace, everybody win
Interestingly, in 'Arial Black' on my MacBook in Chrome, lowercase m is the widest, by a small margin.
How about this ........................................ WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ................................................................... so i think the @ wins!!
PRO TIP: I had the same question, specific to Trebuchet MS font. I used Chrome dev tools to change the font-family on the answer and on the comments: body p, body .comment-copy { font-family: Trebuchet MS; } SO is using 'Helvetica Neue' for all body text, including the answer (15px) and the comments (13px). In this font, the 'W' is the biggest letter with the '@' symbol bigger than the 'W' character. In 'Trebuchet MS' font-family, 'W' is still the biggest letter, but the '@' symbol is smaller.
So W is actually not an upside down M. I've been wrong all these years!
|
162

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

10 Comments

I doubted this info, thinking a '1' would surely be more narrow than other digits. But in the fonts I've checked, all the digits have the same width. I suppose that's a font design choice.
At least for me (viewing this post in Firefox in Ubuntu), 1 is more narrow than others, and others are all same width.
@MestreLion: Which font are you using? Face, size, and any modifiers, such as boldness or italics.
@LukeTaylor -- Why so it is! font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 15px; Oh, that Apple, always trying to be a little bit different....
This actually depends on font-variant-numeric: proportional numerals allow different widths, both in the glyph and the spacing, while tabular numerals must follow similar rules to monospaced fonts.
|
31

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';

1 Comment

Both "M" and "W" has same number of pixels. Since most answers say "W" its better to show M and W are same and won. By the way very nice answer.
19

Capital "M" is conventionally the widest.

2 Comments

Thus the reason for the unit of measurement called "em" en.m.wikipedia.org/wiki/Em_(typography)
@marc_s: JAnderton's answer seems to support this answer.
15

I believe the letter W is the widest.

Comments

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;
}

Comments

5

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.

Comments

5

Arial 30px in Chrome - W wins.

Comments

4

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()

Comments

4

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>

Comments

4

Want to know the real longest glyph, not just guessing?
And I'm not just talking about the letters, digits and common symbols (!, @ and so on). I mean the longest glyph in all the 32,834 characters of UTF-16.
So I started with answer by @NK that had a programmatic solution to it, and made a modification:

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 < 32834; 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';

After running this and waiting (and waiting), it gives the output ௌ won.
And there you have it, the longest character in UTF-32! Note that on most fonts the longest glyph is ﷽, but some fonts (especially monospace ones) overlap the characters, as with the font that the program was run with.

1 Comment

Original question is about English alphabet. You can make a separate question and answer your question.
0

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.

Comments

0

Or if you want to have a map of widths, containing more than just alpha(numeric) characters like described above (like I needed in a non-browser environment)

const chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "!", "\"", "#", "$", "%", "'", "(", ")", "*", "+", ",", "-", ".", "/", ":", ";", "=", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", " ", "&", ">", "<"]

const test = document.createElement('div')
test.id = "Test"
document.body.appendChild(test)
test.style.fontSize = 12

const result = {}

chars.forEach(char => {
  let newStr = ""
  for (let i = 0; i < 10; i++) {
    if (char === " ") {
      newStr += "&nbsp;"
    } else {
      newStr += char
    }  
  }
  test.innerHTML = newStr
  const width = (test.clientWidth)
  result[char] = width / 10
})

console.log('RESULT:', result)
#Test
{
    position: absolute;
    /* visibility: hidden; */
    height: auto;
    width: auto;
    white-space: nowrap; /* Thanks to Herb Caudill comment */
}

Comments

0

This code will get widths for all characters as array:

        const alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        var widths = [];
        
        var div = document.createElement('div');
        div.style.float = 'left';
        document.body.appendChild(div);
        
        var highestObservedWidth = 0;
        // widest characters (not just one)
        var answer = '';
        
        for (var i = 0; i < alphabet.length; i++) {
            div.innerText = alphabet[i];
            var computedWidthString = window.getComputedStyle(div, null).getPropertyValue("width");
            var computedWidth = parseFloat(computedWidthString.slice(0, -2));
    //      console.log(typeof(computedWidth));
            widths[i] = computedWidth;
            if(highestObservedWidth == computedWidth) {
                answer = answer + ', ' + div.innerText;
            }
            if(highestObservedWidth < computedWidth) {
                highestObservedWidth = computedWidth;
                answer = div.innerText;
            }
        }
        if (answer.length == 1) {
            div.innerHTML = ' Winner: ' + answer + '.';
        } else {
            div.innerHTML = ' Winners: ' + answer + '.';
        }
        div.innerHTML = div.innerHTML ;
//      console.log(widths);
//      console.log(widths.sort((a, b) => a - b));

Comments

-3

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.