2

I want to get 26 files (for starters): A.ico, B.ico, ... Z.ico, where they are composed of 16x16 256-color image, and a 32x32 256-color image, where the color of the text is black, and the font is ... say Calibri, and the size - whatever fits best into the square. I would like to do this using Python Image Library if possible.

I know that I can probably get my icons through other means, but I would like to learn to use the PIL better, and would like to use it for the task at hand.

Hamish Grubijan
  • 10,562
  • 23
  • 99
  • 147
  • If you want to learn to use PIL, why are you asking us? Go through the tutorial, then come back here with specific questions about the things you still don't know how to do. Try to write some code and show it to us. As stated, this is not a real question. – agf Aug 18 '11 at 16:23
  • @agf, I am not sure how to approach the part where I create arbitrary text and then scale it to fit into a specific square. Any pointers? – Hamish Grubijan Aug 18 '11 at 16:25
  • If you have a more specific question, __edit it in to your question__, don't ask it in a comment. – agf Aug 18 '11 at 16:26

2 Answers2

2

Start with a large blank image and draw the character on the center of it. Find the edges of the character and extract a square from the image that includes all of the character. Use the thumbnail function with the ANTIALIAS option to reduce it to the 16x16 or 32x32 size required. Then reduce the number of colors to 256: How to reduce color palette with PIL

Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Cool! Do you know whether PIL can pack two images into an ico file? Where in the tutorial should I look for it? – Hamish Grubijan Aug 18 '11 at 18:43
  • @Hamish, sorry I don't know how to pack multiple icons into a single file. You might have some luck asking this specific part as a new question. – Mark Ransom Aug 18 '11 at 20:40
2

This is based on the answer by @Mark Ransom. Thank you, Mark! This worked for me, though the 'blackify' function is imperfect still. I still need to figure out how to create an .ico file without using icotool for Linux.

# This script generates icon files from the two images.
# Uses Python 2.6.5, uses the Python Imaging Library

import Image
import ImageDraw
import ImageFont

letters = [chr(i + ord('A')) for i in range(26)]
default_huge =  ImageFont.load_default()
large_size = 1000
lim = large_size + 1

# Apparently I can use the same size for the font.
calibri_huge = ImageFont.truetype("calibri.ttf", large_size)

def crop_letter(img):
    minx, maxx, miny, maxy = lim, -lim, lim, -lim
    for x in range(large_size):
        for y in range(large_size):
            if sum(img.getpixel((x, y))) == 3 * 255: continue
            # Else, found a black pixel
            minx = min(minx, x)
            maxx = max(maxx, x)
            miny = min(miny, y)
            maxy = max(maxy, y)
    return img.crop(box = (minx, miny, maxx, maxy))

# This works for me 95% of the time
def blackify(color):
    return 255 * (color > 240)

for letter in letters:
    # A bit wasteful, but I have plenty of RAM.
    img = Image.new("RGB", (large_size, large_size), "white")
    draw = ImageDraw.Draw(img)
    draw.text((0,0), letter, font = calibri_huge, fill = "black")

    img32 = crop_letter(img)
    img16 = img32.copy()

    img32.thumbnail((32, 32), Image.ANTIALIAS)
    img16.thumbnail((16, 16), Image.ANTIALIAS)

    img32 = Image.eval(img32, blackify)
    img16 = Image.eval(img16, blackify)

##  Not needed
##    # Apparently this is all it takes to get 256 colors.
##    img32 = img32.convert('P')
##    img16 = img16.convert('P')

    img32.save('icons3/{0}32x32.bmp'.format(letter))
    img16.save('icons3/{0}16x16.bmp'.format(letter))
#    break

print('DONE!')
Hamish Grubijan
  • 10,562
  • 23
  • 99
  • 147