]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/bin/python | |
2 | ||
3 | # This script is a slightly modified version of the original found at | |
4 | # | |
5 | # http://wiki.wxwidgets.org/Embedding_PNG_Images-Bin2c_In_Python | |
6 | # | |
7 | # without any copyright attribution so it is assumed it can be used under | |
8 | # wxWindows licence as the rest of the wiki material. | |
9 | ||
10 | import sys | |
11 | import os | |
12 | import os.path | |
13 | import re | |
14 | import array | |
15 | ||
16 | USAGE = """Usage: png2c [-s] [file...] | |
17 | Output input PNG files as C arrays to standard output. Used to embed PNG images | |
18 | in C code (like XPM but with full alpha channel support). | |
19 | ||
20 | -s embed the image size in the image names in generated code.""" | |
21 | ||
22 | if len(sys.argv) < 2: | |
23 | print USAGE | |
24 | sys.exit(1) | |
25 | ||
26 | r = re.compile("^([a-zA-Z._][a-zA-Z._0-9]*)[.][pP][nN][gG]$") | |
27 | ||
28 | with_size = 0 | |
29 | size_suffix = '' | |
30 | for path in sys.argv[1:]: | |
31 | if path == '-s': | |
32 | with_size = 1 | |
33 | continue | |
34 | ||
35 | filename = os.path.basename(path).replace('-','_') | |
36 | m = r.match(filename) | |
37 | ||
38 | # Allow only filenames that make sense as C variable names | |
39 | if not(m): | |
40 | print "Skipped file (unsuitable filename): " + filename | |
41 | continue | |
42 | ||
43 | # Read PNG file as character array | |
44 | bytes = array.array('B', open(path, "rb").read()) | |
45 | count = len(bytes) | |
46 | ||
47 | # Check that it's actually a PNG to avoid problems when loading it | |
48 | # later. | |
49 | # | |
50 | # Each PNG file starts with a 8 byte signature that should be followed | |
51 | # by IHDR chunk which is always 13 bytes in length so the first 16 | |
52 | # bytes are fixed (or at least we expect them to be). | |
53 | if bytes[0:16].tostring() != '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR': | |
54 | print '"%s" doesn\'t seem to be a valid PNG file.' % filename | |
55 | continue | |
56 | ||
57 | # Try to naively get its size if necessary | |
58 | if with_size: | |
59 | def getInt(start): | |
60 | """ Convert 4 bytes in network byte order to an integer. """ | |
61 | return 16777216*bytes[start] + \ | |
62 | 65536*bytes[start+1] + \ | |
63 | 256*bytes[start+2] + \ | |
64 | bytes[start+3]; | |
65 | ||
66 | size_suffix = "_%dx%d" % (getInt(16), getInt(20)) | |
67 | ||
68 | # Create the C header | |
69 | text = "/* %s - %d bytes */\n" \ | |
70 | "static const unsigned char %s%s_png[] = {\n" % ( | |
71 | filename, count, m.group(1), size_suffix) | |
72 | ||
73 | # Iterate the characters, we want | |
74 | # lines like: | |
75 | # 0x01, 0x02, .... (8 values per line maximum) | |
76 | i = 0 | |
77 | count = len(bytes) | |
78 | for byte in bytes: | |
79 | # Every new line starts with two whitespaces | |
80 | if (i % 8) == 0: | |
81 | text += " " | |
82 | # Then the hex data (up to 8 values per line) | |
83 | text += "0x%02x" % (byte) | |
84 | # Separate all but the last values | |
85 | if (i % 8) == 7: | |
86 | text += ',\n' | |
87 | elif (i + 1) < count: | |
88 | text += ", " | |
89 | i += 1 | |
90 | ||
91 | # Now conclude the C source | |
92 | text += "};\n\n" | |
93 | ||
94 | print text |