2024-10-20 08:19:33 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
# Convert png icons to bitmap.hpp inspired by
|
|
|
|
# make_bitmap.py - Copyright (C) 2016 Furrtek
|
|
|
|
# Convert bitmap.hpp to icons inspyred by
|
|
|
|
# bitmap_arr_reverse_decode.py - Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
|
|
|
# bitmap_arr_reverse_decode.py - Copyleft (ɔ) 2024 zxkmm with the GPL license
|
|
|
|
# Copysomething (c) 2024 LupusE with the license, needed by the PortaPack project
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
# any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; see the file COPYING. If not, write to
|
|
|
|
# the Free Software Foundation, Inc., 51 Franklin Street,
|
|
|
|
# Boston, MA 02110-1301, USA.
|
|
|
|
#
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import numpy as np
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
from PIL import Image
|
|
|
|
|
|
|
|
### Convert a directory of icons in png format to one bitmap.hpp file.
|
|
|
|
######################################################################
|
|
|
|
|
|
|
|
def pp_bitmaphpp_header():
|
|
|
|
return ("""/*
|
|
|
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
|
|
|
* Copyright (C) 2016 Furrtek
|
|
|
|
*
|
|
|
|
* This file is part of PortaPack.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; see the file COPYING. If not, write to
|
|
|
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// This file was generated by make_bitmap.py
|
|
|
|
|
|
|
|
#ifndef __BITMAP_HPP__
|
|
|
|
#define __BITMAP_HPP__
|
|
|
|
|
|
|
|
#include \"ui.hpp\"
|
|
|
|
|
|
|
|
namespace ui {
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
|
|
def convert_png(file):
|
|
|
|
bmp_data = []
|
|
|
|
data = 0
|
|
|
|
|
|
|
|
rgb_im = Image.open(file).convert('RGBA')
|
|
|
|
|
|
|
|
if rgb_im.size[0] % 8 or rgb_im.size[1] % 8:
|
|
|
|
print((file + ": Size is not a multiple of 8. Image is not included in bitmap.hpp."))
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
name = os.path.basename(file).split(".")[0].lower()
|
|
|
|
|
|
|
|
bmp_data.append(f"\nstatic constexpr uint8_t bitmap_{name}_data[] = {{\n")
|
|
|
|
|
|
|
|
for i in range(rgb_im.size[1]):
|
|
|
|
for j in range(rgb_im.size[0]):
|
|
|
|
r, g, b, a = rgb_im.getpixel((j, i))
|
|
|
|
|
|
|
|
data >>= 1
|
|
|
|
|
|
|
|
if r > 127 and g > 127 and b > 127 and a > 127:
|
|
|
|
data += 128
|
|
|
|
|
|
|
|
if j % 8 == 7:
|
|
|
|
bmp_data.append(" 0x%0.2X,\n" % data)
|
|
|
|
data = 0
|
|
|
|
|
|
|
|
bmp_data.append(f"""}};
|
|
|
|
static constexpr Bitmap bitmap_{name}{{
|
|
|
|
{{{str(rgb_im.size[0])}, {str(rgb_im.size[1])}}},
|
|
|
|
bitmap_{name}_data}};
|
|
|
|
""")
|
|
|
|
|
|
|
|
out_bmpdata = ''.join(map(str, bmp_data))
|
|
|
|
|
|
|
|
return (out_bmpdata)
|
|
|
|
|
|
|
|
def pp_bitmaphpp_data(pngicons_path):
|
|
|
|
count = 0
|
|
|
|
bitmaphpp_data = []
|
|
|
|
for file in os.listdir(pngicons_path):
|
|
|
|
if os.path.isfile(pngicons_path + file) and file.endswith(".png"):
|
|
|
|
bitmaphpp_data.append(convert_png(pngicons_path + file))
|
|
|
|
count += 1
|
|
|
|
|
|
|
|
return bitmaphpp_data
|
|
|
|
|
|
|
|
|
|
|
|
def pp_bitmaphpp_footer():
|
|
|
|
return("""
|
|
|
|
} /* namespace ui */
|
|
|
|
|
|
|
|
#endif /*__BITMAP_HPP__*/
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
|
|
def pp_write_bitmaphpp(pngicons_path, hpp_outpath):
|
|
|
|
bitmaphpp_file = []
|
|
|
|
|
|
|
|
bitmaphpp_file.append(pp_bitmaphpp_header())
|
|
|
|
bitmaphpp_file.append("".join(str(x) for x in pp_bitmaphpp_data(pngicons_path)))
|
|
|
|
bitmaphpp_file.append(pp_bitmaphpp_footer())
|
|
|
|
|
|
|
|
out_file = "".join(str(x) for x in bitmaphpp_file)
|
|
|
|
|
|
|
|
with open(hpp_outpath, "w", encoding="utf-8") as fd:
|
|
|
|
fd.writelines(out_file)
|
|
|
|
|
2024-10-24 11:43:18 -04:00
|
|
|
print("Find your bitmap.hpp at", hpp_outpath)
|
2024-10-20 08:19:33 -04:00
|
|
|
|
|
|
|
|
|
|
|
### Convert from a bitmap.hpp file one or all icons in png.
|
|
|
|
###########################################################
|
|
|
|
|
|
|
|
def parse_bitmaphpp(bitmaphpp_file,icon_name):
|
|
|
|
ico_pattern = re.compile(r"static constexpr uint8_t bitmap_(.*)_data\[\] = {\n((?:\s+(?:.*)\n)+)};\nstatic constexpr Bitmap bitmap_.*\{\n\s+\{(.*)\},", re.MULTILINE)
|
|
|
|
ico_data = []
|
|
|
|
|
|
|
|
# read file to buffer, to find multiline regex
|
|
|
|
readfile = open(bitmaphpp_file,'r')
|
|
|
|
buff = readfile.read()
|
|
|
|
readfile.close()
|
|
|
|
|
|
|
|
if icon_name == 'all':
|
|
|
|
for match in ico_pattern.finditer(buff):
|
|
|
|
ico_data.append([match.group(1), match.group(2), match.group(3)])
|
|
|
|
else:
|
|
|
|
for match in ico_pattern.finditer(buff):
|
|
|
|
if match.group(1) in icon_name:
|
|
|
|
ico_data.append([match.group(1), match.group(2), match.group(3)])
|
|
|
|
|
|
|
|
return (ico_data)
|
|
|
|
|
|
|
|
|
|
|
|
def convert_hpp(icon_name,bitmap_array,iconsize_str,png_outdir):
|
|
|
|
iconsize = iconsize_str.split(", ")
|
|
|
|
bitmap_size = (int(iconsize[0]),int(iconsize[1]))
|
|
|
|
bitmap_data=[]
|
|
|
|
|
|
|
|
image_data = np.zeros((bitmap_size[1], bitmap_size[0]), dtype=np.uint8)
|
|
|
|
|
|
|
|
for value in bitmap_array.split(",\n"):
|
|
|
|
if (value):
|
|
|
|
bitmap_data.append(int(value, 0))
|
|
|
|
|
|
|
|
for y in range(bitmap_size[1]):
|
|
|
|
for x in range(bitmap_size[0]):
|
|
|
|
byte_index = (y * bitmap_size[0] + x) // 8
|
|
|
|
bit_index = x % 8
|
|
|
|
# bit_index = 7 - (x % 8)
|
|
|
|
pixel_value = (bitmap_data[byte_index] >> bit_index) & 1
|
|
|
|
image_data[y, x] = pixel_value * 255
|
|
|
|
|
|
|
|
image = Image.fromarray(image_data, 'L')
|
|
|
|
icon_out = os.path.join(png_outdir,icon_name+".png")
|
|
|
|
image.save(icon_out)
|
|
|
|
|
|
|
|
|
|
|
|
### Processing
|
|
|
|
##############
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument("hpp", help="Path of the bitmap.hpp")
|
|
|
|
parser.add_argument("graphics", help="Path of <icon>.png files to convert", default=os.path.join(os.getcwd(),"graphics"))
|
|
|
|
parser.add_argument("--icon","-i", help="Name of the icon to convert in reverse. Use 'all' to convert all. More names can be comma seperated.")
|
|
|
|
parser.add_argument("--reverse","-r", help="Convert icon from bitmap.hpp to <name>.png", action="store_true")
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
if args.reverse:
|
|
|
|
print("Reverse: Converting from hpp to png")
|
|
|
|
|
|
|
|
# filter hpp arg is a file
|
|
|
|
hpp_file_path = args.hpp
|
|
|
|
if not os.path.isfile(hpp_file_path):
|
|
|
|
print(f"Error: {hpp_file_path} is not a valid file.")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
# filter graph arg is a path
|
|
|
|
if args.graphics:
|
|
|
|
graphics_path = os.path.join(args.graphics, '')
|
|
|
|
else:
|
|
|
|
graphics_path = os.path.join(os.getcwd(),"graphics", '')
|
|
|
|
if not os.path.exists(graphics_path):
|
|
|
|
os.makedirs(graphics_path) # create if not exist
|
|
|
|
|
|
|
|
# define icons to convert
|
|
|
|
if args.icon:
|
|
|
|
icon_name = args.icon
|
|
|
|
else:
|
|
|
|
icon_name = 'titlebar_image'
|
|
|
|
|
|
|
|
icons = parse_bitmaphpp(hpp_file_path, icon_name)
|
|
|
|
|
|
|
|
for icon in icons:
|
|
|
|
print("Converting icon", icon[0])
|
|
|
|
convert_hpp(icon[0], icon[1], icon[2], graphics_path)
|
|
|
|
sys.exit()
|
|
|
|
else:
|
|
|
|
print("Converting from png to hpp")
|
|
|
|
if args.graphics:
|
|
|
|
graphics_path = os.path.join(args.graphics, '')
|
|
|
|
else:
|
|
|
|
graphics_path = os.path.join(os.getcwd(),"graphics", '')
|
2024-10-24 11:43:18 -04:00
|
|
|
print("From path", graphics_path, "to file", args.hpp)
|
2024-10-20 08:19:33 -04:00
|
|
|
pp_write_bitmaphpp(graphics_path, args.hpp)
|
|
|
|
sys.exit()
|