diff --git a/apps/desktop/scripts/png_to_bmp.py b/apps/desktop/scripts/png_to_bmp.py index b8bf2f0..cc5c11e 100644 --- a/apps/desktop/scripts/png_to_bmp.py +++ b/apps/desktop/scripts/png_to_bmp.py @@ -123,15 +123,16 @@ def parse_png(path: Path): return width, height, image -def resize_with_letterbox(image, width, height, target_w, target_h, background): - if width == target_w and height == target_h: +def resize_with_letterbox(image, width, height, target_w, target_h, background, scale_factor=1.0): + if width == target_w and height == target_h and abs(scale_factor - 1.0) < 1e-6: return image, width, height bg_r, bg_g, bg_b = background - scale = min(target_w / width, target_h / height) - scale = max(scale, 1 / max(width, height)) # avoid zero - scaled_w = max(1, int(round(width * scale))) - scaled_h = max(1, int(round(height * scale))) + base_scale = min(target_w / width, target_h / height) + base_scale *= scale_factor + base_scale = max(base_scale, 1 / max(width, height)) # avoid zero / collapse + scaled_w = max(1, int(round(width * base_scale))) + scaled_h = max(1, int(round(height * base_scale))) output = bytearray(target_w * target_h * 4) # Fill background @@ -142,9 +143,9 @@ def resize_with_letterbox(image, width, height, target_w, target_h, background): offset_y = (target_h - scaled_h) // 2 for y in range(scaled_h): - src_y = min(height - 1, int(round(y / scale))) + src_y = min(height - 1, int(round(y / base_scale))) for x in range(scaled_w): - src_x = min(width - 1, int(round(x / scale))) + src_x = min(width - 1, int(round(x / base_scale))) src_idx = (src_y * width + src_x) * 4 dst_idx = ((y + offset_y) * target_w + (x + offset_x)) * 4 output[dst_idx : dst_idx + 4] = image[src_idx : src_idx + 4] @@ -206,6 +207,12 @@ def main(): parser.add_argument("output", type=Path) parser.add_argument("--width", type=int, help="Target width (px)") parser.add_argument("--height", type=int, help="Target height (px)") + parser.add_argument( + "--scale", + type=float, + default=1.0, + help="Optional multiplier applied to the fitted image size (e.g. 0.7 adds padding).", + ) parser.add_argument( "--background", type=str, @@ -218,7 +225,9 @@ def main(): width, height, image = parse_png(args.input) if args.width and args.height: bg = tuple(int(args.background[i : i + 2], 16) for i in (0, 2, 4)) - image, width, height = resize_with_letterbox(image, width, height, args.width, args.height, bg) + image, width, height = resize_with_letterbox( + image, width, height, args.width, args.height, bg, max(args.scale, 0.05) + ) rgb = blend_to_rgb(image) write_bmp(args.output, width, height, rgb) except Exception as exc: # noqa: BLE001 @@ -228,4 +237,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/apps/desktop/scripts/pngs_to_ico.py b/apps/desktop/scripts/pngs_to_ico.py new file mode 100644 index 0000000..6eb649e --- /dev/null +++ b/apps/desktop/scripts/pngs_to_ico.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +""" +Utility to build an .ico file from a list of PNGs of different sizes. + +Uses only Python's standard library so it can run in restricted environments. +""" + +from __future__ import annotations + +import argparse +import struct +from pathlib import Path + + +PNG_SIGNATURE = b"\x89PNG\r\n\x1a\n" + + +def read_png_dimensions(data: bytes) -> tuple[int, int]: + if not data.startswith(PNG_SIGNATURE): + raise ValueError("All inputs must be PNG files.") + width, height = struct.unpack(">II", data[16:24]) + return width, height + + +def build_icon(png_paths: list[Path], output: Path) -> None: + png_data = [p.read_bytes() for p in png_paths] + entries = [] + offset = 6 + 16 * len(png_data) # icon header + entries + + for data in png_data: + width, height = read_png_dimensions(data) + entry = { + "width": width if width < 256 else 0, + "height": height if height < 256 else 0, + "colors": 0, + "reserved": 0, + "planes": 1, + "bit_count": 32, + "size": len(data), + "offset": offset, + "data": data, + } + entries.append(entry) + offset += entry["size"] + + header = struct.pack(" None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("output", type=Path) + parser.add_argument("inputs", nargs="+", type=Path) + args = parser.parse_args() + + if not args.inputs: + raise SystemExit("Provide at least one PNG input.") + + build_icon(args.inputs, args.output) + + +if __name__ == "__main__": + main() diff --git a/apps/desktop/src-tauri/icons/icon.ico b/apps/desktop/src-tauri/icons/icon.ico index b56f21d..454f644 100644 Binary files a/apps/desktop/src-tauri/icons/icon.ico and b/apps/desktop/src-tauri/icons/icon.ico differ diff --git a/apps/desktop/src-tauri/icons/nsis-header.bmp b/apps/desktop/src-tauri/icons/nsis-header.bmp index c58e0da..1313bac 100644 Binary files a/apps/desktop/src-tauri/icons/nsis-header.bmp and b/apps/desktop/src-tauri/icons/nsis-header.bmp differ diff --git a/apps/desktop/src-tauri/icons/nsis-sidebar.bmp b/apps/desktop/src-tauri/icons/nsis-sidebar.bmp index 5763d73..061adc8 100644 Binary files a/apps/desktop/src-tauri/icons/nsis-sidebar.bmp and b/apps/desktop/src-tauri/icons/nsis-sidebar.bmp differ diff --git a/apps/desktop/src/main.tsx b/apps/desktop/src/main.tsx index ddbcda8..1f02a2f 100644 --- a/apps/desktop/src/main.tsx +++ b/apps/desktop/src/main.tsx @@ -757,7 +757,7 @@ function App() { alt="Logotipo Raven" width={160} height={160} - className="h-16 w-auto md:h-20" + className="h-14 w-auto md:h-16" onError={() => { if (logoFallbackRef.current) return logoFallbackRef.current = true @@ -766,15 +766,7 @@ function App() { />
Portal do Cliente -
- - - - Raven -
-
-
-

Agente Desktop

+ Agente Desktop