| #!/usr/bin/env python |
| |
| '''This script converts from any image type supported by |
| Python imaging library to the RLE-encoded format used by |
| NxWidgets. |
| ''' |
| |
| from PIL import Image |
| |
| def get_palette(img, maxcolors = 255): |
| '''Returns a list of colors. If there are too many colors in the image, |
| the least used are removed. |
| ''' |
| img = img.convert("RGB") |
| colors = img.getcolors(65536) |
| colors.sort(key = lambda c: -c[0]) |
| return [c[1] for c in colors[:maxcolors]] |
| |
| def write_palette(outfile, palette): |
| '''Write the palette (normal and highlight) to the output file.''' |
| |
| outfile.write('static const NXWidgets::nxwidget_pixel_t palette[BITMAP_PALETTESIZE] =\n') |
| outfile.write('{\n') |
| |
| for i in range(0, len(palette), 4): |
| outfile.write(' ') |
| for r, g, b in palette[i:i+4]: |
| outfile.write('MKRGB(%3d,%3d,%3d), ' % (r, g, b)) |
| outfile.write('\n') |
| |
| outfile.write('};\n\n') |
| |
| outfile.write('static const NXWidgets::nxwidget_pixel_t hilight_palette[BITMAP_PALETTESIZE] =\n') |
| outfile.write('{\n') |
| |
| for i in range(0, len(palette), 4): |
| outfile.write(' ') |
| for r, g, b in palette[i:i+4]: |
| r = min(255, r + 50) |
| g = min(255, g + 50) |
| b = min(255, b + 50) |
| outfile.write('MKRGB(%3d,%3d,%3d), ' % (r, g, b)) |
| outfile.write('\n') |
| |
| outfile.write('};\n\n') |
| |
| |
| def quantize(color, palette): |
| '''Return the color index to closest match in the palette.''' |
| try: |
| return palette.index(color) |
| except ValueError: |
| # No exact match, search for the closest |
| def distance(color2): |
| return sum([(a - b)**2 for a, b in zip(color, color2)]) |
| |
| return palette.index(min(palette, key = distance)) |
| |
| |
| def encode_row(img, palette, y): |
| '''RLE-encode one row of image data.''' |
| entries = [] |
| color = None |
| repeats = 0 |
| |
| for x in range(0, img.size[0]): |
| c = quantize(img.getpixel((x, y)), palette) |
| if c == color and repeats < 255: |
| repeats += 1 |
| else: |
| if color is not None: |
| entries.append((repeats, color)) |
| |
| repeats = 1 |
| color = c |
| |
| if color is not None: |
| entries.append((repeats, color)) |
| |
| return entries |
| |
| def write_image(outfile, img, palette): |
| '''Write the image contents to the output file.''' |
| |
| outfile.write('static const NXWidgets::SRlePaletteBitmapEntry bitmap[] =\n') |
| outfile.write('{\n') |
| |
| for y in range(0, img.size[1]): |
| entries = encode_row(img, palette, y) |
| row = "" |
| for r, c in entries: |
| if len(row) > 60: |
| outfile.write(' ' + row + '\n') |
| row = "" |
| |
| row += '{%3d, %3d}, ' % (r, c) |
| |
| row += ' ' * (73 - len(row)) |
| outfile.write(' ' + row + '/* Row %d */\n' % y) |
| |
| outfile.write('};\n\n') |
| |
| |
| def write_descriptor(outfile, name): |
| '''Write the public descriptor structure for the image.''' |
| |
| outfile.write('extern const struct NXWidgets::SRlePaletteBitmap g_%s =\n' % name) |
| outfile.write('{\n') |
| outfile.write(' CONFIG_NXWIDGETS_BPP,\n') |
| outfile.write(' CONFIG_NXWIDGETS_FMT,\n') |
| outfile.write(' BITMAP_PALETTESIZE,\n') |
| outfile.write(' BITMAP_WIDTH,\n') |
| outfile.write(' BITMAP_HEIGHT,\n') |
| outfile.write(' {palette, hilight_palette},\n') |
| outfile.write(' bitmap\n') |
| outfile.write('};\n') |
| |
| if __name__ == '__main__': |
| import sys |
| import os.path |
| |
| if len(sys.argv) != 3: |
| print "Usage: bitmap_converter.py source.png output.cxx" |
| sys.exit(1) |
| |
| img = Image.open(sys.argv[1]).convert("RGB") |
| outfile = open(sys.argv[2], 'w') |
| palette = get_palette(img) |
| |
| outfile.write( |
| ''' |
| /* Automatically NuttX bitmap file. */ |
| /* Generated from %(src)s by bitmap_converter.py. */ |
| |
| #include <nxconfig.hxx> |
| #include <crlepalettebitmap.hxx> |
| |
| #define BITMAP_WIDTH %(width)s |
| #define BITMAP_HEIGHT %(height)s |
| #define BITMAP_PALETTESIZE %(palettesize)s |
| |
| ''' % {'src': sys.argv[1], 'width': img.size[0], 'height': img.size[1], |
| 'palettesize': len(palette)} |
| ) |
| |
| name = os.path.splitext(os.path.basename(sys.argv[1]))[0] |
| |
| write_palette(outfile, palette) |
| write_image(outfile, img, palette) |
| write_descriptor(outfile, name) |