nuttx-apps/tools/bitmap_converter.py
Old-Ding f1d53c875d tools: format bitmap converter
Run the bitmap converter through the Python formatter required by checkpatch so the Python 3 print syntax fix passes the project style checks.

Signed-off-by: Old-Ding <35417409+Old-Ding@users.noreply.github.com>
2026-07-06 16:31:47 +08:00

163 lines
4.3 KiB
Python
Executable file

#!/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 os.path
import sys
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)