No description
  • Rust 95.2%
  • Fluent 2.3%
  • Lua 1.5%
  • Python 0.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-11-04 08:16:29 +03:00
.cargo * build: CRT-static Windows exe (bare machines have no vcruntime140.dll); version untouched (build config) 2026-10-23 16:29:44 +03:00
.forgejo ci: add mask_layer to the selective LFS pull — the masked-layers fast test (56d513a) matches the PSD by 8BPS magic, an smudge-skipped pointer panics 'handler not found' 2026-10-07 15:21:18 +03:00
.zed - vscode: remove .vscode configs (editor switched to Zed, local .zed config stays untracked) 2026-09-28 15:35:12 +03:00
assets/locale + --inv-pos-y flag: layout y counted from the document bottom (reference inv_pos_y; verified byte-identical to canonical armor_icons/mosaic_icons layouts) 2026-10-21 15:03:39 +03:00
profiles + scale field in layout.jsonl for layers with scale > 0 2026-09-05 12:21:19 +03:00
src resize: replace the calibrated Mitchell approximation with Photoshop's measured Bicubic Sharper (Keys a=-1-1.6(1-s), stretch 1.05/s; at 50% a=-1.8, 8 taps) — straight RGB with edge fold + alpha edge drop, f64 taps, 8-bit intermediate, no unsharp; all 6 kernel probes now byte-exact (RMSE 0/MAX 0 like bilinear), worst corpus sprite 26.75->17.80, composite 1.37->0.62; legacy chain kept for the calibration probes via ps_measured:false 2026-11-04 08:16:29 +03:00
test_files resize: replace the calibrated Mitchell approximation with Photoshop's measured Bicubic Sharper (Keys a=-1-1.6(1-s), stretch 1.05/s; at 50% a=-1.8, 8 taps) — straight RGB with edge fold + alpha edge drop, f64 taps, 8-bit intermediate, no unsharp; all 6 kernel probes now byte-exact (RMSE 0/MAX 0 like bilinear), worst corpus sprite 26.75->17.80, composite 1.37->0.62; legacy chain kept for the calibration probes via ps_measured:false 2026-11-04 08:16:29 +03:00
.gitattributes * added Photoshop reference tests for transparent layers 2026-08-27 11:22:22 +03:00
.gitignore + Forgejo Actions: CI (clippy+tests on push) and Release (linux+windows on tags), commit Cargo.lock 2026-09-08 14:58:12 +03:00
AGENTS.md resize: replace the calibrated Mitchell approximation with Photoshop's measured Bicubic Sharper (Keys a=-1-1.6(1-s), stretch 1.05/s; at 50% a=-1.8, 8 taps) — straight RGB with edge fold + alpha edge drop, f64 taps, 8-bit intermediate, no unsharp; all 6 kernel probes now byte-exact (RMSE 0/MAX 0 like bilinear), worst corpus sprite 26.75->17.80, composite 1.37->0.62; legacy chain kept for the calibration probes via ps_measured:false 2026-11-04 08:16:29 +03:00
BENCHMARK_FORMATS.md + output format benchmark results (layer_as_sprite) 2026-09-05 09:19:45 +03:00
Cargo.lock resize: replace the calibrated Mitchell approximation with Photoshop's measured Bicubic Sharper (Keys a=-1-1.6(1-s), stretch 1.05/s; at 50% a=-1.8, 8 taps) — straight RGB with edge fold + alpha edge drop, f64 taps, 8-bit intermediate, no unsharp; all 6 kernel probes now byte-exact (RMSE 0/MAX 0 like bilinear), worst corpus sprite 26.75->17.80, composite 1.37->0.62; legacy chain kept for the calibration probes via ps_measured:false 2026-11-04 08:16:29 +03:00
Cargo.toml resize: replace the calibrated Mitchell approximation with Photoshop's measured Bicubic Sharper (Keys a=-1-1.6(1-s), stretch 1.05/s; at 50% a=-1.8, 8 taps) — straight RGB with edge fold + alpha edge drop, f64 taps, 8-bit intermediate, no unsharp; all 6 kernel probes now byte-exact (RMSE 0/MAX 0 like bilinear), worst corpus sprite 26.75->17.80, composite 1.37->0.62; legacy chain kept for the calibration probes via ps_measured:false 2026-11-04 08:16:29 +03:00
CI_CD.md * ci: strip checkout's actions-token extraheader before git lfs pull — Forgejo answers any LFS request carrying that token with 'Authentication required' even on a public repo (anonymous LFS works, verified in the CI image container), so the previous selective-pull step failed with per-object client errors; remove http.*.extraheader keys before pulling, CI_CD.md gotcha documented 2026-09-28 16:18:36 +03:00
README.md Revert "+ --rename-duplicates: suffix duplicate output names instead of failing" 2026-10-17 16:19:03 +03:00

imaginum

imaginum — консольная утилита для нарезки файлов Adobe Photoshop (PSD) на спрайты: каждый слой или весь композит сохраняются в PNG, WebP, TIFF или QOI.

Поведение программы настраивается Lua-профилем: скрипт решает, какие слои переименовать, масштабировать, обрезать или отключить. Это позволяет подстроить нарезку под конкретный PSD без изменения самого инструмента — достаточно описать правила в небольшом Lua-скрипте.

