Files

52 lines
5.4 KiB
PowerShell
Raw Permalink Normal View History

$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
if (-not $env:FAL_KEY) { $env:FAL_KEY = [System.Environment]::GetEnvironmentVariable("FAL_KEY","User") }
if (-not $env:FAL_KEY) { throw "FAL_KEY not set." }
$auth = @{ Authorization = "Key $env:FAL_KEY" }
$dir = "C:\Users\CAN\tinqs-ltd\tattoo-test\gen-v4"
$log = "$dir\_gen-marks-v4.log"
"START $(Get-Date -Format o)" | Out-File $log
# v4: generated INTO the exact UV-island silhouette. Arms/legs are FULL SLEEVES:
# dense allover coverage, zero bare skin. Torso plates fill their whole silhouette.
$style = "Polynesian / Micronesian TRIBAL tattoo, solid black ink on off-white parchment. ONE clear bold hero symbol carried by tribal detailing: thin NEGATIVE-SPACE lines carved through the thick black shapes, small koru spirals, shark-tooth (niho) notches and light dotwork. Confident linework, strong tribal character."
$fill = "The input image shows a light parchment SILHOUETTE on a black background - it is the UV texture island of a 3D character's body part. Fill the ENTIRE parchment silhouette with the tattoo design so it reaches EVERY edge of the silhouette. Keep the black background outside the silhouette pure black and untouched. The silhouette's vertical axis maps to the body part: TOP of the silhouette is the TOP of the body part."
$sleeve = "This is a FULL SLEEVE: cover the COMPLETE silhouette with dense, continuous tribal patternwork - stacked horizontal pattern bands (niho teeth rows, current lines, koru scroll bands, dotwork bands) flowing from the very top edge to the very bottom edge. Parchment may only appear as thin negative-space linework INSIDE the pattern, never as empty regions. ABSOLUTELY NO bare parchment areas, margins or gaps anywhere inside the silhouette."
$plate = "Fill the whole silhouette with the piece: bold hero plus supporting pattern bands reaching every edge, parchment only as carved negative-space detail inside the pattern."
$neg = "No color, no grey shading, no gradient, no photoreal, no 3D, no human figure, no text. Keep the carved negative-space detail crisp - not a solid featureless black blob."
$jobs = @(
@{ part="arm_r"; mark="chiefs-mark"; mode="sleeve"; d="Theme - CHIEF'S CREST: hero is a bold spearhead crown with a fan of broad rays at the TOP (shoulder); below it, continuous bands of interlocking koru spirals and niho tooth rows all the way down to the BOTTOM edge (wrist)." }
@{ part="arm_l"; mark="iron-spine"; mode="sleeve"; d="Theme - IRON SPINE (warrior): hero is two bold crossed spears with barbed heads at the TOP (shoulder); below it, continuous stacked rows of shark-tooth (niho) triangles, spearhead chevrons and small spirals down to the BOTTOM edge (wrist)." }
@{ part="leg_r"; mark="voyagers-current"; mode="sleeve"; d="Theme - VOYAGER'S CURRENT (ocean): hero is a big bold curling koru WAVE at the TOP (thigh); below it, continuous flowing current bands, wave scrolls and spiral eddies down to the BOTTOM edge (ankle)." }
@{ part="leg_l"; mark="storm-bearer"; mode="sleeve"; d="Theme - STORM BEARER: hero is a bold LIGHTNING bolt flanked by two storm-cloud koru scrolls at the TOP (thigh); below it, continuous bands of jagged rain lines, zigzag bolts and dotwork down to the BOTTOM edge (ankle)." }
@{ part="chest"; mark="star-eye"; mode="plate"; d="Theme - STAR EYE (navigator): hero is a bold eight-point STAR with a carved spiral center, high on the silhouette (chest); a navigator's line band with star dots sweeps symmetrically outward and down the abdomen to the BOTTOM edge. SYMMETRICAL layout." }
@{ part="back"; mark="hearth-warmth"; mode="plate"; d="Theme - HEARTH WARMTH (fire): hero is a bold three-tongue FLAME whose tip reaches the TOP edge (neck); a radiant base of carved rays and ember dotwork spreads down to the BOTTOM edge (lower back). SYMMETRICAL layout." }
)
$perImage = 0.17 # GPT Image 2 edit, quality=high (estimate)
$runCost = 0.0; $ok = 0; $fail = 0; $skip = 0
foreach ($j in $jobs) {
$name = "v4_$($j.part)_$($j.mark)"
$path = "$dir\$name.png"
if (Test-Path $path) { $skip++; "SKIP $name (exists)" | Tee-Object -FilePath $log -Append | Out-Null; continue }
Write-Host "=== $name ===" -ForegroundColor Cyan
$canvasB64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes("$dir\canvas_$($j.part).png"))
$coverage = if ($j.mode -eq "sleeve") { $sleeve } else { $plate }
$prompt = "$style`n$fill`n$coverage`n$($j.d)`nSTRICT: $neg"
try {
$body = @{ prompt=$prompt; image_urls=@("data:image/png;base64,$canvasB64"); image_size="square"; quality="high"; num_images=1 } | ConvertTo-Json -Depth 6 -Compress
$resp = Invoke-RestMethod -Method Post -Uri "https://fal.run/openai/gpt-image-2/edit" -Headers $auth -ContentType 'application/json' -Body $body -TimeoutSec 600
Invoke-WebRequest -Uri $resp.images[0].url -OutFile $path -TimeoutSec 300
$runCost += $perImage; $ok++
"OK $name" | Tee-Object -FilePath $log -Append | Out-Null
Write-Host " OK" -ForegroundColor Green
} catch {
$fail++
"FAIL $name : $($_.Exception.Message) $($_.ErrorDetails.Message)" | Tee-Object -FilePath $log -Append | Out-Null
Write-Host " FAIL: $($_.Exception.Message)" -ForegroundColor Red
}
}
"DONE ok=$ok fail=$fail skip=$skip RUN_COST_USD=$([math]::Round($runCost,2)) $(Get-Date -Format o)" | Tee-Object -FilePath $log -Append
Write-Host ("RUN_COST_USD={0:N2} ok={1} fail={2} skip={3}" -f $runCost,$ok,$fail,$skip) -ForegroundColor Yellow