← back to Wallco Ai
scripts/dig1984_facesup_master_preprocess.js
86 lines
#!/usr/bin/env node
/**
* Option A: pre-process DIG-1984 into a "FacesUp Master" — one Gemini call
* to RE-ORIENT every leaf to face upward while preserving the chinoiserie
* composition, butterflies, and flowers. If Gemini honors the recompose
* here, the resulting master image becomes the source for the 100-colorway
* batch (each downstream recolor inherits the directional fix).
*
* Output: /tmp/wallco-sources/DIG-1984-facesup-master.png
* Cost: ~$0.001 (1 image)
*
* Run: cd ~/Projects/wallco-ai && node scripts/dig1984_facesup_master_preprocess.js
*/
'use strict';
require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') });
const fs = require('fs');
const path = require('path');
const KEY = process.env.GEMINI_API_KEY;
if (!KEY) { console.error('GEMINI_API_KEY missing'); process.exit(1); }
const SRC = '/tmp/wallco-sources/DIG-1984.jpg';
const OUT = '/tmp/wallco-sources/DIG-1984-facesup-master.png';
if (!fs.existsSync(SRC)) { console.error(`source missing: ${SRC}`); process.exit(1); }
const SRC_B64 = fs.readFileSync(SRC).toString('base64');
const PROMPT = [
'TASK: Re-orient the foliage in this chinoiserie wallpaper pattern.',
'',
'KEEP IDENTICAL:',
'- The overall composition, vine paths, and pattern scale.',
'- Every butterfly: same positions, same colors, same shapes.',
'- Every flower: same positions, same colors, same shapes.',
'- The white/cream background.',
'- The branch and vine networks.',
'',
'CHANGE (the only change):',
'- ROTATE every individual leaf so its tip points UPWARD toward the top of the tile.',
'- This applies to EVERY leaf — large leaves, small leaves, accent leaves.',
'- A leaf that currently points sideways or downward must be rotated in place to point UP.',
'- The leaf STEM stays attached to its vine; only the leaf BLADE rotates around the stem.',
'- Single directional axis. NO leaves sideways. NO leaves downward.',
'',
'COMPLIANCE CHECK: when you are done, every leaf in the output must have its tip pointing toward the top of the image. If you cannot fully comply with this rule, redraw the leaves rather than leaving them mis-oriented.',
'',
'Output is a seamless wallpaper tile, archival quality, no signature, no watermark, no text.',
].join('\n');
(async () => {
console.log('Pre-processing DIG-1984 into FacesUp master…');
const body = {
contents: [{
parts: [
{ inline_data: { mime_type: 'image/jpeg', data: SRC_B64 } },
{ text: PROMPT }
]
}],
generationConfig: { responseModalities: ['IMAGE'] }
};
const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image:generateContent?key=${KEY}`;
const t0 = Date.now();
const r = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!r.ok) { console.error(`HTTP ${r.status}: ${(await r.text()).slice(0, 400)}`); process.exit(1); }
const j = await r.json();
try {
const { logGemini } = require(require('os').homedir() + '/.claude/skills/cost-tracker/scripts/log-gemini.js');
logGemini(j, { app: 'wallco-ai', note: 'dig-1984-facesup-master-preprocess', model: 'gemini-2.5-flash-image' });
} catch {}
const part = j.candidates?.[0]?.content?.parts?.find(p => p.inline_data || p.inlineData);
const data = part?.inline_data?.data || part?.inlineData?.data;
if (!data) {
const text = j.candidates?.[0]?.content?.parts?.find(p => p.text)?.text;
console.error(`no image returned (${j.candidates?.[0]?.finishReason || 'unknown'}): ${(text || '').slice(0, 400)}`);
process.exit(1);
}
fs.writeFileSync(OUT, Buffer.from(data, 'base64'));
const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
console.log(`\n✓ ${OUT} (${elapsed}s, ${(fs.statSync(OUT).size / 1024).toFixed(0)} KB)`);
console.log(`\nOpen for eyeball: open '${OUT}'`);
console.log(`If every leaf now faces UP, this is the new canonical source for the 100-colorway batch.`);
})();