2009-10-05 18:57:32 -04:00
|
|
|
#!/usr/bin/python
|
|
|
|
|
|
|
|
# This script is a slightly modified version of the original found at
|
|
|
|
#
|
2017-07-04 15:15:14 -04:00
|
|
|
# https://wiki.wxwidgets.org/Embedding_PNG_Images-Bin2c_In_Python
|
2009-10-05 18:57:32 -04:00
|
|
|
#
|
|
|
|
# without any copyright attribution so it is assumed it can be used under
|
|
|
|
# wxWindows licence as the rest of the wiki material.
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import os.path
|
|
|
|
import re
|
|
|
|
import array
|
|
|
|
|
2010-12-31 12:38:40 -05:00
|
|
|
USAGE = """Usage: png2c [-s] [file...]
|
|
|
|
Output input PNG files as C arrays to standard output. Used to embed PNG images
|
|
|
|
in C code (like XPM but with full alpha channel support).
|
|
|
|
|
|
|
|
-s embed the image size in the image names in generated code."""
|
2009-10-05 18:57:32 -04:00
|
|
|
|
|
|
|
if len(sys.argv) < 2:
|
|
|
|
print USAGE
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
r = re.compile("^([a-zA-Z._][a-zA-Z._0-9]*)[.][pP][nN][gG]$")
|
|
|
|
|
2010-12-31 12:38:40 -05:00
|
|
|
with_size = 0
|
|
|
|
size_suffix = ''
|
2009-10-05 18:57:32 -04:00
|
|
|
for path in sys.argv[1:]:
|
2010-12-31 12:38:40 -05:00
|
|
|
if path == '-s':
|
|
|
|
with_size = 1
|
|
|
|
continue
|
|
|
|
|
2010-12-31 12:38:29 -05:00
|
|
|
filename = os.path.basename(path).replace('-','_')
|
2009-10-05 18:57:32 -04:00
|
|
|
m = r.match(filename)
|
2010-12-31 12:38:40 -05:00
|
|
|
|
|
|
|
# Allow only filenames that make sense as C variable names
|
2009-10-05 18:57:32 -04:00
|
|
|
if not(m):
|
|
|
|
print "Skipped file (unsuitable filename): " + filename
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Read PNG file as character array
|
|
|
|
bytes = array.array('B', open(path, "rb").read())
|
|
|
|
count = len(bytes)
|
|
|
|
|
2010-12-31 12:38:40 -05:00
|
|
|
# Check that it's actually a PNG to avoid problems when loading it
|
|
|
|
# later.
|
|
|
|
#
|
|
|
|
# Each PNG file starts with a 8 byte signature that should be followed
|
|
|
|
# by IHDR chunk which is always 13 bytes in length so the first 16
|
|
|
|
# bytes are fixed (or at least we expect them to be).
|
|
|
|
if bytes[0:16].tostring() != '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR':
|
|
|
|
print '"%s" doesn\'t seem to be a valid PNG file.' % filename
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Try to naively get its size if necessary
|
|
|
|
if with_size:
|
2011-02-08 08:36:06 -05:00
|
|
|
def getInt(start):
|
|
|
|
""" Convert 4 bytes in network byte order to an integer. """
|
|
|
|
return 16777216*bytes[start] + \
|
|
|
|
65536*bytes[start+1] + \
|
|
|
|
256*bytes[start+2] + \
|
|
|
|
bytes[start+3];
|
|
|
|
|
|
|
|
size_suffix = "_%dx%d" % (getInt(16), getInt(20))
|
2010-12-31 12:38:40 -05:00
|
|
|
|
2009-10-05 18:57:32 -04:00
|
|
|
# Create the C header
|
|
|
|
text = "/* %s - %d bytes */\n" \
|
2010-12-31 12:38:40 -05:00
|
|
|
"static const unsigned char %s%s_png[] = {\n" % (
|
|
|
|
filename, count, m.group(1), size_suffix)
|
2009-10-05 18:57:32 -04:00
|
|
|
|
|
|
|
# Iterate the characters, we want
|
|
|
|
# lines like:
|
|
|
|
# 0x01, 0x02, .... (8 values per line maximum)
|
|
|
|
i = 0
|
|
|
|
count = len(bytes)
|
|
|
|
for byte in bytes:
|
|
|
|
# Every new line starts with two whitespaces
|
|
|
|
if (i % 8) == 0:
|
|
|
|
text += " "
|
|
|
|
# Then the hex data (up to 8 values per line)
|
|
|
|
text += "0x%02x" % (byte)
|
|
|
|
# Separate all but the last values
|
|
|
|
if (i % 8) == 7:
|
2010-12-31 12:38:40 -05:00
|
|
|
text += ',\n'
|
|
|
|
elif (i + 1) < count:
|
|
|
|
text += ", "
|
2009-10-05 18:57:32 -04:00
|
|
|
i += 1
|
|
|
|
|
|
|
|
# Now conclude the C source
|
|
|
|
text += "};\n\n"
|
|
|
|
|
|
|
|
print text
|