From 5b2a1ff7886b573217fa4ab0ad9e78713f5b496f Mon Sep 17 00:00:00 2001 From: BuGu <62454025+Z2Z-GuGu@users.noreply.github.com> Date: Wed, 4 Mar 2026 17:09:52 +0800 Subject: [PATCH] Add webpage logo generation tool and method --- kvmapp/system/init.d/S95nanokvm | 12 ++++ tools/logo_generator/logo_generator.py | 83 ++++++++++++++++++++++++-- tools/logo_generator/readme.md | 4 +- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/kvmapp/system/init.d/S95nanokvm b/kvmapp/system/init.d/S95nanokvm index a40cc17..f314261 100755 --- a/kvmapp/system/init.d/S95nanokvm +++ b/kvmapp/system/init.d/S95nanokvm @@ -32,6 +32,18 @@ case "$1" in iptables -C OUTPUT -o eth0 -p tcp --sport 8000 -m state --state ESTABLISHED -j DROP 2>/dev/null || \ iptables -A OUTPUT -o eth0 -p tcp --sport 8000 -m state --state ESTABLISHED -j DROP + # Logo selection + if [ -f /boot/logo.ico ]; then + if [ ! -f /kvmapp/server/web/original.ico ]; then + mv /kvmapp/server/web/sipeed.ico /kvmapp/server/web/original.ico + cp /boot/logo.ico /kvmapp/server/web/sipeed.ico + fi + else + if [ -f /kvmapp/server/web/original.ico ]; then + mv /kvmapp/server/web/original.ico /kvmapp/server/web/sipeed.ico + fi + fi + # Start services cp -r /kvmapp/kvm_system /tmp/ /tmp/kvm_system/kvm_system & diff --git a/tools/logo_generator/logo_generator.py b/tools/logo_generator/logo_generator.py index c932422..3b1d905 100644 --- a/tools/logo_generator/logo_generator.py +++ b/tools/logo_generator/logo_generator.py @@ -21,7 +21,7 @@ LANGUAGES = { 'click_hint': '💡 点击图片以修改像素', 'btn_invert': '🔃 反转', 'btn_reset': '🔄 重置', - 'btn_export': '💾 导出 logo.bin', + 'btn_export': '💾 导出', 'btn_quit': '❌ 退出', 'help_text_with_image': '快捷键:↑↓ 调整±10 | ←→ 调整±1 | I 反转 | R 重置 | D 导出 | Q 退出', 'help_text_editor': '快捷键:I 反转 | R 清空 | D 导出 | Q 退出', @@ -33,7 +33,7 @@ LANGUAGES = { 'status_reset_image': '已重置为原始图片', 'status_reset_canvas': '已清空画布', 'status_export_error': '错误:没有可导出的数据', - 'status_exported': '✅ 已导出 logo.bin (32 字节)', + 'status_exported': '✅ 已导出 logo 文件', 'status_pixel_toggled': '切换像素 ({}, {})', 'lang_select_title': '选择语言 / Select Language', 'btn_chinese': '中文 (Chinese)', @@ -56,7 +56,7 @@ LANGUAGES = { 'click_hint': '💡 Click image to toggle pixels', 'btn_invert': '🔃 Invert', 'btn_reset': '🔄 Reset', - 'btn_export': '💾 Export logo.bin', + 'btn_export': '💾 Export', 'btn_quit': '❌ Quit', 'help_text_with_image': 'Shortcuts: ↑↓ ±10 | ←→ ±1 | I Invert | R Reset | D Export | Q Quit', 'help_text_editor': 'Shortcuts: I Invert | R Clear | D Export | Q Quit', @@ -68,7 +68,7 @@ LANGUAGES = { 'status_reset_image': 'Reset to original image', 'status_reset_canvas': 'Canvas cleared', 'status_export_error': 'Error: No data to export', - 'status_exported': '✅ Exported logo.bin (32 bytes)', + 'status_exported': '✅ Exported logo file', 'status_pixel_toggled': 'Toggled pixel ({}, {})', 'lang_select_title': '选择语言 / Select Language', 'btn_chinese': '中文 (Chinese)', @@ -150,6 +150,72 @@ def binary_to_bytes(binary): return bytes(data) +def binary_to_image(binary_data, size=64): + """ + Convert 16x16 binary data to 64x64 RGBA image + + Args: + binary_data: 16x16 numpy array of binary values + size: Size to scale the image to (default 64) + + Returns: + PIL Image in RGBA mode + """ + # Create 16x16 RGBA image from binary data + img_16 = Image.new('RGBA', (16, 16), (0, 0, 0, 255)) # Black for 1 + pixels = img_16.load() + + for y in range(16): + for x in range(16): + if binary_data[y][x] == 1: + pixels[x, y] = (255, 255, 255, 255) # White + else: + pixels[x, y] = (0, 0, 0, 255) # Black + + # Scale to 64x64 using NEAREST for pixel-perfect scaling + img_64 = img_16.resize((size, size), Image.Resampling.NEAREST) + return img_64 + + +def image_to_ico(image_path=None, binary_data=None, output_path="logo.ico", size=64): + """ + Convert image or binary data to 64x64 32-bit ICO file + + Args: + image_path: Path to the source image (optional if binary_data is provided) + binary_data: 16x16 numpy array of binary values (optional if image_path is provided) + output_path: Output ICO file path + size: Size to scale the icon to (default 64) + """ + try: + if image_path and os.path.exists(image_path): + img = Image.open(image_path).convert('RGBA') + + # If not square, crop the center region + if img.width != img.height: + min_size = min(img.width, img.height) + left = (img.width - min_size) // 2 + top = (img.height - min_size) // 2 + img = img.crop((left, top, left + min_size, top + min_size)) + + # Resize to 64x64 using LANCZOS for high quality + img_64 = img.resize((size, size), Image.Resampling.LANCZOS) + elif binary_data is not None: + # Convert binary data to image and scale + img_64 = binary_to_image(binary_data, size) + else: + print("Error: No image source provided") + return False + + except Exception as e: + print(f"Error: Failed to create ICO - {e}") + return False + + # Save as ICO with 32-bit color depth + img_64.save(output_path, format='ICO', sizes=[(size, size)]) + return True + + class PixelGrid(Static): """16x16 pixel grid component""" @@ -475,7 +541,7 @@ class LogoApp(App): self.status.update(self.lang['status_reset_canvas']) def action_export(self): - """Export logo.bin""" + """Export logo.bin and logo.ico""" if self.current_binary is None: self.status.update(self.lang['status_export_error']) return @@ -485,6 +551,13 @@ class LogoApp(App): with open("logo.bin", "wb") as f: f.write(data) + # Export 64x64 32-bit ICO file + if self.has_image and self.image_path: + image_to_ico(self.image_path, "logo.ico", size=64) + else: + # Export from current canvas (16x16 -> 64x64) + image_to_ico(binary_data=self.current_binary, output_path="logo.ico", size=64) + self.status.update(self.lang['status_exported']) def action_threshold_up(self): diff --git a/tools/logo_generator/readme.md b/tools/logo_generator/readme.md index bea0f53..de1c3e4 100644 --- a/tools/logo_generator/readme.md +++ b/tools/logo_generator/readme.md @@ -3,7 +3,7 @@ **Compatible Hardware:** NanoKVM-Cube, NanoKVM-PCIe 🛠️ **Tool Description:** -This is a logo generator for the NanoKVM OLED display. You can use it to create a `logo.bin` file and place it in the `/boot` directory of your NanoKVM system. +This is a logo generator for the NanoKVM OLED display and Web. You can use it to create a `logo.bin` and `logo.ico` file and place them in the `/boot` directory of your NanoKVM system. 📋 **Instructions:** @@ -30,7 +30,7 @@ This is a logo generator for the NanoKVM OLED display. You can use it to create Click on individual pixels to adjust details. If you prefer an inverted display, just click the invert button 🔄 7. **Export and deploy:** - Export the `logo.bin` file and copy it to the `/boot` directory of your NanoKVM system. You can do this by: + Export the `logo.bin` & `logo.ico`, then copy it to the `/boot` directory of your NanoKVM system. You can do this by: * Enabling SSH and using SCP to copy the file 💻 * Or directly placing it in the boot partition of your TF card 💾