diff --git a/app/storage.py b/app/storage.py index 6650a7e..0281024 100644 --- a/app/storage.py +++ b/app/storage.py @@ -82,6 +82,42 @@ def save_palette_ase(palette: Palette, output_path: Path) -> None: output_path.write_bytes(header + b"".join(blocks)) +def save_tecot_map(palette: Palette, output_path: Path) -> None: + ensure_directory(output_path.parent) + colors = palette.colors + num_points = len(colors) + if num_points < 2: + return + + lines: list[str] = ["#!MC 1410"] + lines.append("$!CreateColorMap") + lines.append(f" Name = '{palette.name}'") + lines.append(f" NumControlPoints = {num_points}") + + for idx, color in enumerate(colors): + r, g, b = color.rgb + fraction = idx / (num_points - 1) if num_points > 1 else 0.0 + fraction_str = f"{fraction:.4f}".rstrip("0").rstrip(".") + lines.append(f" ControlPoint {idx + 1}") + lines.append(" {") + lines.append(f" ColorMapFraction = {fraction_str}") + lines.append(" LeadRGB") + lines.append(" {") + lines.append(f" R = {r}") + lines.append(f" G = {g}") + lines.append(f" B = {b}") + lines.append(" }") + lines.append(" TrailRGB") + lines.append(" {") + lines.append(f" R = {r}") + lines.append(f" G = {g}") + lines.append(f" B = {b}") + lines.append(" }") + lines.append(" }") + + output_path.write_text("\n".join(lines), encoding="utf-8") + + def save_originlab_pal(palette: Palette, output_path: Path, steps: int = 256) -> None: ensure_directory(output_path.parent) rgb_values = [color.rgb for color in palette.colors] diff --git a/app/ui/main_window.py b/app/ui/main_window.py index 4b56837..d5f2742 100644 --- a/app/ui/main_window.py +++ b/app/ui/main_window.py @@ -49,7 +49,7 @@ from app.config import AppConfig from app.models import ColorEntry, Palette from app.parsers import load_image_grid_palette, load_palette, load_pdf_palette, pdf_page_count, render_pdf_page, scan_palettes -from app.storage import ensure_directory, save_originlab_pal, save_palette_ase, save_palette_csv, save_palette_json +from app.storage import ensure_directory, save_originlab_pal, save_palette_ase, save_palette_csv, save_palette_json, save_tecot_map from app.webdav import WebDavClient, WebDavError from app.ui.pdf_dialog import PdfExtractDialog @@ -72,6 +72,7 @@ def ui_text(language: str, key: str, **kwargs: object) -> str: "target_general": "通用", "target_python": "Python", "target_matlab": "MATLAB", + "target_tecot": "Tecplot (.map)", "target_all_formats": "全部格式", "order_current": "当前顺序", "order_reverse": "反向顺序", @@ -150,6 +151,7 @@ def ui_text(language: str, key: str, **kwargs: object) -> str: "target_general": "General", "target_python": "Python", "target_matlab": "MATLAB", + "target_tecot": "Tecplot (.map)", "target_all_formats": "All Formats", "order_current": "Current order", "order_reverse": "Reverse order", @@ -1405,6 +1407,7 @@ def __init__(self, colors: list[ColorEntry], parent: QWidget | None = None) -> N [ ui_text(self.ui_language, "target_originlab"), ui_text(self.ui_language, "target_general"), + ui_text(self.ui_language, "target_tecot"), "R", ui_text(self.ui_language, "target_python"), ui_text(self.ui_language, "target_matlab"), @@ -1444,6 +1447,7 @@ def target_key(self) -> str: mapping = { ui_text(self.ui_language, "target_general"): "general", ui_text(self.ui_language, "target_originlab"): "originlab", + ui_text(self.ui_language, "target_tecot"): "tecot", "R": "r", ui_text(self.ui_language, "target_python"): "python", ui_text(self.ui_language, "target_matlab"): "matlab", @@ -4130,6 +4134,9 @@ def build_clipboard_text(self, target_key: str, palette: Palette) -> str: if target_key == "matlab": rows = [f"{r/255:.6f} {g/255:.6f} {b/255:.6f}" for r, g, b in (color.rgb for color in palette.colors)] return f"{self.make_safe_filename(palette.name)} = [ ...\n " + "; ...\n ".join(rows) + "\n];" + if target_key == "tecot": + rows = [f"{r/255:.6f} {g/255:.6f} {b/255:.6f}" for r, g, b in (color.rgb for color in palette.colors)] + return f"{self.make_safe_filename(palette.name)} = [ ...\n " + "; ...\n ".join(rows) + "\n];" if target_key == "originlab": return "\n".join(hexes) return ", ".join(hexes) @@ -4143,7 +4150,7 @@ def export_palette_files(self, target_key: str, palette: Palette) -> Path | None save_palette_json(palette, library_json_path) created_files: list[Path] = [library_json_path] if target_key == "all_formats": - for export_key in ("originlab", "general", "r", "python", "matlab"): + for export_key in ("originlab", "general", "tecot", "r", "python", "matlab"): self.export_palette_files(export_key, palette) return library_json_path exports_root = Path(self.config.library_dir) / "exports" / target_key @@ -4164,6 +4171,12 @@ def export_palette_files(self, target_key: str, palette: Palette) -> Path | None created_files.extend([ase_path, csv_path]) self.upload_webdav_files(created_files) return library_json_path + if target_key == "tecot": + map_path = exports_root / f"{file_stem}.map" + save_tecot_map(palette, map_path) + created_files.append(map_path) + self.upload_webdav_files(created_files) + return library_json_path content = self.build_clipboard_text(target_key, palette) extension = {"r": ".R", "python": ".py", "matlab": ".m"}[target_key] output_path = exports_root / f"{file_stem}{extension}"