GritAI-ComicPipeline / run_story.ps1
BonusLockSMith's picture
Upload run_story.ps1 with huggingface_hub
b8e878b verified
# run_story.ps1 - Multi-page story runner
# Generates consistent pages using same base_prompt/seed across all pages
param(
[Parameter(Mandatory=$true)]
[string]$StoryFile
)
$storyPath = Join-Path ".\stories" $StoryFile
if (-not (Test-Path $storyPath)) {
Write-Host "Story not found: $storyPath" -ForegroundColor Red
return
}
$story = Get-Content $storyPath -Raw | ConvertFrom-Json
$storyStart = Get-Date
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " STORY: $($story.story_title)" -ForegroundColor Cyan
Write-Host " Pages: $($story.pages.Count)" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
$storyOutput = ".\output\stories\$($story.story_id)"
New-Item -Path $storyOutput -ItemType Directory -Force | Out-Null
$pageNum = 0
foreach ($page in $story.pages) {
$pageNum++
Write-Host "
========================================" -ForegroundColor Yellow
Write-Host " PAGE $pageNum/$($story.pages.Count): $($page.page_title)" -ForegroundColor Yellow
Write-Host " Template: $($page.page_template) | Panels: $($page.panels.Count)" -ForegroundColor Yellow
Write-Host "========================================" -ForegroundColor Yellow
# Build temp scene JSON for this page
$pageScene = @{
scene_id = "$($story.story_id)_p$pageNum"
page_template = $page.page_template
panels = @()
global_settings = $story.global_settings
}
foreach ($panel in $page.panels) {
$pageScene.panels += @{
panel_id = $panel.panel_id
base_prompt = $story.base_prompt
seed = $story.base_seed
edit_prompt = $panel.edit_prompt
}
}
$tempFile = "_story_p$pageNum.json"
$pageScene | ConvertTo-Json -Depth 5 | Set-Content ".\scenes\$tempFile"
# Run full pipeline for this page
.\run_comic_pipeline.ps1 -SceneFile $tempFile
# Copy output to story folder
$pageFile = Get-ChildItem ".\output\stage3_pages" -Filter "page_$($story.story_id)_p$pageNum*" |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if ($pageFile) {
$destName = "page_$($pageNum.ToString('D2'))_$($page.page_title -replace ' ','_').png"
Copy-Item $pageFile.FullName -Destination (Join-Path $storyOutput $destName) -Force
Write-Host " Saved: $destName" -ForegroundColor Green
}
[System.Console]::Beep(800, 200)
}
# Add titles to all pages
Write-Host "
Adding titles..." -ForegroundColor Yellow
$pageFiles = Get-ChildItem $storyOutput -Filter "page_*.png" | Sort-Object Name
foreach ($pf in $pageFiles) {
$titleMatch = $pf.Name -match 'page_\d+_(.*?)\.png'
if ($titleMatch) {
$title = ($Matches[1] -replace '_',' ').ToUpper()
} else {
$title = "PAGE"
}
python -c "
from PIL import Image, ImageDraw, ImageFont
import math
img = Image.open(r'$($pf.FullName)')
pw, ph = img.size
bar_h = 140
new = Image.new('RGB', (pw, ph+bar_h), (10,8,20))
new.paste(img, (0, bar_h))
draw = ImageDraw.Draw(new)
font = ImageFont.truetype('C:/Windows/Fonts/impact.ttf', 90)
title = '$title'
bbox = draw.textbbox((0,0), title, font=font)
tw, th = bbox[2]-bbox[0], bbox[3]-bbox[1]
cx, cy = pw//2, bar_h//2
sweep, steps = 0.95, 100
r_top, r_bot = 220, 120
tp, bp = [], []
for i in range(steps+1):
t=i/steps; a=math.pi+(1-sweep)/2*math.pi+t*sweep*math.pi
tp.append((cx+int(pw*0.55*math.cos(a)), cy-15+r_top*math.sin(a)))
bp.append((cx+int(pw*0.55*math.cos(a)), cy+15+r_bot*math.sin(a)))
bp.reverse()
draw.polygon(tp+bp, fill=(100,10,10), outline=(0,0,0))
itp, ibp = [], []
for i in range(steps+1):
t=i/steps; a=math.pi+(1-sweep)/2*math.pi+t*sweep*math.pi
itp.append((cx+int(pw*0.53*math.cos(a)), cy-15+(r_top-10)*math.sin(a)))
ibp.append((cx+int(pw*0.53*math.cos(a)), cy+15+(r_bot+10)*math.sin(a)))
ibp.reverse()
draw.polygon(itp+ibp, fill=(190,20,20))
chars=list(title); cws=[]
for c in chars: b=draw.textbbox((0,0),c,font=font); cws.append(b[2]-b[0])
sp=8; ts=sum(cws)+sp*(len(chars)-1); cur=cx-ts//2
for i,c in enumerate(chars):
cw=cws[i]; ccx=cur+cw//2
t2=(ccx-cx)/(ts/2+1); yo=int(25*t2*t2); ad=-t2*9
tmp=Image.new('RGBA',(cw+30,th+30),(0,0,0,0)); td=ImageDraw.Draw(tmp)
for dx in [-4,-3,-2,0,2,3,4]:
for dy in [-4,-3,-2,0,2,3,4]:
if dx or dy: td.text((15+dx,15+dy),c,fill=(0,0,0,255),font=font)
td.text((15,15),c,fill=(255,215,0,255),font=font)
tmp=tmp.rotate(ad,expand=True,resample=Image.BICUBIC)
new.paste(tmp,(int(ccx-tmp.width//2),int(cy-th//2-10+yo)),tmp)
cur+=cw+sp
new.save(r'$($pf.FullName)')
print('Titled: $($pf.Name)')
"
}
# Build PDF
Write-Host "
Building PDF..." -ForegroundColor Yellow
$sortedPages = (Get-ChildItem $storyOutput -Filter "page_*.png" | Sort-Object Name | ForEach-Object { $_.FullName -replace '\\','/' })
$pyList = ($sortedPages | ForEach-Object { "'$_'" }) -join ","
python -c "
from PIL import Image
pages = [$pyList]
imgs = [Image.open(p).convert('RGB') for p in pages]
out = '$($storyOutput -replace '\\','/')/$($story.story_id)_complete.pdf'
imgs[0].save(out, save_all=True, append_images=imgs[1:], resolution=150)
print('PDF: ' + out + ' (' + str(len(imgs)) + ' pages)')
"
# Cleanup
Remove-Item ".\scenes\_story_*.json" -Force -ErrorAction SilentlyContinue
$totalMin = [math]::Round(((Get-Date)-$storyStart).TotalMinutes, 1)
Write-Host "
========================================" -ForegroundColor Green
Write-Host " STORY COMPLETE: $($story.story_title)" -ForegroundColor Green
Write-Host " Pages: $($story.pages.Count)" -ForegroundColor Green
Write-Host " Time: $totalMin min" -ForegroundColor Green
Write-Host " Output: $storyOutput" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
1000, 1200, 1500, 2000 | ForEach-Object { [System.Console]::Beep($_, 250) }