| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals, print_function
- import os
- import math
- import sys
- from xml.dom import minidom
- import Image
- if sys.version_info[0] < 3:
- xrange = xrange
- else:
- xrange = range
- def _open_xml(path):
- file = open(path, "r")
- font_doc = minidom.parse(file)
- del file
- return font_doc
- class point:
- def __init__(self, x, y):
- self.dx = x
- self.dy = y
- def distSq(self):
- return self.dx * self.dx + self.dy * self.dy
- def copy(self):
- return point(self.dx, self.dy)
- def compare(g, p, x, y, offsetX, offsetY):
- other = g.get(x + offsetX, y + offsetY)
- other.dx += offsetX
- other.dy += offsetY
- if other.distSq() < p.distSq():
- return other
- return p
- class grid:
- def __init__(self, w, h):
- self.data = [None for x in range(w) for y in range(h)]
- self.w = w
- self.h = h
- def put(self, x, y, val):
- self.data[x + y * self.w] = val # .copy()
- def get(self, x, y):
- if x < 0 or y < 0:
- return point(9999, 9999)
- if x >= self.w or y >= self.h:
- return point(9999, 9999)
- return self.data[x + y * self.w].copy()
- def generateSD_pass(g):
- print("generateSD_pass...")
- get = g.get
- put = g.put
- w = g.w
- h = g.h
- cmp = compare
- xr = xrange
- for y in xr(h):
- for x in xr(w):
- p = get(x, y)
- p = cmp(g, p, x, y, -1, 0)
- p = cmp(g, p, x, y, 0, -1)
- p = cmp(g, p, x, y, -1, -1)
- p = cmp(g, p, x, y, 1, -1)
- put(x, y, p)
- for x in xr(w - 1, -1, -1):
- p = get(x, y)
- p = cmp(g, p, x, y, 1, 0)
- put(x, y, p)
- for y in xr(h - 1, -1, -1):
- for x in xr(w - 1, -1, -1):
- p = get(x, y)
- p = cmp(g, p, x, y, 1, 0)
- p = cmp(g, p, x, y, 0, 1)
- p = cmp(g, p, x, y, -1, 1)
- p = cmp(g, p, x, y, 1, 1)
- put(x, y, p)
- for x in xr(w):
- p = get(x, y)
- p = cmp(g, p, x, y, 1, 0)
- put(x, y, p)
- def generateSD(image):
- w = image.size[0]
- h = image.size[1]
- g = grid(w, h)
- grid1 = grid(w, h)
- grid2 = grid(w, h)
- data = image.load()
- getpixel = image.im.getpixel
- g1put = grid1.put
- g2put = grid2.put
- pZero = point(0, 0)
- pInf = point(9999, 9999)
- for y in range(h):
- for x in range(w):
- alpha = getpixel((x, y))[3]
- if alpha < 128:
- g1put(x, y, pZero)
- g2put(x, y, pInf)
- else:
- g1put(x, y, pInf)
- g2put(x, y, pZero)
- generateSD_pass(grid1)
- generateSD_pass(grid2)
- sd_image = Image.new("L", (w, h))
- data = sd_image.getdata()
- putpixel = sd_image.im.putpixel
- for y in range(h):
- for x in range(w):
- dist1 = int(math.sqrt(grid1.get(x, y).distSq()))
- dist2 = int(math.sqrt(grid2.get(x, y).distSq()))
- dist = dist1 - dist2
- dist = dist * 10
- dist += 128
- #dist = dist * 3 + 128
- if dist < 0:
- dist = 0
- if dist > 255:
- dist = 255
- putpixel((x, y), dist)
- return sd_image
- def downscaleAttr(el, attr, ds):
- v = el.getAttribute(attr)
- el.setAttribute(attr, str(int(v) / ds))
- def convert(args):
- xml_doc = _open_xml(args.bmfont)
- xml = xml_doc.documentElement
- folder, file = os.path.split(args.bmfont)
- if folder:
- folder += "/"
- pages = xml.getElementsByTagName("pages")[0].getElementsByTagName("page")
- downscale = args.scale
- for page in pages:
- image_file_name = page.getAttribute("file")
- image = Image.open(folder + image_file_name)
- image.load()
- #image = image.crop((0,0, 256, 256))
- w = image.size[0]
- h = image.size[1]
- sd_image = generateSD(image)
- sd_image = sd_image.resize(
- (w / downscale, h / downscale), Image.ANTIALIAS)
- sd_image_name = "sd_" + image_file_name
- sd_image.save(folder + sd_image_name, "PNG")
- page.setAttribute("file", sd_image_name)
- info_el = xml.getElementsByTagName("info")[0]
- downscaleAttr(info_el, "size", downscale)
- common_el = xml.getElementsByTagName("common")[0]
- downscaleAttr(common_el, "lineHeight", downscale)
- downscaleAttr(common_el, "base", downscale)
- downscaleAttr(common_el, "scaleW", downscale)
- downscaleAttr(common_el, "scaleH", downscale)
- new_font_xml = folder + "sd_" + file
- fileh = open(new_font_xml, "w")
- xml_doc.writexml(fileh)
- if __name__ == "__main__":
- import os
- import sys
- folder = os.path.split(os.path.abspath(__file__))[0] + "\\src"
- sys.path.append(folder)
- # print sys.path
- import argparse
- parser = argparse.ArgumentParser(
- description="convert xml bmfont to signed distance font")
- parser.add_argument("bmfont", help="src font")
- parser.add_argument(
- "-s", "--scale", help="scale factor", type=int, default=1)
- import xml_processor
- args = parser.parse_args()
- convert(args)
- #p = xml_processor.XmlProcessor(args)
- # p.process()
|