Skip to content

Commit 0f27812

Browse files
committed
fix(image): add --out flag for saving to exact file path
Closes #112
1 parent 527e06d commit 0f27812

1 file changed

Lines changed: 28 additions & 12 deletions

File tree

src/commands/image/generate.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { Config } from '../../config/schema';
99
import type { GlobalFlags } from '../../types/flags';
1010
import type { ImageRequest, ImageResponse } from '../../types/api';
1111
import { mkdirSync, existsSync, readFileSync } from 'fs';
12-
import { join, resolve, extname } from 'path';
12+
import { dirname, join, resolve, extname } from 'path';
1313

1414
const MIME_TYPES: Record<string, string> = {
1515
'.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
@@ -33,6 +33,7 @@ export default defineCommand({
3333
{ flag: '--prompt-optimizer', description: 'Automatically optimize the prompt before generation for better results.' },
3434
{ flag: '--aigc-watermark', description: 'Embed AI-generated content watermark in the output image.' },
3535
{ flag: '--subject-ref <params>', description: 'Subject reference for character consistency. Format: type=character,image=path-or-url' },
36+
{ flag: '--out <path>', description: 'Save image to exact file path (single image only)' },
3637
{ flag: '--out-dir <dir>', description: 'Download images to directory' },
3738
{ flag: '--out-prefix <prefix>', description: 'Filename prefix (default: image)' },
3839
],
@@ -46,6 +47,8 @@ export default defineCommand({
4647
'mmx image generate --prompt "Wide landscape" --width 1920 --height 1080',
4748
'# Optimized prompt with watermark',
4849
'mmx image generate --prompt "sunset" --prompt-optimizer --aigc-watermark',
50+
'# Save to exact path',
51+
'mmx image generate --prompt "A cat" --out /tmp/cat.jpg',
4952
],
5053
async run(config: Config, flags: GlobalFlags) {
5154
let prompt = (flags.prompt ?? (flags._positional as string[]|undefined)?.[0]) as string | undefined;
@@ -88,6 +91,11 @@ export default defineCommand({
8891
validateSize('height', height);
8992
}
9093

94+
const outPath = flags.out as string | undefined;
95+
if (outPath && (flags.n as number) > 1) {
96+
throw new CLIError('--out cannot be used with --n > 1. Use --out-dir instead.', ExitCode.USAGE);
97+
}
98+
9199
const body: ImageRequest = {
92100
model: 'image-01',
93101
prompt,
@@ -149,23 +157,31 @@ export default defineCommand({
149157
process.stderr.write('[Model: image-01]\n');
150158
}
151159

152-
const outDir = (flags.outDir as string | undefined) ?? '.';
153-
if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
154-
155-
const prefix = (flags.outPrefix as string) || 'image';
156160
const saved: string[] = [];
157161

158-
for (let i = 0; i < imageUrls.length; i++) {
159-
const filename = `${prefix}_${String(i + 1).padStart(3, '0')}.jpg`;
160-
const destPath = join(outDir, filename);
161-
162-
// Warn if overwriting existing file (but don't block)
162+
if (outPath) {
163+
const dir = dirname(resolve(outPath));
164+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
165+
const destPath = resolve(outPath);
163166
if (existsSync(destPath)) {
164167
process.stderr.write(`Warning: overwriting existing file: ${destPath}\n`);
165168
}
166-
167-
await downloadFile(imageUrls[i]!, destPath, { quiet: config.quiet });
169+
await downloadFile(imageUrls[0]!, destPath, { quiet: config.quiet });
168170
saved.push(destPath);
171+
} else {
172+
const outDir = (flags.outDir as string | undefined) ?? '.';
173+
if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
174+
const prefix = (flags.outPrefix as string) || 'image';
175+
176+
for (let i = 0; i < imageUrls.length; i++) {
177+
const filename = `${prefix}_${String(i + 1).padStart(3, '0')}.jpg`;
178+
const destPath = join(outDir, filename);
179+
if (existsSync(destPath)) {
180+
process.stderr.write(`Warning: overwriting existing file: ${destPath}\n`);
181+
}
182+
await downloadFile(imageUrls[i]!, destPath, { quiet: config.quiet });
183+
saved.push(destPath);
184+
}
169185
}
170186

171187
// --output json is respected even in --quiet mode (JSON is the actual output, not progress)

0 commit comments

Comments
 (0)