@mediaproc/image 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2516 -0
- package/bin/cli.js +6 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +89 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/auto-enhance.d.ts +3 -0
- package/dist/commands/auto-enhance.d.ts.map +1 -0
- package/dist/commands/auto-enhance.js +148 -0
- package/dist/commands/auto-enhance.js.map +1 -0
- package/dist/commands/batch.d.ts +3 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +230 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/blur.d.ts +3 -0
- package/dist/commands/blur.d.ts.map +1 -0
- package/dist/commands/blur.js +122 -0
- package/dist/commands/blur.js.map +1 -0
- package/dist/commands/border.d.ts +3 -0
- package/dist/commands/border.d.ts.map +1 -0
- package/dist/commands/border.js +122 -0
- package/dist/commands/border.js.map +1 -0
- package/dist/commands/clahe.d.ts +3 -0
- package/dist/commands/clahe.d.ts.map +1 -0
- package/dist/commands/clahe.js +121 -0
- package/dist/commands/clahe.js.map +1 -0
- package/dist/commands/composite.d.ts +3 -0
- package/dist/commands/composite.d.ts.map +1 -0
- package/dist/commands/composite.js +167 -0
- package/dist/commands/composite.js.map +1 -0
- package/dist/commands/convert.d.ts +3 -0
- package/dist/commands/convert.d.ts.map +1 -0
- package/dist/commands/convert.js +136 -0
- package/dist/commands/convert.js.map +1 -0
- package/dist/commands/convolve.d.ts +3 -0
- package/dist/commands/convolve.d.ts.map +1 -0
- package/dist/commands/convolve.js +171 -0
- package/dist/commands/convolve.js.map +1 -0
- package/dist/commands/crop.d.ts +3 -0
- package/dist/commands/crop.d.ts.map +1 -0
- package/dist/commands/crop.js +120 -0
- package/dist/commands/crop.js.map +1 -0
- package/dist/commands/dominant-color.d.ts +3 -0
- package/dist/commands/dominant-color.d.ts.map +1 -0
- package/dist/commands/dominant-color.js +175 -0
- package/dist/commands/dominant-color.js.map +1 -0
- package/dist/commands/extend.d.ts +3 -0
- package/dist/commands/extend.d.ts.map +1 -0
- package/dist/commands/extend.js +146 -0
- package/dist/commands/extend.js.map +1 -0
- package/dist/commands/extract.d.ts +3 -0
- package/dist/commands/extract.d.ts.map +1 -0
- package/dist/commands/extract.js +169 -0
- package/dist/commands/extract.js.map +1 -0
- package/dist/commands/flip.d.ts +3 -0
- package/dist/commands/flip.d.ts.map +1 -0
- package/dist/commands/flip.js +112 -0
- package/dist/commands/flip.js.map +1 -0
- package/dist/commands/gamma.d.ts +3 -0
- package/dist/commands/gamma.d.ts.map +1 -0
- package/dist/commands/gamma.js +129 -0
- package/dist/commands/gamma.js.map +1 -0
- package/dist/commands/grayscale.d.ts +3 -0
- package/dist/commands/grayscale.d.ts.map +1 -0
- package/dist/commands/grayscale.js +94 -0
- package/dist/commands/grayscale.js.map +1 -0
- package/dist/commands/grid.d.ts +3 -0
- package/dist/commands/grid.d.ts.map +1 -0
- package/dist/commands/grid.js +193 -0
- package/dist/commands/grid.js.map +1 -0
- package/dist/commands/median.d.ts +3 -0
- package/dist/commands/median.d.ts.map +1 -0
- package/dist/commands/median.js +132 -0
- package/dist/commands/median.js.map +1 -0
- package/dist/commands/metadata-cmd.d.ts +3 -0
- package/dist/commands/metadata-cmd.d.ts.map +1 -0
- package/dist/commands/metadata-cmd.js +201 -0
- package/dist/commands/metadata-cmd.js.map +1 -0
- package/dist/commands/mirror.d.ts +3 -0
- package/dist/commands/mirror.d.ts.map +1 -0
- package/dist/commands/mirror.js +218 -0
- package/dist/commands/mirror.js.map +1 -0
- package/dist/commands/modulate.d.ts +3 -0
- package/dist/commands/modulate.d.ts.map +1 -0
- package/dist/commands/modulate.js +151 -0
- package/dist/commands/modulate.js.map +1 -0
- package/dist/commands/negate.d.ts +3 -0
- package/dist/commands/negate.d.ts.map +1 -0
- package/dist/commands/negate.js +111 -0
- package/dist/commands/negate.js.map +1 -0
- package/dist/commands/normalize.d.ts +3 -0
- package/dist/commands/normalize.d.ts.map +1 -0
- package/dist/commands/normalize.js +119 -0
- package/dist/commands/normalize.js.map +1 -0
- package/dist/commands/optimize.d.ts +3 -0
- package/dist/commands/optimize.d.ts.map +1 -0
- package/dist/commands/optimize.js +137 -0
- package/dist/commands/optimize.js.map +1 -0
- package/dist/commands/palette.d.ts +3 -0
- package/dist/commands/palette.d.ts.map +1 -0
- package/dist/commands/palette.js +138 -0
- package/dist/commands/palette.js.map +1 -0
- package/dist/commands/pixelate.d.ts +3 -0
- package/dist/commands/pixelate.d.ts.map +1 -0
- package/dist/commands/pixelate.js +123 -0
- package/dist/commands/pixelate.js.map +1 -0
- package/dist/commands/resize.d.ts +3 -0
- package/dist/commands/resize.d.ts.map +1 -0
- package/dist/commands/resize.js +187 -0
- package/dist/commands/resize.js.map +1 -0
- package/dist/commands/rotate.d.ts +3 -0
- package/dist/commands/rotate.d.ts.map +1 -0
- package/dist/commands/rotate.js +103 -0
- package/dist/commands/rotate.js.map +1 -0
- package/dist/commands/sepia.d.ts +3 -0
- package/dist/commands/sepia.d.ts.map +1 -0
- package/dist/commands/sepia.js +119 -0
- package/dist/commands/sepia.js.map +1 -0
- package/dist/commands/sharpen.d.ts +3 -0
- package/dist/commands/sharpen.d.ts.map +1 -0
- package/dist/commands/sharpen.js +123 -0
- package/dist/commands/sharpen.js.map +1 -0
- package/dist/commands/smart-crop.d.ts +3 -0
- package/dist/commands/smart-crop.d.ts.map +1 -0
- package/dist/commands/smart-crop.js +137 -0
- package/dist/commands/smart-crop.js.map +1 -0
- package/dist/commands/split.d.ts +3 -0
- package/dist/commands/split.d.ts.map +1 -0
- package/dist/commands/split.js +177 -0
- package/dist/commands/split.js.map +1 -0
- package/dist/commands/stack.d.ts +3 -0
- package/dist/commands/stack.d.ts.map +1 -0
- package/dist/commands/stack.js +205 -0
- package/dist/commands/stack.js.map +1 -0
- package/dist/commands/stats.d.ts +3 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +187 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/thumbnail.d.ts +3 -0
- package/dist/commands/thumbnail.d.ts.map +1 -0
- package/dist/commands/thumbnail.js +131 -0
- package/dist/commands/thumbnail.js.map +1 -0
- package/dist/commands/tint.d.ts +3 -0
- package/dist/commands/tint.d.ts.map +1 -0
- package/dist/commands/tint.js +123 -0
- package/dist/commands/tint.js.map +1 -0
- package/dist/commands/trim.d.ts +3 -0
- package/dist/commands/trim.d.ts.map +1 -0
- package/dist/commands/trim.js +123 -0
- package/dist/commands/trim.js.map +1 -0
- package/dist/commands/vignette.d.ts +3 -0
- package/dist/commands/vignette.d.ts.map +1 -0
- package/dist/commands/vignette.js +139 -0
- package/dist/commands/vignette.js.map +1 -0
- package/dist/commands/watermark.d.ts +3 -0
- package/dist/commands/watermark.d.ts.map +1 -0
- package/dist/commands/watermark.js +172 -0
- package/dist/commands/watermark.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/register.d.ts +5 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +93 -0
- package/dist/register.js.map +1 -0
- package/dist/types.d.ts +91 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/helpFormatter.d.ts +63 -0
- package/dist/utils/helpFormatter.d.ts.map +1 -0
- package/dist/utils/helpFormatter.js +171 -0
- package/dist/utils/helpFormatter.js.map +1 -0
- package/dist/utils/sharp.d.ts +20 -0
- package/dist/utils/sharp.d.ts.map +1 -0
- package/dist/utils/sharp.js +14 -0
- package/dist/utils/sharp.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { createSharpInstance } from '../utils/sharp.js';
|
|
6
|
+
import { createStandardHelp } from '../utils/helpFormatter.js';
|
|
7
|
+
export function thumbnailCommand(imageCmd) {
|
|
8
|
+
imageCmd
|
|
9
|
+
.command('thumbnail <input>')
|
|
10
|
+
.description('Generate thumbnail from image')
|
|
11
|
+
.option('-s, --size <size>', 'Thumbnail size in pixels (default: 150)', parseInt, 150)
|
|
12
|
+
.option('-o, --output <path>', 'Output file path')
|
|
13
|
+
.option('-q, --quality <quality>', 'Quality (1-100)', parseInt, 85)
|
|
14
|
+
.option('--fit <fit>', 'Fit mode: cover, contain, fill, inside, outside', 'cover')
|
|
15
|
+
.option('--dry-run', 'Show what would be done without executing')
|
|
16
|
+
.option('-v, --verbose', 'Verbose output')
|
|
17
|
+
.option('--help', 'Display help for thumbnail command')
|
|
18
|
+
.action(async (input, options) => {
|
|
19
|
+
if (options.help) {
|
|
20
|
+
createStandardHelp({
|
|
21
|
+
commandName: 'thumbnail',
|
|
22
|
+
emoji: '🖼️',
|
|
23
|
+
description: 'Generate thumbnails from images. Perfect for creating preview images, avatar sizes, or gallery thumbnails.',
|
|
24
|
+
usage: ['thumbnail <input>', 'thumbnail <input> -s <size>', 'thumbnail <input> -s 200 --fit contain'],
|
|
25
|
+
options: [
|
|
26
|
+
{ flag: '-s, --size <size>', description: 'Thumbnail size in pixels (default: 150, creates 150x150)' },
|
|
27
|
+
{ flag: '-o, --output <path>', description: 'Output file path (default: <input>-thumb.<ext>)' },
|
|
28
|
+
{ flag: '-q, --quality <quality>', description: 'Output quality 1-100 (default: 85)' },
|
|
29
|
+
{ flag: '--fit <fit>', description: 'Fit mode: cover, contain, fill, inside, outside (default: cover)' },
|
|
30
|
+
{ flag: '--dry-run', description: 'Preview changes without executing' },
|
|
31
|
+
{ flag: '-v, --verbose', description: 'Show detailed output' }
|
|
32
|
+
],
|
|
33
|
+
examples: [
|
|
34
|
+
{ command: 'thumbnail photo.jpg', description: 'Generate 150x150 thumbnail (default)' },
|
|
35
|
+
{ command: 'thumbnail image.png -s 200', description: 'Generate 200x200 thumbnail' },
|
|
36
|
+
{ command: 'thumbnail pic.jpg -s 100 --fit contain', description: '100x100 thumbnail with padding' },
|
|
37
|
+
{ command: 'thumbnail photo.jpg -s 300 -q 90', description: '300x300 high-quality thumbnail' }
|
|
38
|
+
],
|
|
39
|
+
additionalSections: [
|
|
40
|
+
{
|
|
41
|
+
title: 'Common Sizes',
|
|
42
|
+
items: [
|
|
43
|
+
'64x64 - Favicon, small icons',
|
|
44
|
+
'150x150 - Default thumbnail size',
|
|
45
|
+
'200x200 - Medium thumbnails',
|
|
46
|
+
'300x300 - Large thumbnails',
|
|
47
|
+
'512x512 - App icons, large previews'
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
title: 'Fit Modes',
|
|
52
|
+
items: [
|
|
53
|
+
'cover - Fill entire area, crop if needed (default)',
|
|
54
|
+
'contain - Fit inside with padding',
|
|
55
|
+
'fill - Stretch to fill (may distort)',
|
|
56
|
+
'inside - Shrink if larger, no enlargement',
|
|
57
|
+
'outside - Enlarge to cover, crop if needed'
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
tips: [
|
|
62
|
+
'Cover mode works best for profile pictures and avatars',
|
|
63
|
+
'Contain mode preserves full image with padding',
|
|
64
|
+
'Quality 85 is optimal for thumbnails',
|
|
65
|
+
'Use WebP format for smaller file sizes'
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
70
|
+
const spinner = ora('Generating thumbnail...').start();
|
|
71
|
+
try {
|
|
72
|
+
if (!fs.existsSync(input)) {
|
|
73
|
+
spinner.fail(chalk.red(`Input file not found: ${input}`));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
const inputPath = path.parse(input);
|
|
77
|
+
const outputPath = options.output || path.join(process.cwd(), `${inputPath.name}-thumb${inputPath.ext}`);
|
|
78
|
+
const size = options.size || 150;
|
|
79
|
+
if (options.verbose) {
|
|
80
|
+
spinner.info(chalk.blue('Configuration:'));
|
|
81
|
+
console.log(chalk.dim(` Input: ${input}`));
|
|
82
|
+
console.log(chalk.dim(` Output: ${outputPath}`));
|
|
83
|
+
console.log(chalk.dim(` Size: ${size}x${size}`));
|
|
84
|
+
console.log(chalk.dim(` Fit: ${options.fit || 'cover'}`));
|
|
85
|
+
console.log(chalk.dim(` Quality: ${options.quality || 85}`));
|
|
86
|
+
spinner.start('Processing...');
|
|
87
|
+
}
|
|
88
|
+
if (options.dryRun) {
|
|
89
|
+
spinner.info(chalk.yellow('Dry run mode - no changes will be made'));
|
|
90
|
+
console.log(chalk.green('✓ Would generate thumbnail:'));
|
|
91
|
+
console.log(chalk.dim(` From: ${input}`));
|
|
92
|
+
console.log(chalk.dim(` To: ${outputPath}`));
|
|
93
|
+
console.log(chalk.dim(` Size: ${size}x${size}`));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const metadata = await createSharpInstance(input).metadata();
|
|
97
|
+
const pipeline = createSharpInstance(input)
|
|
98
|
+
.resize(size, size, {
|
|
99
|
+
fit: options.fit || 'cover',
|
|
100
|
+
position: 'center'
|
|
101
|
+
});
|
|
102
|
+
const outputExt = path.extname(outputPath).toLowerCase();
|
|
103
|
+
if (outputExt === '.jpg' || outputExt === '.jpeg') {
|
|
104
|
+
pipeline.jpeg({ quality: options.quality || 85 });
|
|
105
|
+
}
|
|
106
|
+
else if (outputExt === '.png') {
|
|
107
|
+
pipeline.png({ quality: options.quality || 85 });
|
|
108
|
+
}
|
|
109
|
+
else if (outputExt === '.webp') {
|
|
110
|
+
pipeline.webp({ quality: options.quality || 85 });
|
|
111
|
+
}
|
|
112
|
+
await pipeline.toFile(outputPath);
|
|
113
|
+
const outputStats = fs.statSync(outputPath);
|
|
114
|
+
spinner.succeed(chalk.green('✓ Thumbnail generated successfully!'));
|
|
115
|
+
console.log(chalk.dim(` Input: ${input} (${metadata.width}x${metadata.height})`));
|
|
116
|
+
console.log(chalk.dim(` Output: ${outputPath} (${size}x${size})`));
|
|
117
|
+
console.log(chalk.dim(` File size: ${(outputStats.size / 1024).toFixed(2)}KB`));
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
spinner.fail(chalk.red('Failed to generate thumbnail'));
|
|
121
|
+
if (options.verbose) {
|
|
122
|
+
console.error(chalk.red('Error details:'), error);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
console.error(chalk.red(error.message));
|
|
126
|
+
}
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=thumbnail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thumbnail.js","sourceRoot":"","sources":["../../src/commands/thumbnail.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tint.d.ts","sourceRoot":"","sources":["../../src/commands/tint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CA0HnD"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { createSharpInstance } from '../utils/sharp.js';
|
|
6
|
+
import { createStandardHelp } from '../utils/helpFormatter.js';
|
|
7
|
+
export function tintCommand(imageCmd) {
|
|
8
|
+
imageCmd
|
|
9
|
+
.command('tint <input>')
|
|
10
|
+
.description('Apply color tint to image')
|
|
11
|
+
.option('-c, --color <color>', 'Tint color (hex, rgb, or name, default: #0000ff)', '#0000ff')
|
|
12
|
+
.option('-o, --output <path>', 'Output file path')
|
|
13
|
+
.option('-q, --quality <quality>', 'Quality (1-100)', parseInt, 90)
|
|
14
|
+
.option('--dry-run', 'Show what would be done without executing')
|
|
15
|
+
.option('-v, --verbose', 'Verbose output')
|
|
16
|
+
.option('--help', 'Display help for tint command')
|
|
17
|
+
.action(async (input, options) => {
|
|
18
|
+
if (options.help) {
|
|
19
|
+
createStandardHelp({
|
|
20
|
+
commandName: 'tint',
|
|
21
|
+
emoji: '🎨',
|
|
22
|
+
description: 'Apply color tint overlay to images. Great for creating artistic effects, mood adjustments, or brand color filters.',
|
|
23
|
+
usage: ['tint <input>', 'tint <input> -c <color>', 'tint <input> -c "#ff6600"'],
|
|
24
|
+
options: [
|
|
25
|
+
{ flag: '-c, --color <color>', description: 'Tint color as hex (#ff0000), rgb (rgb(255,0,0)), or name (red)' },
|
|
26
|
+
{ flag: '-o, --output <path>', description: 'Output file path (default: <input>-tinted.<ext>)' },
|
|
27
|
+
{ flag: '-q, --quality <quality>', description: 'Output quality 1-100 (default: 90)' },
|
|
28
|
+
{ flag: '--dry-run', description: 'Preview changes without executing' },
|
|
29
|
+
{ flag: '-v, --verbose', description: 'Show detailed output' }
|
|
30
|
+
],
|
|
31
|
+
examples: [
|
|
32
|
+
{ command: 'tint photo.jpg -c blue', description: 'Apply blue tint' },
|
|
33
|
+
{ command: 'tint image.png -c "#ff6600"', description: 'Apply orange tint (hex color)' },
|
|
34
|
+
{ command: 'tint pic.jpg -c "rgb(255, 0, 128)"', description: 'Apply pink tint (RGB)' },
|
|
35
|
+
{ command: 'tint photo.jpg -c red', description: 'Apply red tint' }
|
|
36
|
+
],
|
|
37
|
+
additionalSections: [
|
|
38
|
+
{
|
|
39
|
+
title: 'Color Formats',
|
|
40
|
+
items: [
|
|
41
|
+
'Hex: #ff0000 or #f00 (red)',
|
|
42
|
+
'RGB: rgb(255, 0, 0) (red)',
|
|
43
|
+
'Names: red, blue, green, yellow, etc.',
|
|
44
|
+
'Popular: sepia (#704214), cyan (#00ffff)'
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
title: 'Common Tints',
|
|
49
|
+
items: [
|
|
50
|
+
'Sepia: #704214 - Vintage/warm look',
|
|
51
|
+
'Blue: #0066cc - Cool/cold mood',
|
|
52
|
+
'Orange: #ff6600 - Warm/sunset effect',
|
|
53
|
+
'Purple: #9933cc - Creative/artistic',
|
|
54
|
+
'Green: #00cc66 - Nature/fresh feel'
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
tips: [
|
|
59
|
+
'Subtle tints work better than strong colors',
|
|
60
|
+
'Use sepia (#704214) for vintage effects',
|
|
61
|
+
'Blue tints create cool, calm atmospheres',
|
|
62
|
+
'Orange/red tints add warmth to photos'
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}
|
|
67
|
+
const spinner = ora('Processing image...').start();
|
|
68
|
+
try {
|
|
69
|
+
if (!fs.existsSync(input)) {
|
|
70
|
+
spinner.fail(chalk.red(`Input file not found: ${input}`));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
const inputPath = path.parse(input);
|
|
74
|
+
const outputPath = options.output || path.join(process.cwd(), `${inputPath.name}-tinted${inputPath.ext}`);
|
|
75
|
+
if (options.verbose) {
|
|
76
|
+
spinner.info(chalk.blue('Configuration:'));
|
|
77
|
+
console.log(chalk.dim(` Input: ${input}`));
|
|
78
|
+
console.log(chalk.dim(` Output: ${outputPath}`));
|
|
79
|
+
console.log(chalk.dim(` Color: ${options.color || '#0000ff'}`));
|
|
80
|
+
spinner.start('Processing...');
|
|
81
|
+
}
|
|
82
|
+
if (options.dryRun) {
|
|
83
|
+
spinner.info(chalk.yellow('Dry run mode - no changes will be made'));
|
|
84
|
+
console.log(chalk.green('✓ Would apply tint:'));
|
|
85
|
+
console.log(chalk.dim(` From: ${input}`));
|
|
86
|
+
console.log(chalk.dim(` To: ${outputPath}`));
|
|
87
|
+
console.log(chalk.dim(` Color: ${options.color || '#0000ff'}`));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const metadata = await createSharpInstance(input).metadata();
|
|
91
|
+
const pipeline = createSharpInstance(input).tint(options.color || '#0000ff');
|
|
92
|
+
const outputExt = path.extname(outputPath).toLowerCase();
|
|
93
|
+
if (outputExt === '.jpg' || outputExt === '.jpeg') {
|
|
94
|
+
pipeline.jpeg({ quality: options.quality || 90 });
|
|
95
|
+
}
|
|
96
|
+
else if (outputExt === '.png') {
|
|
97
|
+
pipeline.png({ quality: options.quality || 90 });
|
|
98
|
+
}
|
|
99
|
+
else if (outputExt === '.webp') {
|
|
100
|
+
pipeline.webp({ quality: options.quality || 90 });
|
|
101
|
+
}
|
|
102
|
+
await pipeline.toFile(outputPath);
|
|
103
|
+
const outputStats = fs.statSync(outputPath);
|
|
104
|
+
spinner.succeed(chalk.green('✓ Tint applied successfully!'));
|
|
105
|
+
console.log(chalk.dim(` Input: ${input}`));
|
|
106
|
+
console.log(chalk.dim(` Output: ${outputPath}`));
|
|
107
|
+
console.log(chalk.dim(` Size: ${metadata.width}x${metadata.height}`));
|
|
108
|
+
console.log(chalk.dim(` Color: ${options.color || '#0000ff'}`));
|
|
109
|
+
console.log(chalk.dim(` File size: ${(outputStats.size / 1024).toFixed(2)}KB`));
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
spinner.fail(chalk.red('Failed to apply tint'));
|
|
113
|
+
if (options.verbose) {
|
|
114
|
+
console.error(chalk.red('Error details:'), error);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.error(chalk.red(error.message));
|
|
118
|
+
}
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=tint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tint.js","sourceRoot":"","sources":["../../src/commands/tint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trim.d.ts","sourceRoot":"","sources":["../../src/commands/trim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CA0HnD"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { createSharpInstance } from '../utils/sharp.js';
|
|
6
|
+
import { createStandardHelp } from '../utils/helpFormatter.js';
|
|
7
|
+
export function trimCommand(imageCmd) {
|
|
8
|
+
imageCmd
|
|
9
|
+
.command('trim <input>')
|
|
10
|
+
.description('Trim/remove border edges from image')
|
|
11
|
+
.option('-t, --threshold <value>', 'Threshold for edge detection (1-100, default: 10)', parseInt, 10)
|
|
12
|
+
.option('-o, --output <path>', 'Output file path')
|
|
13
|
+
.option('-q, --quality <quality>', 'Quality (1-100)', parseInt, 90)
|
|
14
|
+
.option('--dry-run', 'Show what would be done without executing')
|
|
15
|
+
.option('-v, --verbose', 'Verbose output')
|
|
16
|
+
.option('--help', 'Display help for trim command')
|
|
17
|
+
.action(async (input, options) => {
|
|
18
|
+
if (options.help) {
|
|
19
|
+
createStandardHelp({
|
|
20
|
+
commandName: 'trim',
|
|
21
|
+
emoji: '✂️',
|
|
22
|
+
description: 'Automatically trim/remove boring border edges from images. Perfect for removing whitespace, borders, or uniform backgrounds.',
|
|
23
|
+
usage: ['trim <input>', 'trim <input> -t <threshold>', 'trim <input> -t 20'],
|
|
24
|
+
options: [
|
|
25
|
+
{ flag: '-t, --threshold <value>', description: 'Edge detection threshold 1-100 (default: 10, higher = more aggressive)' },
|
|
26
|
+
{ flag: '-o, --output <path>', description: 'Output file path (default: <input>-trimmed.<ext>)' },
|
|
27
|
+
{ flag: '-q, --quality <quality>', description: 'Output quality 1-100 (default: 90)' },
|
|
28
|
+
{ flag: '--dry-run', description: 'Preview changes without executing' },
|
|
29
|
+
{ flag: '-v, --verbose', description: 'Show detailed output' }
|
|
30
|
+
],
|
|
31
|
+
examples: [
|
|
32
|
+
{ command: 'trim photo.jpg', description: 'Auto-trim with default threshold (10)' },
|
|
33
|
+
{ command: 'trim image.png -t 5', description: 'Gentle trim (sensitive)' },
|
|
34
|
+
{ command: 'trim pic.jpg -t 20', description: 'Aggressive trim' },
|
|
35
|
+
{ command: 'trim screenshot.png', description: 'Remove screenshot borders' }
|
|
36
|
+
],
|
|
37
|
+
additionalSections: [
|
|
38
|
+
{
|
|
39
|
+
title: 'Threshold Guide',
|
|
40
|
+
items: [
|
|
41
|
+
'1-5 - Very sensitive (removes slight differences)',
|
|
42
|
+
'10 - Default (balanced)',
|
|
43
|
+
'15-25 - Aggressive (removes more)',
|
|
44
|
+
'25+ - Very aggressive (may over-trim)'
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
title: 'Best For',
|
|
49
|
+
items: [
|
|
50
|
+
'Scanned documents with borders',
|
|
51
|
+
'Screenshots with padding',
|
|
52
|
+
'Images with solid color borders',
|
|
53
|
+
'Product photos on white backgrounds',
|
|
54
|
+
'Auto-cropping uniform edges'
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
tips: [
|
|
59
|
+
'Start with default threshold (10)',
|
|
60
|
+
'Lower threshold for subtle edges',
|
|
61
|
+
'Higher threshold for obvious borders',
|
|
62
|
+
'Perfect for batch processing scans'
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}
|
|
67
|
+
const spinner = ora('Processing image...').start();
|
|
68
|
+
try {
|
|
69
|
+
if (!fs.existsSync(input)) {
|
|
70
|
+
spinner.fail(chalk.red(`Input file not found: ${input}`));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
const inputPath = path.parse(input);
|
|
74
|
+
const outputPath = options.output || path.join(process.cwd(), `${inputPath.name}-trimmed${inputPath.ext}`);
|
|
75
|
+
if (options.verbose) {
|
|
76
|
+
spinner.info(chalk.blue('Configuration:'));
|
|
77
|
+
console.log(chalk.dim(` Input: ${input}`));
|
|
78
|
+
console.log(chalk.dim(` Output: ${outputPath}`));
|
|
79
|
+
console.log(chalk.dim(` Threshold: ${options.threshold || 10}`));
|
|
80
|
+
spinner.start('Processing...');
|
|
81
|
+
}
|
|
82
|
+
if (options.dryRun) {
|
|
83
|
+
spinner.info(chalk.yellow('Dry run mode - no changes will be made'));
|
|
84
|
+
console.log(chalk.green('✓ Would trim image:'));
|
|
85
|
+
console.log(chalk.dim(` From: ${input}`));
|
|
86
|
+
console.log(chalk.dim(` To: ${outputPath}`));
|
|
87
|
+
console.log(chalk.dim(` Threshold: ${options.threshold || 10}`));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const originalMetadata = await createSharpInstance(input).metadata();
|
|
91
|
+
const pipeline = createSharpInstance(input).trim({ threshold: options.threshold || 10 });
|
|
92
|
+
const outputExt = path.extname(outputPath).toLowerCase();
|
|
93
|
+
if (outputExt === '.jpg' || outputExt === '.jpeg') {
|
|
94
|
+
pipeline.jpeg({ quality: options.quality || 90 });
|
|
95
|
+
}
|
|
96
|
+
else if (outputExt === '.png') {
|
|
97
|
+
pipeline.png({ quality: options.quality || 90 });
|
|
98
|
+
}
|
|
99
|
+
else if (outputExt === '.webp') {
|
|
100
|
+
pipeline.webp({ quality: options.quality || 90 });
|
|
101
|
+
}
|
|
102
|
+
await pipeline.toFile(outputPath);
|
|
103
|
+
const outputMetadata = await createSharpInstance(outputPath).metadata();
|
|
104
|
+
const outputStats = fs.statSync(outputPath);
|
|
105
|
+
spinner.succeed(chalk.green('✓ Image trimmed successfully!'));
|
|
106
|
+
console.log(chalk.dim(` Input: ${input} (${originalMetadata.width}x${originalMetadata.height})`));
|
|
107
|
+
console.log(chalk.dim(` Output: ${outputPath} (${outputMetadata.width}x${outputMetadata.height})`));
|
|
108
|
+
console.log(chalk.dim(` Threshold: ${options.threshold || 10}`));
|
|
109
|
+
console.log(chalk.dim(` File size: ${(outputStats.size / 1024).toFixed(2)}KB`));
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
spinner.fail(chalk.red('Failed to trim image'));
|
|
113
|
+
if (options.verbose) {
|
|
114
|
+
console.error(chalk.red('Error details:'), error);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.error(chalk.red(error.message));
|
|
118
|
+
}
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=trim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trim.js","sourceRoot":"","sources":["../../src/commands/trim.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vignette.d.ts","sourceRoot":"","sources":["../../src/commands/vignette.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBzC,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CA+IvD"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { createSharpInstance } from '../utils/sharp.js';
|
|
6
|
+
import { createStandardHelp } from '../utils/helpFormatter.js';
|
|
7
|
+
export function vignetteCommand(imageCmd) {
|
|
8
|
+
imageCmd
|
|
9
|
+
.command('vignette <input>')
|
|
10
|
+
.description('Add vignette effect (darkened edges)')
|
|
11
|
+
.option('-s, --strength <value>', 'Vignette strength 0-100 (default: 50)', parseFloat, 50)
|
|
12
|
+
.option('-o, --output <path>', 'Output file path')
|
|
13
|
+
.option('--dry-run', 'Show what would be done without executing')
|
|
14
|
+
.option('-v, --verbose', 'Verbose output')
|
|
15
|
+
.option('--help', 'Display help for vignette command')
|
|
16
|
+
.action(async (input, options) => {
|
|
17
|
+
if (options.help) {
|
|
18
|
+
createStandardHelp({
|
|
19
|
+
commandName: 'vignette',
|
|
20
|
+
emoji: '🌓',
|
|
21
|
+
description: 'Add vignette effect by darkening or lightening the edges of an image. Creates focus on the center and adds artistic mood.',
|
|
22
|
+
usage: ['vignette <input>', 'vignette <input> -s 70', 'vignette <input> -o artistic.jpg'],
|
|
23
|
+
options: [
|
|
24
|
+
{ flag: '-s, --strength <value>', description: 'Vignette strength 0-100 (default: 50)' },
|
|
25
|
+
{ flag: '-o, --output <path>', description: 'Output file path' },
|
|
26
|
+
{ flag: '--dry-run', description: 'Preview changes without executing' },
|
|
27
|
+
{ flag: '-v, --verbose', description: 'Show detailed output' }
|
|
28
|
+
],
|
|
29
|
+
examples: [
|
|
30
|
+
{ command: 'vignette photo.jpg', description: 'Apply default vignette' },
|
|
31
|
+
{ command: 'vignette portrait.png -s 80', description: 'Strong vignette effect' },
|
|
32
|
+
{ command: 'vignette landscape.jpg -s 30', description: 'Subtle edge darkening' },
|
|
33
|
+
{ command: 'vignette image.jpg -o artistic.jpg', description: 'Save with vignette' }
|
|
34
|
+
],
|
|
35
|
+
additionalSections: [
|
|
36
|
+
{
|
|
37
|
+
title: 'Strength Guide',
|
|
38
|
+
items: [
|
|
39
|
+
'0-20 - Very subtle, barely noticeable',
|
|
40
|
+
'30-50 - Moderate, natural look (recommended)',
|
|
41
|
+
'60-80 - Strong, dramatic effect',
|
|
42
|
+
'90-100 - Very intense, artistic'
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
title: 'Use Cases',
|
|
47
|
+
items: [
|
|
48
|
+
'Portrait photography - focus on subject',
|
|
49
|
+
'Vintage/retro effects',
|
|
50
|
+
'Artistic mood creation',
|
|
51
|
+
'Direct viewer attention to center',
|
|
52
|
+
'Wedding and event photography',
|
|
53
|
+
'Social media posts'
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
tips: [
|
|
58
|
+
'Start with 50 and adjust to taste',
|
|
59
|
+
'Works great with portraits',
|
|
60
|
+
'Combine with sepia for vintage look',
|
|
61
|
+
'Lower strength for natural results'
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
const spinner = ora('Adding vignette...').start();
|
|
67
|
+
try {
|
|
68
|
+
if (!fs.existsSync(input)) {
|
|
69
|
+
spinner.fail(chalk.red(`Input file not found: ${input}`));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
const strength = Math.max(0, Math.min(100, options.strength || 50)) / 100;
|
|
73
|
+
const inputPath = path.parse(input);
|
|
74
|
+
const outputPath = options.output || path.join(inputPath.dir, `${inputPath.name}-vignette${inputPath.ext}`);
|
|
75
|
+
if (options.verbose) {
|
|
76
|
+
spinner.info(chalk.blue('Configuration:'));
|
|
77
|
+
console.log(chalk.dim(` Input: ${input}`));
|
|
78
|
+
console.log(chalk.dim(` Output: ${outputPath}`));
|
|
79
|
+
console.log(chalk.dim(` Strength: ${(strength * 100).toFixed(0)}%`));
|
|
80
|
+
spinner.start('Processing...');
|
|
81
|
+
}
|
|
82
|
+
if (options.dryRun) {
|
|
83
|
+
spinner.info(chalk.yellow('Dry run mode - no changes will be made'));
|
|
84
|
+
console.log(chalk.green('✓ Would add vignette:'));
|
|
85
|
+
console.log(chalk.dim(` Input: ${input}`));
|
|
86
|
+
console.log(chalk.dim(` Strength: ${(strength * 100).toFixed(0)}%`));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const metadata = await createSharpInstance(input).metadata();
|
|
90
|
+
const width = metadata.width;
|
|
91
|
+
const height = metadata.height;
|
|
92
|
+
// Create radial gradient for vignette
|
|
93
|
+
const centerX = width / 2;
|
|
94
|
+
const centerY = height / 2;
|
|
95
|
+
const maxRadius = Math.sqrt(centerX * centerX + centerY * centerY);
|
|
96
|
+
if (options.verbose) {
|
|
97
|
+
console.log(chalk.dim(` Center: (${centerX}, ${centerY})`));
|
|
98
|
+
console.log(chalk.dim(` Max radius: ${maxRadius.toFixed(2)}px`));
|
|
99
|
+
console.log(chalk.dim(` Strength: ${strength}`));
|
|
100
|
+
}
|
|
101
|
+
// Create vignette overlay using SVG
|
|
102
|
+
const vignetteOverlay = Buffer.from(`
|
|
103
|
+
<svg width="${width}" height="${height}">
|
|
104
|
+
<defs>
|
|
105
|
+
<radialGradient id="vignette" cx="50%" cy="50%" r="70%">
|
|
106
|
+
<stop offset="40%" style="stop-color:white;stop-opacity:0" />
|
|
107
|
+
<stop offset="100%" style="stop-color:black;stop-opacity:${strength}" />
|
|
108
|
+
</radialGradient>
|
|
109
|
+
</defs>
|
|
110
|
+
<rect width="${width}" height="${height}" fill="url(#vignette)" />
|
|
111
|
+
</svg>
|
|
112
|
+
`);
|
|
113
|
+
await createSharpInstance(input)
|
|
114
|
+
.composite([{
|
|
115
|
+
input: vignetteOverlay,
|
|
116
|
+
blend: 'multiply'
|
|
117
|
+
}])
|
|
118
|
+
.toFile(outputPath);
|
|
119
|
+
const outputStats = fs.statSync(outputPath);
|
|
120
|
+
spinner.succeed(chalk.green('✓ Vignette added successfully!'));
|
|
121
|
+
console.log(chalk.dim(` Input: ${input}`));
|
|
122
|
+
console.log(chalk.dim(` Output: ${outputPath}`));
|
|
123
|
+
console.log(chalk.dim(` Size: ${width}x${height}`));
|
|
124
|
+
console.log(chalk.dim(` Strength: ${(strength * 100).toFixed(0)}%`));
|
|
125
|
+
console.log(chalk.dim(` File size: ${(outputStats.size / 1024).toFixed(2)}KB`));
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
spinner.fail(chalk.red('Failed to add vignette'));
|
|
129
|
+
if (options.verbose) {
|
|
130
|
+
console.error(chalk.red('Error details:'), error);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
console.error(chalk.red(error.message));
|
|
134
|
+
}
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=vignette.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vignette.js","sourceRoot":"","sources":["../../src/commands/vignette.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watermark.d.ts","sourceRoot":"","sources":["../../src/commands/watermark.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CA8KxD"}
|