<filename>resource_generator/make_resources.py
#!/usr/bin/env python2
import json
import os
from PIL import Image
import sys

#returns tuple (name, height, width, payload)
#Serialization order is left-to-right, top-to-bottom, so for the eInk
#display all images have to be rotated 90 degrees counterclockwise
def make_image_array(file_path, rotate = False):
    im = Image.open(file_path)
    if rotate:
        im = im.rotate(rotate, expand=True)
    width, height = im.size
    print "Processing file %s color depth is %s, width %d, height %d" % (file_path, im.mode, width, height)
    rgb_im = im.convert('1') #make sure the color depth is 1-bit
    name = os.path.splitext(file_name)[0]

    payload = []
    for y in range(0,height):
        bit_list = [0] * 8
        bit_index = 0
        for x in range(0,width):
            pixel = rgb_im.getpixel((x,y))
            if pixel:
                bit_list[bit_index] = 1
            bit_index += 1
            if bit_index == 8:
                byte = 0
                for bit in bit_list:
                    byte = (byte << 1) | bit
                payload.append(byte)
                bit_index = 0
                bit_list = [0] * 8
        if bit_index % 8: #there is something left over in this row (row is not multiple of 8 bits)
            byte = 0
            for bit in bit_list:
                byte = (byte << 1) | bit
            payload.append(byte)
    return (name, height, width, payload)

def serialize_image_array(name, height, width, payload):
    print 'Serializing image array %s' % name
    header_output = 'extern const bitmap_t BITMAP_'+name+';\n'
    output = '\nstatic const uint8_t %s_payload[] ={\n' % name
    row = ''
    c = 0;
    for byte in payload:
        row += '0x%02X,' % byte
        c += 1
        if c > 9:
            c = 0
            row += '\n'
    row = row[0:-1] #get rid of last comma
    row += '};\n\n'
    output += row
    output += 'const bitmap_t BITMAP_%s = {.size_x=%d, .size_y=%d, .payload=%s_payload};\n' % (name, width, height, name)
    return (header_output, output)

#returns tuple (header, data) with header and .c code
def make_font_description(file_path):
    print 'Making font description from %s' % file_path
    input_description = json.loads(open(file_path).read())
    name = os.path.splitext(file_name)[0]
    output_header = '\nextern const font_t FONT_%s;\n' % name
    output_data = ''

    output_data += 'static const glyph_t FONT_GLYPHS_%s[] = {\n' % name
    counter = 0
    for g in input_description['symbols']:
        output_data += '{ .character=%d/*%c*/, .width=%d, .x_offset=%d },\n' % (g['id'], unichr(g['id']), g['width'], g['x'])
        counter += 1
    output_data += '};\n\n'

    output_data += '\nconst font_t FONT_%s = { .bitmap = &BITMAP_%s, .glyph_count = %d, .glyphs = FONT_GLYPHS_%s };\n\n' % (name, name, counter, name)
    
    return (output_header, output_data)

#----------------- main -----------------
try:
    source_path = sys.argv[1]
    destination_path = sys.argv[2]
except Exception:
    print "Usage: ./make_resource.py path_to_images path_to_output_C_files\n"
    sys.exit(1)

output_h_file = open(destination_path+'/resources.h', 'w')
output_c_file = open(destination_path+'/resources.c', 'w')

output_h_file.write('//AUTOGENERATED FILE! DO NOT EDIT!\n')
output_h_file.write('#include "graphic_types.h"\n')

output_c_file.write('//AUTOGENERATED FILE! DO NOT EDIT!\n')
output_c_file.write('#include "resources.h"\n')

rotation = 270

#serialize images
for file_name in os.listdir(source_path):
    if file_name.endswith(".png") or file_name.endswith(".PNG"):
        file_path = source_path+file_name
        name, height, width, payload = make_image_array(file_path, rotation)
        header, data = serialize_image_array(name, height, width, payload)
        output_h_file.write(header)
        output_c_file.write(data)

#serialize font descriptions - font description must come after bitmaps to compile properly
for file_name in os.listdir(source_path):
    if file_name.endswith(".json"):
        file_path = source_path+file_name
        header, data = make_font_description(file_path)
        print header
        output_h_file.write(header)
        output_c_file.write(data.encode('utf8'))

<filename>resource_generator/make_resources.py
#!/usr/bin/env python2
import json
import os
from PIL import Image
import sys