Возможности

  • 3 режима работы — от быстрой валидации до нарезки каждого слоя.
  • Lua-профили — правила обработки слоёв: переименование, масштаб (%), обрезка, отключение, групповые трансформации.
  • Ресайз, калиброванный под Photoshop — ядра Bicubic Sharper и Bilinear; режим --half повторяет Image Size 50% из Photoshop.
  • Lossless-форматы — PNG (compression 0–9), WebP, TIFF (Deflate fast/balanced/best), QOI.
  • Пакетная обработка — несколько PSD за запуск, входные пути поддерживают glob-маски (assets/**/*.psd); файлы обрабатываются в детерминированном порядке (сортировка по полному пути, дубликаты убираются), поэтому layout.jsonl всегда одинаковый независимо от порядка перечисления.
  • layout.jsonl — метаданные сохранённых слоёв (координаты, размеры, blake3-хэш) для генерации атласов/манифестов.
  • Локализация — русский и английский интерфейс и сообщения об ошибках.

Использование

imaginum \
  -i assets/**/*.psd \
  -p profiles/marlo_engine.lua \
  -m layer_as_sprite \
  -o ./out

Профиль profiles/marlo_engine.lua идёт в комплекте: он парсит теги вида {zoom=50; tiled} в именах слоёв Photoshop и управляет нарезкой через них.

Опции командной строки

Опция Описание
-i, --input-files <ФАЙЛЫ…> Один или несколько PSD-файлов (обязательно). Поддерживаются glob-маски; значения можно разделять ;
-p, --profile <ФАЙЛ> Lua-профиль (обязательно), например profiles/marlo_engine.lua
-o, --output <КАТАЛОГ> Выходной каталог. Обязателен для всех режимов, кроме validate_only. Создаётся автоматически; существующее содержимое затирается
-m, --mode <РЕЖИМ> Режим работы (по умолчанию layer_as_sprite) — см. ниже
--half Уменьшение результата в 2 раза (аналог Image Size 50% в Photoshop) с компенсацией прозрачных краёв (bleed)
--scale-filter <ФИЛЬТР> bicubic (по умолчанию; аналог Photoshop «Bicubic Sharper») или bilinear
--output-format <ФОРМАТ> png, webp, tiff или qoi (по умолчанию qoi). Все форматы — lossless
--png-compression <0..9> Уровень сжатия PNG (по умолчанию 6)
--tiff-compression <РЕЖИМ> Deflate-сжатие TIFF: fast, balanced (по умолчанию), best
--rgb-background <0xRRGGBB> Цвет подложки при рендере композита (по умолчанию 0x000000)
--show-tree Вывести дерево слоёв в консоль перед обработкой (по умолчанию выключено)
--log-level <УРОВЕНЬ> Детализация лога (консоль и файл): error, warn, info (по умолчанию), debug, trace — полная диагностика конвейера

Режимы работы

Режим Что делает
validate_only Только проверка слоёв (имена, blend-режимы, эффекты — правила задаёт профиль), без записи файлов
layer_as_sprite Каждый слой сохраняется отдельным файлом
file_as_sprite Весь файл сводится в один композит

Lua-профили

Профиль — обычный Lua-скрипт. Все хуки опциональны: что не определено, работает по умолчанию. Полный живой пример — profiles/marlo_engine.lua.

Хуки

Хук Назначение
handle_layer_attributes(layer_name, transform) Разбор имени/атрибутов слоя → трансформации через API ниже
handle_layer_name(layer_name, …) Переименование слоя
validate_layer_name(name) Разрешить/запретить имя (true/false)
validate_layer_blend_mode(blend_mode) Проверка blend-режима
validate_layer_effects(has_effects) Проверка наличия эффектов
validate_layer_attributes(…) Прочие проверки атрибутов
handle_layer_group(…) Групповые трансформации
handle_layers_layout(…) Метаданные сохранённых слоёв (имя, координаты, размеры, blake3-хэш) — например, для записи layout.jsonl

Transform API

Внутри handle_layer_attributes и handle_layer_group доступен объект transform:

transform:set_scale(50)             -- масштаб слоя в % (50 = вдвое меньше)
transform:disable()                 -- исключить слой из обработки
transform:enable_crop_by_viewport() -- обрезать по границам документа
transform:enable_export_as_rect()   -- экспортировать как прямоугольник
transform:enable_tiled()            -- пометить слой как тайловый
transform:force_rgb()               -- сохранить без альфы
transform:set_fit_rect(rect)        -- вписать в заданный прямоугольник

Пример

Фрагмент profiles/marlo_engine.lua: правила читаются прямо из имён слоёв в Photoshop — префиксы ~ (отключить), @ (экспорт как rect), #n (обрезка по документу) и теги {…}:

function handle_layer_attributes(layer_name, transform)
    layer_name = layer_name:lower()

    if layer_name:sub(1, 1) == "~" then
        transform:disable()          -- слой начинается с "~" — не экспортировать
    elseif layer_name:sub(1, 1) == "@" then
        transform:enable_export_as_rect()
    end

    -- тег {zoom=50; tiled} в имени слоя
    local first = layer_name:find("{", 1, true)
    local last = first and layer_name:find("}", first + 1, true)
    if first and last then
        local tags = layer_name:sub(first + 1, last - 1)
        for part in tags:gmatch("[^;]+") do
            local key, value = part:match("(%w+)%s*=%s*(%d+)")
            if key == "zoom" and tonumber(value) ~= 100 then
                transform:set_scale(tonumber(value))
            end
        end
    end
end

Логи

Логи пишутся в ~/.imaginum/logs/YYYYMMDD-HHMMSS.log. При запуске логи старше месяца удаляются автоматически.