mirror of
https://github.com/apache/nuttx.git
synced 2025-12-13 15:12:38 +08:00
drivers/video/fb.c: Add startup splashscreen option
Adds Kconfig-selected splashscreen options used when the driver is first registered * Includes a new Python script in ./tools to create RLE bitmap files * Includes default NS logo btimaps in 320x320, 160x160 and 80x80 resolutions along with their PNG files Signed-off-by: Tim Hardisty timh@jti.uk.com>
This commit is contained in:
committed by
Alan C. Assis
parent
b333ad3ab5
commit
ed0c18c66c
256
tools/splashscreen_converter.py
Executable file
256
tools/splashscreen_converter.py
Executable file
@@ -0,0 +1,256 @@
|
||||
#!/usr/bin/env python3
|
||||
# tools/splashscreen_converter.py
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
"""This script converts from any image type supported by
|
||||
Python imaging library to the RLE-encoded format used by
|
||||
the framebuffer splashscreen feature.
|
||||
"""
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def get_palette(img, maxcolors=256):
|
||||
"""Returns a list of colours. If there are too many colours in the image,
|
||||
the least used are removed.
|
||||
"""
|
||||
|
||||
colors = img.getcolors(65536)
|
||||
colors.sort(key=lambda c: -c[0])
|
||||
return [c[1] for c in colors[:maxcolors]]
|
||||
|
||||
|
||||
def write_palette(outfile, palette, type):
|
||||
"""Write the palette to the output file."""
|
||||
|
||||
if type == "ARGB":
|
||||
outfile.write("#ifdef CONFIG_VIDEO_FB_SPLASHSCREEN_BPP32\n")
|
||||
outfile.write("static const fb_pixel_t palette[] =\n")
|
||||
outfile.write("{\n")
|
||||
|
||||
for i in range(0, len(palette), 4):
|
||||
for r, g, b, a in palette[i : i + 4]:
|
||||
outfile.write(" MKRGB(%d, %d, %d, %d),\n" % (a, r, g, b))
|
||||
|
||||
outfile.write("};\n")
|
||||
outfile.write("#endif\n\n")
|
||||
|
||||
elif type == "RGB":
|
||||
outfile.write("#if defined(CONFIG_VIDEO_FB_SPLASHSCREEN_BPP24) || \\\n")
|
||||
outfile.write(" defined(CONFIG_VIDEO_FB_SPLASHSCREEN_BPP16) || \\\n")
|
||||
outfile.write(" defined(CONFIG_VIDEO_FB_SPLASHSCREEN_BPP8)\n")
|
||||
outfile.write("static const fb_pixel_t palette[] =\n")
|
||||
outfile.write("{\n")
|
||||
|
||||
for i in range(0, len(palette), 4):
|
||||
for r, g, b in palette[i : i + 4]:
|
||||
outfile.write(" MKRGB(%d, %d, %d),\n" % (r, g, b))
|
||||
|
||||
outfile.write("};\n")
|
||||
outfile.write("#endif\n\n")
|
||||
|
||||
else:
|
||||
outfile.write("#if defined(CONFIG_VIDEO_FB_SPLASHSCREEN_GREY) || \\\n")
|
||||
outfile.write(" defined(CONFIG_VIDEO_FB_SPLASHSCREEN_MONO)\n")
|
||||
outfile.write("static const fb_pixel_t palette[] =\n{\n};\n")
|
||||
outfile.write("#endif\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, type):
|
||||
"""RLE-encode one row of image data."""
|
||||
|
||||
color = None
|
||||
entries = []
|
||||
repeats = 0
|
||||
|
||||
for x in range(0, img.width):
|
||||
if type == "BPP32" or type == "BPP24" or type == "BPP16":
|
||||
c = quantize(img.getpixel((x, y)), palette)
|
||||
else:
|
||||
c = img.getpixel((x, y))
|
||||
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, suffix):
|
||||
"""Write the image contents to the output file."""
|
||||
|
||||
if suffix == "BPP24" or suffix == "BPP16":
|
||||
outfile.write("#if defined(CONFIG_VIDEO_FB_SPLASHSCREEN_BPP24) || \\")
|
||||
outfile.write("\n defined(CONFIG_VIDEO_FB_SPLASHSCREEN_BPP16)\n")
|
||||
else:
|
||||
outfile.write("#ifdef CONFIG_VIDEO_FB_SPLASHSCREEN_%s\n" % suffix)
|
||||
outfile.write("static const struct splscr_bitmap_s bitmap[] =\n")
|
||||
outfile.write("{")
|
||||
for y in range(0, img.height):
|
||||
entries = encode_row(img, palette, y, suffix)
|
||||
for r, c in entries:
|
||||
outfile.write("\n")
|
||||
row = " {%d, %d}," % (r, c)
|
||||
outfile.write(row)
|
||||
|
||||
outfile.write(("/* End of row %3d */" % (y + 1)).rjust(78 - len(row), " "))
|
||||
|
||||
outfile.write("\n};\n")
|
||||
outfile.write("#endif /* CONFIG_VIDEO_FB_SPLASHSCREEN_%s */\n\n" % suffix)
|
||||
|
||||
|
||||
def write_descriptor(outfile, name):
|
||||
outfile.write("const struct palette_bitmap_s g_%s =\n" % name)
|
||||
outfile.write("{\n")
|
||||
lw = len(str(img.width))
|
||||
lh = len(str(img.height))
|
||||
outfile.write(" %d," % img.width)
|
||||
outfile.write(
|
||||
("/* width in pixels */\n").rjust(
|
||||
76 - lw, " "
|
||||
)
|
||||
)
|
||||
outfile.write(" %d," % img.height)
|
||||
outfile.write(
|
||||
("/* height in pixels */\n").rjust(
|
||||
76 - lh, " "
|
||||
)
|
||||
)
|
||||
outfile.write(
|
||||
(
|
||||
" palette, /* Colour palette */\n"
|
||||
).rjust(76, " ")
|
||||
)
|
||||
outfile.write(
|
||||
(
|
||||
" bitmap, /* Pointer to the start of the RLE data */\n"
|
||||
).rjust(76, " ")
|
||||
)
|
||||
outfile.write("};\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: splashscreen_converter.py image.xxx output_directory out.c")
|
||||
print(
|
||||
"\t- image.xxx\t\tis the image file (e.g. logo.png) in a format supported by PIL"
|
||||
)
|
||||
print("\t- output_directory\tis where the output file will be saved.")
|
||||
print("\t- out.c\t\t\tis the name of the output file.")
|
||||
print("\t\t\t\t- If out.c is not specified it will default to fb_splash.c,")
|
||||
print("\t\t\t\t which is the name required for custom splashscreens")
|
||||
sys.exit(1)
|
||||
elif len(sys.argv) == 3:
|
||||
path = sys.argv[2]
|
||||
filename = "fb_splash.c"
|
||||
else:
|
||||
path = os.path.relpath(sys.argv[2])
|
||||
filename = sys.argv[3]
|
||||
img = Image.open(sys.argv[1]).convert("RGBA")
|
||||
file = os.path.realpath(path + "/" + filename)
|
||||
outfile = open(file, "w")
|
||||
palette_argb = get_palette(img)
|
||||
palette_rgb = get_palette(img.convert("RGB"))
|
||||
outfile.write(
|
||||
"""/****************************************************************************
|
||||
* %(file)s
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Script-generated framebuffer splashscreen bitmap file.
|
||||
* Generated from %(src)s
|
||||
* by splashscreen_converter.py
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/video/fb.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
"""
|
||||
% {"file": path + "/" + filename, "src": os.path.relpath(sys.argv[1])}
|
||||
)
|
||||
|
||||
name = "splscr"
|
||||
|
||||
write_palette(outfile, palette_argb, "ARGB")
|
||||
write_palette(outfile, palette_rgb, "RGB")
|
||||
write_palette(outfile, None, None)
|
||||
write_image(outfile, img, palette_argb, "BPP32")
|
||||
write_image(outfile, img.convert("RGB"), palette_rgb, "BPP24")
|
||||
write_image(outfile, img.convert("L"), None, "GREY")
|
||||
write_image(outfile, img.convert("1"), None, "MONO")
|
||||
write_descriptor(outfile, name)
|
||||
outfile.write(
|
||||
"""
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
"""
|
||||
)
|
||||
print("Created %s from %s" % (file, sys.argv[1]))
|
||||
Reference in New Issue
Block a user