#!/usr/bin/env node // Prints the request for the optional relight step (a badly lit photo, before the grade). It does not call any API. // Usage: // node scripts/build-relight-input.mjs --photo photo.jpg [--light "soft late-afternoon sun"] [--out relight.json] // --photo takes a local file (embedded as a data URI, so it never has to be uploaded publicly) or a public https URL. import { readFileSync, writeFileSync, existsSync } from 'node:fs' import { dirname, join, extname } from 'node:path' import { fileURLToPath } from 'node:url' const root = join(dirname(fileURLToPath(import.meta.url)), '..') const usage = 'Usage: node scripts/build-relight-input.mjs --photo [--light "soft, even daylight"] [--out relight.json]' const VALUE_FLAGS = new Set(['photo', 'light', 'out']) const fail = (message) => { console.error(`${message}\n${usage}`); process.exit(1) } const options = {} const args = process.argv.slice(2) for (let i = 0; i < args.length; i += 1) { const arg = args[i] if (!arg.startsWith('--')) fail(`Unexpected argument "${arg}".`) const key = arg.slice(2) if (!VALUE_FLAGS.has(key)) fail(`Unknown flag --${key}.`) const value = args[i + 1] if (value === undefined || value.startsWith('--')) fail(`--${key} needs a value.`) options[key] = value i += 1 } if (!options.photo) fail('--photo is required.') const MIME = { '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.webp': 'image/webp' } let photo = options.photo if (!/^https:\/\//.test(photo)) { if (!existsSync(photo)) fail(`Photo not found: ${photo}`) const mime = MIME[extname(photo).toLowerCase()] if (!mime) fail('The photo must be .jpg, .png or .webp.') photo = `data:${mime};base64,${readFileSync(photo).toString('base64')}` } const settings = JSON.parse(readFileSync(join(root, 'assets/generation-input.json'), 'utf8')).relight const template = readFileSync(join(root, 'assets/prompt-template.md'), 'utf8').trim() const light = options.light ?? settings.default_light // A replacer function keeps any "$" in the text literal. const prompt = template.replace('{{light}}', () => light) const output = JSON.stringify({ model: settings.model, input: { ...settings.input, image_urls: [photo], prompt } }, null, 2) if (options.out) { writeFileSync(options.out, output) console.log(`Wrote the relight request to ${options.out}`) } else console.log(output)