Shrink large textures in Koikatsu files
Find a file
Liquid 8e0e66da2d add config examples (#7)
Reviewed-on: #7
Co-authored-by: Liquid <liquid4139@noreply.localhost>
Co-committed-by: Liquid <liquid4139@noreply.localhost>
2026-05-31 02:13:44 +00:00
kkpy new skip rule, explicit scene handlers, break files apart (#6) 2026-05-31 02:04:25 +00:00
.gitignore feat: initial import 2026-05-16 15:49:18 -04:00
config.yml add config examples (#7) 2026-05-31 02:13:44 +00:00
gui_app.py new skip rule, explicit scene handlers, break files apart (#6) 2026-05-31 02:04:25 +00:00
LICENSE feat: initial import 2026-05-16 15:49:18 -04:00
main.py new skip rule, explicit scene handlers, break files apart (#6) 2026-05-31 02:04:25 +00:00
pyproject.toml add config examples (#7) 2026-05-31 02:13:44 +00:00
README.md feat: GUI (#3) 2026-05-24 07:18:19 +00:00
run-gui.bat feat: GUI (#3) 2026-05-24 07:18:19 +00:00
uv.lock add config examples (#7) 2026-05-31 02:13:44 +00:00

KKPy

A texture optimizer for Koikatsu game files. Reduces texture sizes by resizing large textures to a maximum dimension and optimizing PNG compression.

GUI Application

KKPy includes a graphical user interface for easy texture optimization without command-line usage.

Quick Start

Windows:

  1. Download the project files
  2. Double-click run-gui.bat
  3. The script will:
    • Check if UV is installed (and install it if needed)
    • Set up the project files
    • Launch the GUI application

Linux:

uv run gui_app.py

GUI Features

The GUI provides a two-tab interface:

Process Tab

Select files or directories to optimize with the following options:

Feature Description
Input/Output Browse for input and output paths, or drag-and-drop files
File Type Auto-detect or manually select (chara, scene, coord, etc.)
In-place Modify files directly without creating copies
Recursive Process subdirectories when input is a directory
Max Size Maximum texture dimension (power-of-two values)
Compression PNG compression level 0-9 (visual regions: Fast/Balanced/Max)
Resize Filter Algorithm: nearest, bilinear, bicubic, lanczos
Max Workers Parallel processing threads (CPU-aware)
Always Optimize Optimize textures even if under max size
Verbosity Log detail level: Quiet, Normal, Verbose, Extra

Progress Monitoring:

  • Real-time progress bar with file counter
  • Elapsed time display
  • Summary statistics (textures processed, bytes saved)
  • ANSI color support in log output

Resolution Rules Tab

Configure per-texture resolution rules with a visual table editor:

Feature Description
Rule Management Add, edit, delete, and reorder rules
Drag-and-Drop Reorder rules by dragging rows
Filter Search rules by name, property, or material
Import/Export Load and save configuration files
Object Types Select from predefined object type names

Rule Properties:

  • Name: Descriptive rule name
  • Max Size: Maximum dimension for matching textures
  • Property: Glob pattern for texture property (e.g., MainTex, Normal*)
  • Material Name: Glob pattern for material name (e.g., Skin*, Cloth*)
  • Object Type: Numeric type (0-4) for texture category

Additional Features

  • Dark/Light Mode: Toggle via View menu
  • Drag-and-Drop: Drop files directly onto the application window

Requirements

  • Python: 3.14 or higher
  • Package Manager: uv (recommended) or pip

Installation

# Clone the repository
git clone <repo-url>
cd kkPy

# Install with uv (recommended)
uv sync

# Or install with pip
pip install -e .

Note: For 2-4x faster image operations, install pillow-simd instead of pillow:

pip install pillow-simd

Supported File Types

Type Description
chara / character Character files
scene Scene files
coord / coordinate Coordinate/clothes files

Usage

Process a single file

uv run main.py input.png output.png

Process a directory

uv run main.py input_dir output_dir

Auto-detect file type

uv run main.py input.png output.png

Specify file type explicitly

uv run main.py -t chara input.png output.png

In-place modification

# Single file (will prompt for confirmation)
uv run main.py -i input.png

# Directory (will prompt for confirmation)
uv run main.py -i input_dir

Command-line Options

usage: main.py [-h] [-t {chara,scene,save,coord,emocre_chara,emocre_map,emocre_scene,honeycome_chara,honeycome_scene,summer_chara,summer_save,aicomi_chara}]
               [-v] [-j JOBS] [-r] [-i] [--max-size MAX_SIZE]
               [--compress-level COMPRESS_LEVEL]
               [--resize-filter {nearest,bilinear,bicubic,lanczos}]
               [--always-optimize]
               [--config CONFIG]
               input output

Load KK files, optimize large textures in materialeditor data, and save.

positional arguments:
  input                 Path to input file or directory
  output                Path to output file or directory (optional with --in-place)

options:
  -h, --help            show this help message and exit
  -t, --type            Type of file to process. If not provided, will be
                        auto-detected from file content.
  -v, --verbose         Show detailed progress messages
  -j, --jobs            Number of parallel jobs for directory processing
                        (default: auto)
  -r, --recursive       Search subdirectories recursively when processing
                        a directory
  -i, --in-place        Modify files in place (output path becomes optional,
                        will prompt for confirmation)
  --max-size            Maximum texture dimension in pixels (default: 2048)
  --compress-level      PNG compression level, 0-9 (default: 6, higher =
                        smaller but slower)
  --resize-filter       Resize filter algorithm (default: bilinear)
  --always-optimize     Optimize textures even if under max resolution
                        (only if smaller)
  --config              Path to YAML config file for per-texture resolution
                        rules (default: config.yml)

Option Details

Option Shorthand Default Description
--type -t auto-detect File type (chara, scene, coord, etc.)
--verbose -v false Show detailed progress messages
--jobs -j CPU count Number of parallel workers
--recursive -r false Process subdirectories recursively
--in-place -i false Modify files in place (prompts for confirmation)
--max-size 2048 Maximum texture dimension in pixels
--compress-level 6 PNG compression level (0-9)
--resize-filter bilinear Resize algorithm (nearest, bilinear, bicubic, lanczos)
--always-optimize -ao false Optimize even if under max size (if smaller)
--config config.yml Path to YAML config file for per-texture resolution rules

Configuration

KKPy can be configured using a YAML file (config.yml by default) for per-texture resolution rules. This allows different maximum sizes for different texture types based on their properties.

Configuration File Format

# Default settings for textures that don't match any rule
default_max_size: 2048    # Maximum dimension in pixels
compress_level: 6         # PNG compression level (0-9)
resize_filter: bilinear # Resize algorithm: nearest, bilinear, bicubic, lanczos
always_optimize: false    # Optimize textures even if under max resolution
max_workers: 4            # Number of parallel workers

# Resolution rules - evaluated in order, first match wins
rules:
  - name: "Rule name"
    max_size: 1024        # Maximum dimension for matching textures
    match:
      property: "DetailMask"     # Glob pattern for texture property (e.g., "MainTex", "Normal*")
      material_name: "cf_m_hair_f_*"  # Glob pattern for material name (optional)
      object_type: 2          # Exact object type ID (optional)

Top-Level Settings

Setting Type Default Description
default_max_size int 2048 Default maximum texture dimension for textures not matching any rule
compress_level int 6 PNG compression level (0-9, higher = smaller but slower)
resize_filter string bilinear Resize algorithm: nearest, bilinear, bicubic, or lanczos
always_optimize bool false Optimize textures even if under max resolution (if smaller)
max_workers int 4 Number of parallel workers for texture processing

Resolution Rules

Rules are evaluated in order; the first matching rule determines the max_size for a texture. Each rule supports the following match criteria:

Match Field Type Description
property string (glob) Texture property name pattern (e.g., MainTex, Normal*, Shadow*)
material_name string (glob) Material name pattern (e.g., Skin*, Cloth*)
object_type int or list[int] Object type ID(s) to match exactly

All specified match conditions must be satisfied (AND logic).

Object Types

The object_type field in resolution rules matches against the ObjectType value in the MaterialTexturePropertyList. The following object types are defined in the MaterialEditor plugin:

Object Type Description
0 Unknown (reserved)
1 Clothing/Body textures
2 Accessory textures
3 Hair textures
4 Character (face/body parts)

Example Configuration

# Accessory textures (ObjectType 2) - often need higher resolution
- name: "Accessory textures"
  max_size: 2048
  match:
    object_type: 2

Development

Setup

# Install with development dependencies
uv sync --extra dev

# Or with pip
pip install -e ".[dev]"

Running Tests

# Run all tests
uv run pytest

# Run with coverage
uv run pytest --cov=kkpy

# Run specific test file
uv run pytest tests/test_unit.py

Code Quality

# Run linting
uv run ruff check .

# Run type checking
uv run ty check .

# Format code
uv run ruff format .