GWの宿題的な何か
pypyのベンチマーク的な何か with Pillow(PIL)
# -*- coding:utf-8 -*- import os import re import threading from PIL import Image from bs4 import BeautifulSoup def transHue(img, huetype): img1 = img.copy() for hue in huetype.find_all(u"map"): c_from = [int(n.replace(u"*", u"-1")) for n in hue.get(u"from").split(u",")] c_to = [int(n.replace(u"*", u"-1")) for n in hue.get(u"to").split(u",")] + [255] # RGB + A try: c_idx = c_from.index(-1) except ValueError: c_idx = -1 img2 = Image.new(u"RGBA", img1.size, (255, 0, 255, 0)) for i in xrange(img1.size[0]): for j in xrange(img1.size[1]): img1_pixel = img1.getpixel((i,j)) if ((c_from[0] == -1 and img1_pixel[0] > 0) or c_from[0] == img1_pixel[0]) \ and ((c_from[1] == -1 and img1_pixel[1] > 0) or c_from[1] == img1_pixel[1]) \ and ((c_from[2] == -1 and img1_pixel[2] > 0) or c_from[2] == img1_pixel[2]): if c_idx == -1: img2.putpixel((i, j), c_to) else: img2.putpixel((i, j), map(lambda n: ((n * img1_pixel[c_idx]) >> 8) + 1, c_to)) else: img2.putpixel((i, j), img1_pixel) img1.close() img1 = img2 return img2 def decodeXml(filepath): re_ent = re.compile(u"<!ENTITY (.*?) '(.*?)'>", re.S) xml_raw = open(filepath).read().decode(u"cp932") xml_re = re_ent.findall(xml_raw) for group in xml_re or []: xml_raw = xml_raw.replace(u"&" + group[0] + u";", group[1]) return xml_raw.lower() class scrap: def __init__(self): self.pic_dic = {} self.img_list = [] self.soup = None self.lock = threading.RLock() self.semaphore = threading.BoundedSemaphore(32) def load(self, xml_raw): self.soup = BeautifulSoup(xml_raw) for picture in self.soup.find_all(u"picture"): pic_path = picture.get(u"src") if pic_path: contribution = picture.find_parent(u"contribution") if contribution: self.pic_dic[contribution.get('id')] = os.path.join(path, pic_path.replace(u"/", u"\\")) def basename(self, sprite, path): picture = sprite.find(u"picture") file = picture.get(u"src") file = os.path.join(path, file) if file else self.pic_dic[picture.get(u"ref")] return file def crop(self, sprite, size, filepath, opposite): org_x, org_y = [int(n) for n in sprite.get(u"origin").split(u",")] size_x, size_y = [int(n) for n in size.text.split(u",")] if opposite: size_x, size_y = size_y, size_x offset = int(sprite.get(u"offset")) img = Image.open(filepath).convert(u"RGB") base = Image.new(u"RGBA", img.size, (255, 0, 255, 0)) base.paste(img, (0, 0)) img.close() return base.crop((org_x, org_y, org_x + (size_x + size_y) * 16, org_y + offset + (1 + size_y) * 8)) def color(self, contribution, sprite, img, file): huetype = sprite.find(u"spritetype") if huetype: img_hue = transHue(img, huetype) img.close() self.lock.acquire() print "|>", self.img_list.append((img_hue, file)) self.lock.release() else: huetypes = contribution.find_all(u"spritetype") if huetypes: for huetype in huetypes: img_orig = img.copy() img_hue = transHue(img_orig, huetype) img_orig.close() self.lock.acquire() print "/>", self.img_list.append((img_hue, file)) self.lock.release() img.close() else: self.lock.acquire() print "->", self.img_list.append((img, file)) self.lock.release() def parse(self, path): threads = [] event = threading.Event() for contribution in self.soup.find_all(u"contribution"): thread = threading.Thread(target=self.encode, args=(path, contribution)) thread.start() threads.append(thread) for thread in threads: thread.join() def alpha(self, img1): img2 = Image.new(u"RGBA", img1.size, (255, 0, 255, 0)) for i in xrange(img1.size[0]): for j in xrange(img1.size[1]): img1_pixel = img1.getpixel((i, j)) if 255 == img1_pixel[0] and 0 == img1_pixel[1] and 255 == img1_pixel[2]: img2.putpixel((i, j), (255, 0, 255, 0)) else: img2.putpixel((i, j), img1_pixel + (255,)) img1.close() return img2 def tower(self, stack, size, path, opposite, floor_max): imgs = [self.alpha(self.crop(sprite, size, self.basename(sprite, path), opposite)) for sprite in stack] # MAX(MIDDLE_HEIGHT + BOTTOM_HEIGT + TOP_HEIGHT) height_max = max([imgs[1].size[1] + 16 * floor for floor in xrange(1, floor_max + 1)] \ + [imgs[2].size[1], imgs[0].size[1] + 16 * (floor_max + 1)]) background = Image.new(u"RGBA", (imgs[2].size[0], height_max), (255, 0, 255, 0)) # BOTTOM background.paste(imgs[2], (0, background.size[1] - imgs[2].size[1]), mask=imgs[2].split()[3]) # MIDDLE for floor in xrange(1, floor_max + 1): background.paste(imgs[1], (0, background.size[1] - imgs[1].size[1] - 16 * floor), mask=imgs[1].split()[3]) # TOP background.paste(imgs[0], (0, background.size[1] - imgs[0].size[1] - 16 * (floor_max + 1)), mask=imgs[0].split()[3]) return background, self.basename(stack[-1], path) def encode(self, path, contribution): self.semaphore.acquire() try: size = contribution.find(u"size") if size: sprite_list = contribution.find_all(u"sprite") if sprite_list: for sprite in sprite_list: opposite = sprite.get(u"opposite") != None filepath = self.basename(sprite, path) self.color(contribution, sprite, self.crop(sprite, size, filepath, opposite), filepath) else: height_min = contribution.find(u"minheight") height_min = int(height_min.text) if height_min else 2 height_max = contribution.find(u"maxheight") height_max = int(height_max.text) if height_max else 5 pictures_list = contribution.find_all(u"pictures") if pictures_list: for pictures in pictures_list: opposite = pictures.get(u"opposite") != None stack = [pictures.find(key) for key in [u"top", u"middle", u"bottom"]] if not None in stack: img, file = self.tower(stack, size, path, opposite, height_max - height_min) self.color(contribution, pictures, img, file) except Exception as e: self.lock.acquire() print "Error:", str(type(e)), e.message, contribution self.lock.release() self.semaphore.release() def makeTile(img_list, prefix): class img_set: def __init__(self, img1, size1): self.img = img1 self.x, self.y = size1 img_size = {} for img, file in img_list: if file not in img_size: img_size[file] = (0, 0) if img_size[file][1] < img.size[1]: img_size[file] = img.size img_type = {} for img, file in img_list: key = "_".join([str(s) for s in img_size[file]]) if key not in img_type: img_type[key] = [] img_type[key].append(img_set(img, img_size[file])) for filename, val1 in img_type.items(): width = val1[0].x base = Image.new(u"RGB", (width * len(val1), val1[0].y), (255, 0, 255)) for idx, val2 in enumerate(val1): base.paste(val2.img, (width * idx, val1[0].y - val2.img.size[1])) if width > 0: base.save(prefix + filename + u".bmp") base.close() def dirs(directory): for root, dirs, files in os.walk(directory): yield root, None for file in files: yield root, file if __name__ == '__main__': for path, file in dirs(u"."): if file == "plugin.xml": preload = scrap() preload.load(decodeXml(os.path.join(path, file))) for path, file in dirs(u"."): if file == "plugin.xml": imgs = scrap() imgs.pic_dic = preload.pic_dic imgs.load(decodeXml(os.path.join(path, file))) imgs.parse(path) makeTile(imgs.img_list, path.lower().replace(u"\\", u"_").replace(u".", u"_").replace(u"__", u"") + u"_")