#returns tuple (name, height, width, payload)
#Serialization order is left-to-right, top-to-bottom, so for the eInk
#display all images have to be rotated 90 degrees counterclockwise
def make_image_array(file_path, rotate = False):
    im = Image.open(file_path)
    if rotate:
        im = im.rotate(rotate, expand=True)
    width, height = im.size
    print "Processing file %s color depth is %s, width %d, height %d" % (file_path, im.mode, width, height)
    rgb_im = im.convert('1') #make sure the color depth is 1-bit
    name = os.path.splitext(file_name)[0]

    payload = []
    for y in range(0,height):
        bit_list = [0] * 8
        bit_index = 0
        for x in range(0,width):
            pixel = rgb_im.getpixel((x,y))
            if pixel:
                bit_list[bit_index] = 1
            bit_index += 1
            if bit_index == 8:
                byte = 0
                for bit in bit_list:
                    byte = (byte << 1) | bit
                payload.append(byte)
                bit_index = 0
                bit_list = [0] * 8
        if bit_index % 8: #there is something left over in this row (row is not multiple of 8 bits)
            byte = 0
            for bit in bit_list:
                byte = (byte << 1) | bit
            payload.append(byte)
    return (name, height, width, payload)

def serialize_image_array(name, height, width, payload):
    print 'Serializing image array %s' % name
    header_output = 'extern const bitmap_t BITMAP_'+name+';\n'
    output = '\nstatic const uint8_t %s_payload[] ={\n' % name
    row = ''
    c = 0;
    for byte in payload:
        row += '0x%02X,' % byte
        c += 1
        if c > 9:
            c = 0
            row += '\n'
    row = row[0:-1] #get rid of last comma
    row += '};\n\n'
    output += row
    output += 'const bitmap_t BITMAP_%s = {.size_x=%d, .size_y=%d, .payload=%s_payload};\n' % (name, width, height, name)
    return (header_output, output)

#returns tuple (header, data) with header and .c code
def make_font_description(file_path):
    print 'Making font description from %s' % file_path
    input_description = json.loads(open(file_path).read())
    name = os.path.splitext(file_name)[0]
    output_header = '\nextern const font_t FONT_%s;\n' % name
    output_data = ''

    output_data += 'static const glyph_t FONT_GLYPHS_%s[] = {\n' % name
    counter = 0
    for g in input_description['symbols']:
        output_data += '{ .character=%d/*%c*/, .width=%d, .x_offset=%d },\n' % (g['id'], unichr(g['id']), g['width'], g['x'])
        counter += 1
    output_data += '};\n\n'

    output_data += '\nconst font_t FONT_%s = { .bitmap = &BITMAP_%s, .glyph_count = %d, .glyphs = FONT_GLYPHS_%s };\n\n' % (name, name, counter, name)
    
    return (output_header, output_data)

#----------------- main -----------------
try:
    source_path = sys.argv[1]
    destination_path = sys.argv[2]
except Exception:
    print "Usage: ./make_resource.py path_to_images path_to_output_C_files\n"
    sys.exit(1)

output_h_file = open(destination_path+'/resources.h', 'w')
output_c_file = open(destination_path+'/resources.c', 'w')

output_h_file.write('//AUTOGENERATED FILE! DO NOT EDIT!\n')
output_h_file.write('#include "graphic_types.h"\n')

output_c_file.write('//AUTOGENERATED FILE! DO NOT EDIT!\n')
output_c_file.write('#include "resources.h"\n')

rotation = 270

#serialize images
for file_name in os.listdir(source_path):
    if file_name.endswith(".png") or file_name.endswith(".PNG"):
        file_path = source_path+file_name
        name, height, width, payload = make_image_array(file_path, rotation)
        header, data = serialize_image_array(name, height, width, payload)
        output_h_file.write(header)
        output_c_file.write(data)

#serialize font descriptions - font description must come after bitmaps to compile properly
for file_name in os.listdir(source_path):
    if file_name.endswith(".json"):
        file_path = source_path+file_name
        header, data = make_font_description(file_path)
        print header
        output_h_file.write(header)
        output_c_file.write(data.encode('utf8'))

#!/usr/bin/env python2 #returns tuple (name, height, width, payload) #Serialization order is left-to-right, top-to-bottom, so for the eInk #display all images have to be rotated 90 degrees counterclockwise #make sure the color depth is 1-bit #there is something left over in this row (row is not multiple of 8 bits) #get rid of last comma #returns tuple (header, data) with header and .c code #----------------- main ----------------- #serialize images #serialize font descriptions - font description must come after bitmaps to compile properly