Compare commits

...

4 Commits

Author SHA1 Message Date
83a09d054e feat: add --interactive flag to img_api_generate.sh 2026-03-01 11:43:14 +01:00
4de55a9f41 feat: ensure consistent filename IDs across script steps 2026-02-21 18:56:36 +01:00
0d31a6fee8 docs: add sophisticated README covering Pivoine Toolbelt scripts 2026-02-21 13:33:46 +01:00
37b4081448 feat: support aspect ratios and align with image generation schema
- Add support for resolution and styling parameters
- Enable aspect ratio support for all models
- Remove unsupported fields: num_images, negative_prompt, guidance_scale
- Streamline payload builder and input validation
- Align API paths with live Traefik configuration
2026-02-21 13:32:06 +01:00
2 changed files with 149 additions and 582 deletions

539
README.md
View File

@@ -1,519 +1,68 @@
# Utility Scripts Collection
# 🛠️ Pivoine Toolbelt
> Comprehensive collection of bash utility scripts for various tasks
A collection of sophisticated Bash utility scripts for creative automation, asset management, and infrastructure control. These tools are designed with a focus on aesthetics, usability, and seamless integration with the Pivoine ecosystem.
This repository contains a curated collection of bash scripts for repository management, color manipulation, documentation generation, artifact handling, and more.
## 🎨 Image & Creative Automation
## Table of Contents
- [`arty.sh`](#artysh) - Repository and Release Management
- [`artifact_github_download.sh`](#artifact_github_downloadsh) - GitHub Artifact Downloader
- [`artifact_postgres_export.sh`](#artifact_postgres_exportsh) - PostgreSQL Code Export
- [`css_color_filter.sh`](#css_color_filtersh) - CSS Filter Generator
- [`css_color_palette.sh`](#css_color_palettesh) - Color Palette Generator
- [`css_json_convert.sh`](#css_json_convertsh) - CSS Variable Converter
- [`doc_bash_generate.sh`](#doc_bash_generatesh) - Bash Documentation Generator
- [`doc_rust_generate.sh`](#doc_rust_generatesh) - Rust Documentation Generator
- [`jinja_template_render.sh`](#jinja_template_rendersh) - Jinja2 Template Renderer
- [`mime_mp4_gif.sh`](#mime_mp4_gifsh) - MP4 to GIF Converter
### `img_api_generate.sh`
The primary interface for the Pivoine Image Generation API. Supports high-performance image creation with advanced control parameters.
* **Models:** `mystic`, `flux-dev`, `flux-pro`, `seedream`.
* **Features:**
* Custom aspect ratios (e.g., `square_1_1`, `widescreen_16_9`).
* Resolution control for Mystic model (1k, 2k, 4k).
* Seed reproducibility and styling injection.
* Integrated **FaceFusion** face swapping.
* Integrated **Real-ESRGAN** upscaling.
* **Usage:** `./img_api_generate.sh -p "a cinematic portrait of a neon cyborg" --aspect-ratio widescreen_16_9 -m flux-pro`
### `css_color_palette.sh`
A zero-dependency color utility to generate comprehensive design tokens directly from the CLI. Generates tints, shades, and tones from a single base color.
### `mime_mp4_gif.sh`
High-quality video-to-GIF conversion utility optimized for web performance and visual fidelity.
---
## `arty.sh`
## 📦 Asset & Model Management
**A bash library repository and release management system**
### `artifact_civitai_download.sh` & `artifact_huggingface_download.sh`
Streamlined downloaders for AI models (Checkpoints, LoRAs, VAEs).
* Manages a central cache.
* Automates symlinking to target application directories.
* Verification mode to ensure link integrity.
Combined functionality from arty.sh (repository management) and whip.sh (release cycle management).
### Usage
```bash
arty <command> [arguments] [--dry-run] [-v|--verbose]
```
### Commands
#### Repository Commands
- `install <repo-url> [name]` - Install a library from git repository
- `deps [--dry-run]` - Install all dependencies from arty.yml
- `list` - List installed libraries with dependency tree
- `remove <name>` - Remove an installed library
- `init [name]` - Initialize a new arty.yml project
- `source <name> [file]` - Source a library (for use in scripts)
- `exec <lib-name> [args]` - Execute a library's main script with arguments
- `<script-name>` - Execute a script defined in arty.yml
#### Release Commands
- `release [major|minor|patch]` - Full release workflow (default: patch)
- Bumps version in arty.yml
- Updates CHANGELOG.md from git history
- Creates git commit
- Creates and pushes git tag
- `version` - Show current version from arty.yml
- `bump <major|minor|patch>` - Bump version in arty.yml (no commit/tag)
- `changelog` - Generate changelog from git history
- `tag <version>` - Create and push git tag
#### Hook Commands
- `hooks install` - Install git commit hooks (includes shellcheck validation)
- `hooks uninstall` - Remove git commit hooks
- `hooks create` - Create default hook templates
#### Monorepo Commands
- `mono list [root] [pattern]` - List arty.yml projects
- `mono version [root] [pattern]` - Show versions of all projects
- `mono bump <type> [root] [pattern]` - Bump version for all projects
- `mono status [root] [pattern]` - Show git status for all projects
- `mono exec <cmd> [root] [pattern]` - Execute bash command on all projects
- `mono help` - Show detailed mono help
### Examples
```bash
# Repository Management
arty install https://github.com/user/bash-utils.git
arty deps
arty list
# Release Cycle
arty release # Patch release
arty release major # Major version release
arty bump minor # Just bump version
arty hooks install # Install commit hooks
# Monorepo Management
arty mono list # List all projects
arty mono version # Show all project versions
arty mono exec "git status" # Run command on all projects
```
### `artifact_git_download.sh` & `artifact_github_download.sh`
Sophisticated wrappers for managing repository-based artifacts and binary releases.
---
## `artifact_github_download.sh`
## ⚡ Infrastructure & Services
**GitHub Artifact Downloader**
### `service_runpod_control.sh`
A beautiful CLI wrapper for managing RunPod GPU instances. Provides a unified interface for lifecycle management:
* `create`, `remove`, `start`, `stop`, `status`.
Download artifacts from GitHub Actions workflows with interactive selection or automatic matching.
### Usage
```bash
artifact_github_download.sh <REPO> [OPTIONS]
```
### Arguments
- `REPO` - GitHub repository (owner/repo)
### Options
- `-n, --name NAME` - Artifact name to download (preselect)
- `-o, --output DIR` - Output directory (default: current directory)
- `-h, --help` - Show help message
### Examples
```bash
# Interactive mode - list and select artifacts
artifact_github_download.sh valknarness/awesome
# Preselect artifact by name
artifact_github_download.sh valknarness/awesome -n awesome-database-latest
# Download to specific directory
artifact_github_download.sh valknarness/awesome -o ~/downloads
```
### `jinja_template_render.sh`
Sophisticated Jinja2 template rendering engine. Ideal for generating configuration files, HTML emails, or boilerplate code using local JSON/YAML data.
---
## `artifact_postgres_export.sh`
## 🛠️ Developer Utilities
**Export code artifacts from Open WebUI PostgreSQL database**
* **`doc_bash_generate.sh`**: Automatic documentation generator for Bash scripts.
* **`doc_rust_generate.sh`**: Documentation helper for Rust projects.
* **`css_json_convert.sh`**: Bi-directional conversion between CSS variables and JSON objects.
* **`artifact_postgres_export.sh`**: Styled database export and snapshot utility.
Extract code artifacts from chat conversations stored in PostgreSQL, preserving directory structure and file names.
### Usage
```bash
artifact_postgres_export.sh [OPTIONS] <chat_id> <output_dir>
```
### Arguments
- `chat_id` - Chat ID from Open WebUI URL (UUID format)
- `output_dir` - Directory to save extracted code files
### Options
- `-H, --host HOST` - PostgreSQL host (default: ai_postgres via Docker)
- `-u, --user USER` - PostgreSQL user (default: ai)
- `-d, --db DATABASE` - PostgreSQL database (default: openwebui)
- `-v, --verbose` - Verbose output
- `--remote HOST` - SSH remote host for Docker access (default: vps)
- `-f, --force` - Force export even if output directory is not empty
### Features
- **Direct PostgreSQL access** via Docker exec (SSH-enabled for remote servers)
- **Automatic filename detection** from markdown headers
- **Directory structure preservation** - maintains original paths
- **Safety checks** - validates chat ID format and checks for empty output directory
- **Smart code extraction** - parses markdown code blocks with language detection
- **File extension mapping** - supports 20+ file types
### Examples
```bash
# Export chat to local directory
artifact_postgres_export.sh e135d74e-5b43-4b24-a651-e999f103942b ~/Projects/rust/piglet
# Export from remote server
artifact_postgres_export.sh --remote vps abc123def456 ./output
# Force export to non-empty directory
artifact_postgres_export.sh -f e135d74e-5b43-4b24-a651-e999f103942b ./output
```
---
## `css_color_filter.sh`
**CSS Color Filter Generator**
Generate CSS filter values to transform black elements into any target color using SPSA optimization.
### Usage
```bash
css_color_filter.sh [OPTIONS] [COLOR]
```
### Arguments
- `COLOR` - Hex color (e.g., #FF0000, ff0000) or RGB (e.g., 255,0,0)
### Options
- `-i, --interactive` - Interactive mode with colored preview
- `-r, --raw` - Output only the CSS filter (for piping)
- `-c, --copy` - Copy result to clipboard automatically
- `-h, --help` - Show help message
### Examples
```bash
css_color_filter.sh "#FF5733"
css_color_filter.sh ff5733
css_color_filter.sh "255,87,51"
css_color_filter.sh -i
```
### Algorithm
Uses SPSA (Simultaneous Perturbation Stochastic Approximation) to find optimal filter combinations that minimize color difference in RGB and HSL color spaces.
### Dependencies
- `bc` - For floating-point arithmetic
- `jq` - For JSON formatting (optional)
---
## `css_color_palette.sh`
**CSS Color Palette Generator (Pure Bash)**
Generate comprehensive color palettes without Node.js dependencies. Supports multiple harmony types and color scales.
### Usage
```bash
css_color_palette.sh COLOR [OPTIONS]
```
### Arguments
- `COLOR` - Base hex color (e.g., #3498db, 3498db)
### Options
- `-p, --palette TYPE` - Palette type: monochromatic, analogous, complementary, split-complementary, triadic, tetradic
- `-o, --output FILE` - Output file (default: ./colors.yaml)
- `-m, --mode MODE` - Color mode: light, dark (default: light)
- `-s, --style STYLE` - Style: shades, tints, tones, all (default: all)
- `-n, --name NAME` - Palette name (default: auto-generated)
- `--scales N` - Number of scale steps (default: 11)
- `-i, --interactive` - Interactive mode
- `-v, --verbose` - Verbose output with color preview
### Examples
```bash
css_color_palette.sh "#3498db"
css_color_palette.sh "#3498db" -p triadic -o palette.json
css_color_palette.sh "ff5733" -p analogous -m dark
```
### Dependencies
- `bc` - For floating-point arithmetic
---
## `css_json_convert.sh`
**CSS Variable to JSON/YAML Converter**
Extract CSS custom properties (variables) from a CSS file and convert them to JSON or YAML format.
### Usage
```bash
css_json_convert.sh [OPTIONS] <input.css>
```
### Arguments
- `<input.css>` - Input CSS file containing CSS variables
### Options
- `-o, --output FILE` - Output file path (default: ./output.yaml)
- `-c, --camel-case` - Convert variable names to camelCase
- `-v, --verbose` - Enable verbose output
- `-h, --help` - Show help message
### Examples
```bash
# Extract CSS vars to YAML (default)
css_json_convert.sh styles.css
# Extract to JSON with custom output
css_json_convert.sh styles.css -o theme.json
# Convert variable names to camelCase
css_json_convert.sh styles.css -o vars.json --camel-case
```
---
## `doc_bash_generate.sh`
**Bash Documentation Generator with Animated GIFs**
Generate comprehensive README.md files with embedded asciinema GIFs for bash scripts.
### Usage
```bash
doc_bash_generate.sh [OPTIONS] <executable> [executable...]
```
### Arguments
- `executable` - One or more executables or glob patterns
### Options
- `-o, --output FILE` - Output README.md path (default: ./README.md)
- `-t, --title TITLE` - Documentation title (default: auto-generated)
- `--no-gif` - Skip GIF generation (faster, text only)
- `--gif-only` - Only generate GIFs, don't update README
- `-h, --help` - Show help message
### Examples
```bash
doc_bash_generate.sh css_*.sh
doc_bash_generate.sh -o docs/README.md *.sh
doc_bash_generate.sh --title "My Awesome Tools" script1.sh script2.sh
```
### Dependencies
- `asciinema` - Terminal session recorder
- `agg` - Asciinema to GIF converter (cargo install agg)
---
## `doc_rust_generate.sh`
**Rust Documentation Generator with Custom Themes**
Generate beautiful Rust documentation with custom color schemes and styling.
### Usage
```bash
doc_rust_generate.sh [OPTIONS] <inputs...>
```
### Arguments
- `<inputs>` - Input file(s) or pattern(s) to document:
- Rust project directories (containing Cargo.toml)
- Individual .rs files
- Markdown files (.md)
- JSON/TOML configuration files
- Glob patterns (e.g., src/**/*.rs)
### Options
- `-o, --output DIR` - Output directory for generated docs (default: $PWD/output)
- `-c, --color COLOR` - Primary accent color (hex format, default: #ff69b4)
- `-s, --style STYLE` - Background style theme: slate, zinc, neutral, stone, gray (default: slate)
- `--font-sans FONT` - Google Font for body text (default: Inter)
- `--font-mono FONT` - Google Font for code blocks (default: JetBrains Mono)
- `--serve` - Start HTTP server after generation
- `--open` - Open documentation in browser (implies --serve)
- `-p, --port PORT` - Port for HTTP server (default: 8000)
- `-v, --verbose` - Enable verbose output
- `-d, --dry-run` - Show what would be done without executing
### Examples
```bash
# Generate docs for current Rust project
doc_rust_generate.sh .
# Custom color scheme
doc_rust_generate.sh . -c "#3498db" -s zinc -o ./docs
# Document specific files
doc_rust_generate.sh src/lib.rs src/main.rs -o ./api-docs
# Use custom fonts
doc_rust_generate.sh . --font-sans "Roboto" --font-mono "Fira Code"
# Generate and open in browser
doc_rust_generate.sh . --open
```
### Dependencies
- cargo, rustdoc, bc, yq, jq, python3 with jinja2
---
## `jinja_template_render.sh`
**Jinja2 Template Renderer - Ninja Edition**
A sophisticated Jinja2 template rendering engine with support for multiple variable sources, glob patterns, and ninja-style operations.
### Usage
```bash
jinja_template_render.sh [OPTIONS] <template> [template...]
```
### Arguments
- `<template>` - Template file(s) to render (glob patterns supported)
### Options
- `-o, --output DIR` - Output directory (default: ./output)
- `-v, --var KEY=VALUE` - Define template variable (can be used multiple times)
- `-f, --file FILE` - Load variables from JSON/YAML file (repeatable)
- `-V, --verbose` - Enable verbose ninja commentary
- `-p, --preview` - Preview rendered output without saving
- `-s, --strict` - Enable strict mode (fail on undefined variables)
- `-d, --dry-run` - Perform dry run without writing files
- `-w, --watch` - Watch templates and re-render on changes (experimental)
### Examples
```bash
# Render single template with CLI variables
jinja_template_render.sh template.j2 -v name=Ninja -v level=Master
# Render multiple templates with YAML config
jinja_template_render.sh templates/*.j2 -f config.yaml -o dist/
# Render with multiple variable sources
jinja_template_render.sh app.j2 -f base.yaml -f env.json -v debug=true
# Preview without saving
jinja_template_render.sh template.j2 -f vars.yaml --preview --verbose
```
### Dependencies
- Python 3 with jinja2 package
- jq (for JSON parsing)
- yq (for YAML parsing)
---
## `mime_mp4_gif.sh`
**Advanced MP4 to GIF Converter**
Convert MP4 videos to animated GIFs with advanced frame extraction algorithms, interpolation functions, and magical effects.
### Usage
```bash
mime_mp4_gif.sh [OPTIONS] INPUT_FILE [OUTPUT_FILE]
```
### Arguments
- `INPUT_FILE` - Input MP4 video file (required)
- `OUTPUT_FILE` - Output GIF file (optional, defaults to INPUT_FILE.gif)
### Options
- `-k, --keyframes N` - Number of keyframes to extract (default: 10)
- `-d, --keyframe-duration MS` - Duration of each frame in milliseconds (default: 100, range: 1-30000)
- `-i, --input-schedules N` - Number of input schedules (default: 1)
- `-t, --transition TYPE` - Interpolation function for frame timing
- Available: linear, sinoid, cubic, quadratic, exponential, bounce, elastic (default: linear)
- `-s, --schedule TYPE` - Algorithm to distribute keyframes across schedules
- Available: uniform, front-load, back-load, center-peak, edge-peak, fibonacci, golden-ratio (default: uniform)
- `-m, --magic TYPE` - Apply magical effects to the GIF
- Available: none, psychedelic, dither-bloom, edge-glow, temporal-blur, chromatic-shift, vaporwave (default: none)
- `-v, --verbose` - Enable verbose output
### Examples
```bash
# Basic conversion with 15 keyframes
mime_mp4_gif.sh -k 15 video.mp4
# Fast animation with 50ms per frame
mime_mp4_gif.sh -k 20 -d 50 video.mp4
# Use sinusoidal transition with center-peak distribution
mime_mp4_gif.sh -t sinoid -s center-peak -k 20 video.mp4
# Apply psychedelic magic with fibonacci distribution
mime_mp4_gif.sh -m psychedelic -s fibonacci -k 13 video.mp4 trippy.gif
# Complex: 3 schedules with cubic interpolation and edge glow
mime_mp4_gif.sh -i 3 -t cubic -s front-load -m edge-glow -k 30 video.mp4
```
---
## Installation
All scripts are available in this repository. Make sure they are executable:
## 🚀 Getting Started
1. **Dependencies**: Most scripts require `curl`, `jq`, and `base64`.
2. **API Tokens**: For API-reliant scripts (like `img_api_generate.sh`), ensure your token is set in `~/.config/pivoine/token` or via environment variables.
3. **Permissions**: Ensure scripts are executable:
```bash
chmod +x *.sh
```
Add them to your PATH for easy access:
```bash
export PATH="$PATH:/home/valknar/bin"
```
Or create symbolic links in `/usr/local/bin`:
```bash
sudo ln -s /home/valknar/bin/*.sh /usr/local/bin/
```
## Common Dependencies
Most scripts require:
- `bash` (4.0+)
- `bc` - For floating-point arithmetic
- `git` - For repository operations (arty.sh)
- `yq` - For YAML parsing (arty.sh)
- `jq` - For JSON parsing
Additional dependencies are listed in each command's help output.
## Contributing
Contributions are welcome! Please ensure:
- Scripts follow bash best practices
- Include comprehensive `--help` output with usage examples
- Test scripts before submitting
## License
MIT License - See individual scripts for details.
---
*Scripts collection maintained by valknar*
*Created with ✨ by the Pivoine Engineering Team.*

View File

@@ -40,6 +40,7 @@ DIM='\033[2m'
CHECK_MARK="✓"
CROSS_MARK="✗"
QUESTION_MARK="?"
PALETTE="🎨"
SPARKLES="✨"
CAMERA="📸"
@@ -67,16 +68,16 @@ MODEL="flux-dev"
TOKEN=""
FACE_IMAGE=""
OUTPUT_FILE=""
NUM_IMAGES=1
SEED=""
NEGATIVE_PROMPT=""
GUIDANCE_SCALE=""
ASPECT_RATIO=""
RESOLUTION=""
STYLING=""
INPUT_IMAGE=""
ASYNC_MODE=false
DRY_RUN=false
VERBOSE=false
UPSCALE=false
INTERACTIVE=false
# Temp files for cleanup
_TMP_FILES=()
@@ -137,6 +138,22 @@ print_verbose() {
fi
}
prompt_confirm() {
local message="$1"
if [[ "$INTERACTIVE" == false ]]; then
return 0
fi
echo -en "${BOLD_YELLOW}${QUESTION_MARK} ${message} [y/N] ${RESET}"
read -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "Operation cancelled by user."
return 1
fi
return 0
}
# ============================================================================
# SPINNER
# ============================================================================
@@ -270,33 +287,10 @@ validate_inputs() {
((errors++))
fi
# Numeric range checks
if [[ -n "$NUM_IMAGES" ]]; then
if ! [[ "$NUM_IMAGES" =~ ^[1-4]$ ]]; then
print_error "Number of images must be 1-4 (got: $NUM_IMAGES)"
((errors++))
fi
fi
if [[ -n "$GUIDANCE_SCALE" ]]; then
if ! awk "BEGIN {exit ($GUIDANCE_SCALE >= 1.0 && $GUIDANCE_SCALE <= 20.0) ? 0 : 1}" 2>/dev/null; then
print_error "Guidance scale must be 1.0-20.0 (got: $GUIDANCE_SCALE)"
((errors++))
fi
if [[ "$MODEL" != "flux-dev" && "$MODEL" != "flux-pro" ]]; then
print_warning "Guidance scale is only supported for flux models (ignoring)"
GUIDANCE_SCALE=""
fi
fi
if [[ -n "$NEGATIVE_PROMPT" && "$MODEL" != "mystic" ]]; then
print_warning "Negative prompt is only supported for mystic model (ignoring)"
NEGATIVE_PROMPT=""
fi
if [[ -n "$ASPECT_RATIO" && "$MODEL" != "seedream" ]]; then
print_warning "Aspect ratio is only supported for seedream model (ignoring)"
ASPECT_RATIO=""
# Resolution (mystic only)
if [[ -n "$RESOLUTION" && "$MODEL" != "mystic" ]]; then
print_warning "Resolution is only supported for mystic model (ignoring)"
RESOLUTION=""
fi
if ((errors > 0)); then
@@ -310,12 +304,15 @@ validate_inputs() {
# OUTPUT FILENAME GENERATION
# ============================================================================
_GENERATED_TIMESTAMP=""
generate_output_filename() {
local suffix="${1:-}"
local timestamp
timestamp=$(date +%Y%m%d_%H%M%S)
if [[ -z "$_GENERATED_TIMESTAMP" ]]; then
_GENERATED_TIMESTAMP=$(date +%Y%m%d_%H%M%S)
fi
local seed_part="${SEED:-0}"
local base="img_${MODEL}_${timestamp}_${seed_part}"
local base="img_${MODEL}_${_GENERATED_TIMESTAMP}_${seed_part}"
if [[ -n "$suffix" ]]; then
echo "${base}_${suffix}.png"
@@ -334,38 +331,42 @@ build_payload() {
# Start with required fields
payload=$(jq -n \
--arg prompt "$PROMPT" \
--argjson num_images "$NUM_IMAGES" \
'{prompt: $prompt, num_images: $num_images}')
'{prompt: $prompt}')
# Optional: seed
if [[ -n "$SEED" ]]; then
payload=$(echo "$payload" | jq --argjson seed "$SEED" '. + {seed: $seed}')
fi
# Optional: negative prompt (mystic only)
if [[ -n "$NEGATIVE_PROMPT" ]]; then
payload=$(echo "$payload" | jq --arg neg "$NEGATIVE_PROMPT" '. + {negative_prompt: $neg}')
fi
# Optional: guidance scale (flux models)
if [[ -n "$GUIDANCE_SCALE" ]]; then
payload=$(echo "$payload" | jq --argjson gs "$GUIDANCE_SCALE" '. + {guidance_scale: $gs}')
fi
# Optional: aspect ratio (seedream)
# Optional: aspect ratio (All models)
if [[ -n "$ASPECT_RATIO" ]]; then
payload=$(echo "$payload" | jq --arg ar "$ASPECT_RATIO" '. + {aspect_ratio: $ar}')
fi
# Optional: input image (img2img)
# Optional: resolution (mystic only)
if [[ -n "$RESOLUTION" ]]; then
payload=$(echo "$payload" | jq --arg res "$RESOLUTION" '. + {resolution: $res}')
fi
# Optional: styling
if [[ -n "$STYLING" ]]; then
# If STYLING starts with {, treat as JSON, else treat as a simple string if possible
if [[ "$STYLING" == {* ]]; then
payload=$(echo "$payload" | jq --argjson sty "$STYLING" '. + {styling: $sty}')
else
payload=$(echo "$payload" | jq --arg sty "$STYLING" '. + {styling: {style: $sty}}')
fi
fi
# Optional: input image / reference images (mystic supports structure/style ref)
# For now, we keep it simple or align with the specific model's needs.
# The API schema for mystic has structure_reference and style_reference.
if [[ -n "$INPUT_IMAGE" ]]; then
local b64
b64=$(base64 -w 0 "$INPUT_IMAGE")
local mime
mime=$(file -b --mime-type "$INPUT_IMAGE")
payload=$(echo "$payload" | jq \
--arg img "data:${mime};base64,${b64}" \
'. + {image: $img}')
if [[ "$MODEL" == "mystic" ]]; then
payload=$(echo "$payload" | jq --arg img "$b64" '. + {structure_reference: $img}')
fi
fi
echo "$payload"
@@ -534,6 +535,7 @@ fix_extension() {
generate_image() {
local payload="$1"
# Note: URL prefix aligned with actual API endpoints
local url="${BASE_URL}/freepik/generate/image/${MODEL}"
if [[ "$ASYNC_MODE" == false ]]; then
@@ -561,12 +563,14 @@ generate_image() {
print_field "$PALETTE" "Model" "$MODEL"
print_field "$SPARKLES" "Prompt" "$(echo "$PROMPT" | head -c 80)$([ ${#PROMPT} -gt 80 ] && echo '...')"
[[ -n "$SEED" ]] && print_field " " "Seed" "$SEED"
[[ -n "$NEGATIVE_PROMPT" ]] && print_field " " "Negative" "$(echo "$NEGATIVE_PROMPT" | head -c 60)..."
[[ -n "$GUIDANCE_SCALE" ]] && print_field " " "Guidance" "$GUIDANCE_SCALE"
[[ -n "$ASPECT_RATIO" ]] && print_field " " "Aspect" "$ASPECT_RATIO"
[[ -n "$RESOLUTION" ]] && print_field " " "Resolution" "$RESOLUTION"
[[ -n "$STYLING" ]] && print_field " " "Styling" "$STYLING"
[[ -n "$INPUT_IMAGE" ]] && print_field " " "Input Image" "$INPUT_IMAGE"
echo ""
prompt_confirm "Proceed with image generation?" || return 1
local response
if [[ "$ASYNC_MODE" == false ]]; then
# Synchronous mode - wait with spinner
@@ -703,6 +707,8 @@ download_result() {
print_detail "Downloading result..."
prompt_confirm "Download generated image?" || return 1
api_curl_binary GET "$url" "$_dl_output_path" || return 1
if [[ -f "$_dl_output_path" && -s "$_dl_output_path" ]]; then
@@ -746,6 +752,8 @@ swap_face() {
print_field "$CAMERA" "Target" "$target_image"
echo ""
prompt_confirm "Proceed with face swap?" || return 1
local options='{"processors":["face_swapper","face_enhancer"],"face_swapper":{"model":"hyperswap_1a_256"},"face_enhancer":{"model":"gfpgan_1.4","blend":80}}'
local tmp_resp
@@ -802,6 +810,8 @@ realesrgan_upscale() {
print_field "$CAMERA" "Input" "$input_image"
echo ""
prompt_confirm "Proceed with image upscaling?" || return 1
local tmp_resp
tmp_resp=$(mktemp)
_TMP_FILES+=("$tmp_resp")
@@ -846,12 +856,11 @@ REQUIRED:
MODEL & GENERATION:
-m, --model MODEL Model name (default: flux-dev)
Available: mystic, flux-dev, flux-pro, seedream
-n, --num-images N Number of images 1-4 (default: 1)
-s, --seed N Seed for reproducibility
--negative-prompt TEXT Negative prompt (mystic model only)
--guidance-scale N Guidance scale 1.0-20.0 (flux models only)
--aspect-ratio RATIO Aspect ratio (seedream model only)
--image FILE Input image for img2img (base64-encoded automatically)
--aspect-ratio RATIO Aspect ratio (e.g. square_1_1, widescreen_16_9)
--resolution RES Resolution (mystic model only: 1k, 2k, 4k)
--styling STYLE Styling (JSON string or name)
--image FILE Input image for reference (mystic model only)
AUTHENTICATION:
-t, --token TOKEN API token (X-Api-Key)
@@ -868,16 +877,16 @@ OUTPUT:
MODES:
--async Use async mode with polling instead of sync
--dry-run Show curl commands without executing
-i, --interactive Prompt before each API call
--verbose Verbose output
-h, --help Show this help message
EXAMPLES:
# Generate with flux-dev (default model)
./img_api_generate.sh -p "a cat sitting on a rainbow"
# Generate with flux-dev (default model) and custom aspect ratio
./img_api_generate.sh -p "a cat sitting on a rainbow" --aspect-ratio widescreen_16_9
# Generate with mystic model and negative prompt
./img_api_generate.sh -p "photorealistic portrait" -m mystic \
--negative-prompt "blurry, low quality"
# Generate with mystic model and specific resolution
./img_api_generate.sh -p "photorealistic portrait" -m mystic --resolution 2k
# Generate and face swap
./img_api_generate.sh -p "portrait of a person" -m mystic -f face.jpg
@@ -885,9 +894,6 @@ EXAMPLES:
# Dry run to preview API calls
./img_api_generate.sh --dry-run -p "a cat" -m flux-dev
# Use a specific seed for reproducibility
./img_api_generate.sh -p "landscape at sunset" -s 42 -m flux-pro
EOF
}
@@ -918,26 +924,22 @@ parse_args() {
OUTPUT_FILE="$2"
shift 2
;;
-n|--num-images)
NUM_IMAGES="$2"
shift 2
;;
-s|--seed)
SEED="$2"
shift 2
;;
--negative-prompt)
NEGATIVE_PROMPT="$2"
shift 2
;;
--guidance-scale)
GUIDANCE_SCALE="$2"
shift 2
;;
--aspect-ratio)
ASPECT_RATIO="$2"
shift 2
;;
--resolution)
RESOLUTION="$2"
shift 2
;;
--styling)
STYLING="$2"
shift 2
;;
--image)
INPUT_IMAGE="$2"
shift 2
@@ -946,6 +948,10 @@ parse_args() {
ASYNC_MODE=true
shift
;;
-i|--interactive)
INTERACTIVE=true
shift
;;
--dry-run)
DRY_RUN=true
shift
@@ -998,6 +1004,9 @@ main() {
# Validate inputs
validate_inputs
# Initialize timestamp for consistent naming across subshells
_GENERATED_TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Banner
print_banner "${PALETTE} Pivoine Image Generator ${SPARKLES}"
@@ -1071,15 +1080,22 @@ main() {
local ext="${OUTPUT_FILE##*.}"
local base="${OUTPUT_FILE%.*}"
upscale_path="${base}_upscaled.${ext}"
else
# Include faceswap in name if it was performed
if [[ -n "${faceswap_path:-}" && -f "${faceswap_path}" ]]; then
upscale_path="$(generate_output_filename "faceswap_upscaled")"
else
upscale_path="$(generate_output_filename "upscaled")"
fi
fi
realesrgan_upscale "$final_input" upscale_path || exit 1
realesrgan_upscale "$final_input" upscale_path || true
# Use the upscaled image for summary/output
# Use the upscaled image for summary/output if it was created
if [[ -f "${upscale_path:-}" ]]; then
output_path="$upscale_path"
fi
fi
# Summary
print_section "Summary"
@@ -1089,6 +1105,8 @@ main() {
print_field "$FACE" "Face Swap" "$faceswap_path"
fi
[[ -n "$SEED" ]] && print_field " " "Seed" "$SEED"
[[ -n "$ASPECT_RATIO" ]] && print_field " " "Aspect" "$ASPECT_RATIO"
[[ -n "$RESOLUTION" ]] && print_field " " "Resolution" "$RESOLUTION"
echo ""
print_banner "${SPARKLES} Complete ${SPARKLES}"