Skip to content

Instantly share code, notes, and snippets.

@alterakey
Created September 12, 2011 08:09
Show Gist options
  • Save alterakey/1210806 to your computer and use it in GitHub Desktop.
Save alterakey/1210806 to your computer and use it in GitHub Desktop.
Rendering outlined font with FT2 + PIL
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# outline-char.py: POC of rendering outlined font with FT2 + PIL.
#
# Copyright (C) 2011 Takahiro Yoshimura <taky@cs.monolithworks.co.jp>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import struct
import freetype
import Image, ImageDraw
class FT2Bitmap(object):
def __init__(self, bitmap):
self.bitmap = bitmap
def to_pil_image(self):
data = ''.join([struct.pack('B', c) for c in self.bitmap.buffer])
return Image.frombuffer("L", (self.bitmap.width, self.bitmap.rows), data, "raw", "L", 0, 1)
class OutlinedGlyphWriter(object):
def __init__(self, char, face, size, outline, outline_color):
self.char = char
self.face_name = face
self.char_size = size
self.outline_width = outline
self.outline_color = outline_color
def write(self):
mask = self._write_glyph()
im = Image.new('RGBA', mask.size, (0,0,0,255))
draw = ImageDraw.Draw(im)
draw.bitmap((0, 0), mask, self.outline_color)
return im
def _load_glyph(self):
face = freetype.Face(self.face_name)
face.set_char_size(self.char_size * 64)
face.load_char(self.char, freetype.FT_LOAD_DEFAULT | freetype.FT_LOAD_NO_BITMAP)
return face.glyph.get_glyph()
def _write_base(self):
glyph = self._load_glyph()
stroker = freetype.Stroker()
stroker.set(self.outline_width * 64, freetype.FT_STROKER_LINECAP_ROUND, freetype.FT_STROKER_LINEJOIN_ROUND, 0 )
glyph.stroke(stroker)
bitmap = glyph.to_bitmap(freetype.FT_RENDER_MODE_NORMAL, freetype.Vector(0,0)).bitmap
return FT2Bitmap(bitmap).to_pil_image()
def _write_glyph(self):
base = self._write_base()
glyph = self._load_glyph()
bitmap = glyph.to_bitmap(freetype.FT_RENDER_MODE_NORMAL, freetype.Vector(0,0)).bitmap
mask = FT2Bitmap(bitmap).to_pil_image()
draw = ImageDraw.Draw(base)
draw.bitmap((self.outline_width, self.outline_width), mask, 0)
return base
if __name__ == '__main__':
face_name = u'./fonts/ヒラギノ角ゴ Std W6.otf'.encode('utf-8')
glyph_size = 1024
outline_width = 64
outline_color = (255,255,255,255)
char = u'あ'
im = OutlinedGlyphWriter(char, face_name, glyph_size, outline_width, outline_color).write()
im.show()
im.save('hoge.png', 'png')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment