From ef3e0d464b3dd34d312c8ae1418b30c7d573f85b Mon Sep 17 00:00:00 2001 From: "Jan D. Behrens" Date: Tue, 28 Aug 2012 19:57:43 +0200 Subject: [PATCH] Improved PNG output for badges (now using zlib compression) --- xonstat/batch/badges/gen_badges.py | 5 ++-- xonstat/batch/badges/render.py | 38 ++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/xonstat/batch/badges/gen_badges.py b/xonstat/batch/badges/gen_badges.py index 712f7ad..c68e0ba 100644 --- a/xonstat/batch/badges/gen_badges.py +++ b/xonstat/batch/badges/gen_badges.py @@ -4,7 +4,6 @@ import sys from datetime import datetime import sqlalchemy as sa import sqlalchemy.sql.functions as func -from colorsys import rgb_to_hls, hls_to_rgb from pyramid.paster import bootstrap from xonstat.models import * @@ -12,7 +11,7 @@ from render import Skin # maximal number of query results (for testing, set to 0 to get all) -NUM_PLAYERS = 100 +#NUM_PLAYERS = 100 skin_classic = Skin() @@ -41,7 +40,7 @@ req.matchdict = {'id':3} print "Requesting player data from db ..." start = datetime.now() players = [] -if NUM_PLAYERS: +if locals().has_key('NUM_PLAYERS'): players = DBSession.query(Player).\ filter(Player.player_id == PlayerElo.player_id).\ filter(Player.nick != None).\ diff --git a/xonstat/batch/badges/render.py b/xonstat/batch/badges/render.py index f788f94..584688a 100644 --- a/xonstat/batch/badges/render.py +++ b/xonstat/batch/badges/render.py @@ -1,5 +1,7 @@ import re +import zlib, struct import cairo as C +from colorsys import rgb_to_hls, hls_to_rgb import sqlalchemy as sa import sqlalchemy.sql.functions as func from xonstat.models import * @@ -21,6 +23,30 @@ _dec_colors = [ (0.5,0.5,0.5), ] +def writepng(filename, buf, width, height): + width_byte_4 = width * 4 + # fix color ordering (BGR -> RGB) + for byte in xrange(width*height): + pos = byte * 4 + buf[pos:pos+4] = buf[pos+2] + buf[pos+1] + buf[pos+0] + buf[pos+3] + # merge lines + #raw_data = b"".join(b'\x00' + buf[span:span + width_byte_4] for span in xrange((height - 1) * width * 4, -1, - width_byte_4)) + raw_data = b"".join(b'\x00' + buf[span:span + width_byte_4] for span in range(0, (height-1) * width * 4 + 1, width_byte_4)) + def png_pack(png_tag, data): + chunk_head = png_tag + data + return struct.pack("!I", len(data)) + chunk_head + struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head)) + data = b"".join([ + b'\x89PNG\r\n\x1a\n', + png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)), + png_pack(b'IDAT', zlib.compress(raw_data, 9)), + png_pack(b'IEND', b'')]) + f = open(filename, "wb") + try: + f.write(data) + finally: + f.close() + + class Skin: # player data, will be filled by get_data() @@ -214,9 +240,8 @@ class Skin: if not txt or len(txt) == 0: # only colorcode and no real text, skip this continue - - r,g,b = _dec_colors[7] - try: + + if tag: if tag.startswith('x'): r = int(tag[1] * 2, 16) / 255.0 g = int(tag[2] * 2, 16) / 255.0 @@ -227,7 +252,7 @@ class Skin: r, g, b = hls_to_rgb(hue, light, satur) else: r,g,b = _dec_colors[int(tag[0])] - except: + else: r,g,b = _dec_colors[7] ctx.set_source_rgb(r, g, b) @@ -425,7 +450,10 @@ class Skin: # save to PNG - surf.write_to_png(output_filename) + #surf.write_to_png(output_filename) + surf.flush() + imgdata = surf.get_data() + writepng(output_filename, imgdata, self.width, self.height) def get_data(self, player): -- 2.39.2