Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ollm/opencomic-ai-training/llms.txt

Use this file to discover all available pages before exploring further.

OpenComic AI Training generates paired training datasets by coordinating two distinct execution environments: Krita handles procedural comic-style art generation, and Node.js handles synthetic post-processing degradations. Every image that ends up in the dataset traces an identical two-phase path, ensuring that clean and degraded variants are always geometrically aligned and that every run is fully reproducible.

Two-Phase Pipeline

1
Krita Phase (inKrita)
2
Node.js spawns Krita as a subprocess and connects to it over a WebSocket (port 49120) provided by the ollm/kra-remote plugin. Once connected, Node.js drives Krita entirely over this channel — creating documents, adding layers, setting brush presets, painting strokes, applying filter masks, and exporting pixel data.
3
For each clean image the pipeline:
4
  • Creates (or resizes) a Krita document at the target resolution.
  • Fills the background layer with a randomly chosen color.
  • Draws procedural comic-style content across one or more layers: lineart (bezier curves, ink brushes), colorize masks (flat color fills), and optional texture or gradient layers.
  • Applies Krita’s built-in halftone filter as a filter mask on top of the artwork to simulate the halftone screen printing that appears in scanned comics. The filter can use dot or line patterns, RGBA or CMYK color spaces, and randomized angles and dot sizes.
  • Captures two canvas snapshots via get_canvas_image: one before the halftone mask is visible (the clean image) and one after (feeding into the degraded pipeline).
  • 5
    Node.js Phase (inNode)
    6
    After Krita delivers the pixel buffers, Node.js applies a configurable sequence of sharp-based operations to the degraded buffer. These simulate the real-world quality losses that a trained model will eventually need to reverse:
    7
  • Resize — shrink or enlarge using a randomly selected interpolation kernel.
  • Rotate — rotate both clean and degraded by the same angle so the pair stays aligned.
  • JPEG / WebP / AVIF / JXL compression — encode at a random quality level and decode back to a pixel buffer, introducing codec-specific compression artifacts.
  • Blur — apply Gaussian blur with a random sigma.
  • 8
    The resulting clean buffer is saved to the clean/ output folder and the degraded buffer to degraded/. Optionally, the fully resolved options used for that image are written to options/ as a JSON file.

    Degraded Variants Per Clean Image

    Each clean canvas render is expensive because it requires a full Krita paint pass. To amortize this cost, degradedImagesPerCleanImage controls how many independently randomized inNode degradation sequences are derived from the same clean render. For example, setting degradedImagesPerCleanImage: 100 produces 100 JPEG/WebP/resize/blur variants from a single Krita pass, giving 100 paired training examples at a fraction of the rendering cost.
    images: 4000
    degradedImagesPerCleanImage: 100
    # Total final pairs = 4000 × 100 = 400,000
    

    Seeded Randomization

    Every random decision in the pipeline — brush sizes, colors, halftone angles, compression qualities, resize scales — is driven by a deterministic PRNG seeded at generation time. The top-level seed field anchors the global random stream. Each image then derives its own seed as:
    imageSeed = image * 1009 + options.seed
    
    This means re-running the generator with the same seed and the same options file always produces identical output. It also means individual images can be audited or regenerated in isolation.
    Krita brush stroke patterns depend on Krita’s internal state and may vary across sessions even with the same seed. The seed guarantees reproducibility of all JavaScript-side randomness, including which brushes and parameters are chosen.

    Resuming a Stopped Run

    Setting resume: true in the options file enables incremental generation. On startup the generator reads the first degradations[].output.clean directory, scans filenames to find the highest existing image number, and resumes from that image. Already-completed images are skipped without regeneration.
    seed: 1
    resume: true
    images: 20000
    
    If you need to force a full regeneration from scratch, either set resume: false or delete the output directories before running.

    Preventing Krita Memory Leaks

    Long generation runs can cause Krita’s memory footprint to grow unboundedly. The --restart-krita-every CLI flag instructs the generator to kill and relaunch Krita every N images, re-establishing the WebSocket connection after a short sleep. The default is 20 images.
    npm run prepare && npm run generate -- \
      --options ./options/opencomic-ai-upscale-2x.yml \
      --krita ./krita-5.3.1-x86_64.AppImage \
      --restart-krita-every 50
    

    Top-Level Options Reference

    The following YAML block shows the key top-level fields that appear in every options file (taken from options/template.yml):
    seed: 1                        # Global PRNG seed for reproducibility
    resume: true                   # Skip images that already exist in the output folder
    images: 1000                   # Number of clean images to generate
    degradedImagesPerCleanImage: 100  # Degraded variants produced per clean render
    format: jpg                    # Output format for clean and degraded files (png or jpg)
    
    base:
      file: options/common/base.yml  # Shared base drawing configuration
      halftone:
        angle:
          - value: 45
            weight: 5.0
          - value: [42.1, 47.9]    # Decimal range
            weight: 1.0
    
    drawings:
      file: options/common/drawings.yml
    
    degradations:
      - name: my-dataset
        output:
          clean:    datasets/my-dataset/clean
          degraded: datasets/my-dataset/degraded
          # options: datasets/my-dataset/options  # Uncomment to save per-image JSON
        inKrita:
          - type: halftone
            prob: 1.0
            singleRun: false
            file: options/common/halftone-hard.yml
        inNodePromiseAll: true
        inNode:
          - type: jpeg
            prob: 0.8
            quality: [30, 100]
    

    Build docs developers (and LLMs) love