]> de.git.xonotic.org Git - xonotic/xonstat.git/commitdiff
Improved PNG output for badges (now using zlib compression)
authorJan D. Behrens <zykure@web.de>
Tue, 28 Aug 2012 17:57:43 +0000 (19:57 +0200)
committerJan D. Behrens <zykure@web.de>
Tue, 28 Aug 2012 18:26:40 +0000 (20:26 +0200)
xonstat/batch/badges/gen_badges.py
xonstat/batch/badges/render.py

index 712f7adf28d58b02931645ed50d4e35c12644266..c68e0ba442863f1794313eb424dc92522bf62f89 100644 (file)
@@ -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).\
index f788f9480ba50de7eec345d53387370eb8a59567..584688a86a9fbbda8ce5f4f5b0324fd38aa4b84c 100644 (file)
@@ -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):