Shell-Scripts/photo-toolkit/format.js

150 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const {
question,
getImageDimensions,
detectImageType,
getTargetSize,
getOutputExtension,
IMAGE_TYPES,
IMAGE_TYPE_LABELS,
} = require('./utils');
// 处理单个图片
function processImage(inputPath, outputPath) {
const filename = path.basename(inputPath);
const dimensions = getImageDimensions(inputPath);
const { type, reason } = detectImageType(inputPath, dimensions);
const outputExt = getOutputExtension(type);
const newFilename = path.basename(outputPath, path.extname(outputPath)) + outputExt;
const finalOutputPath = path.join(path.dirname(outputPath), newFilename);
if (fs.existsSync(finalOutputPath)) {
console.log(`⏭️ 跳过已存在的文件: ${newFilename}`);
return false;
}
console.log(`\n📸 处理: ${filename}`);
console.log(` 类型: ${IMAGE_TYPE_LABELS[type]} (${reason})`);
console.log(` 尺寸: ${dimensions.width}x${dimensions.height}`);
try {
if (type === IMAGE_TYPES.SCREENSHOT) {
execSync(
`magick "${inputPath}" -gravity center -quality 80 "${finalOutputPath}"`,
{ stdio: 'inherit' }
);
} else {
const newSize = getTargetSize(type, dimensions.width, dimensions.height);
console.log(` 目标尺寸: ${newSize}`);
execSync(
`magick "${inputPath}" -gravity center -resize "${newSize}^" -extent "${newSize}" -quality 80 "${finalOutputPath}"`,
{ stdio: 'inherit' }
);
}
console.log(` ✅ 图片转换完成 → ${outputExt}`);
} catch (error) {
console.error(` ❌ 图片转换失败`);
throw error;
}
try {
execSync(
`exiftool -overwrite_original -gps:all= -artist="奇趣保罗" -CreatorTool= "${finalOutputPath}"`,
{ stdio: 'inherit' }
);
console.log(` ✅ 元数据处理完成`);
} catch (error) {
console.error(` ❌ 元数据处理失败`);
throw error;
}
return true;
}
// 格式转换主函数
async function runFormatTool(rl) {
console.log('\n🎨 图片格式转换工具');
console.log('='.repeat(50));
console.log('支持类型: iPhone (4:3 JPG) · 索尼相机 (3:2 JPG) · 截图 (WebP)');
const inputDir = await question(rl, '\n📁 请输入图片所在目录 (留空使用当前目录): ');
const sourceDir = inputDir.trim() || process.cwd();
if (!fs.existsSync(sourceDir)) {
console.error(`❌ 目录不存在: ${sourceDir}`);
return;
}
const outputDir = await question(rl, '📁 请输入输出目录 (留空使用 output): ');
const targetDir = outputDir.trim() || path.join(sourceDir, 'output');
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true });
console.log(`✅ 已创建输出目录: ${targetDir}`);
}
const extensions = ['.heic', '.heif', '.png', '.jpg', '.jpeg', '.HEIC', '.HEIF', '.PNG', '.JPG', '.JPEG'];
const files = fs.readdirSync(sourceDir).filter(file => {
const ext = path.extname(file);
const fullPath = path.join(sourceDir, file);
const isFile = fs.statSync(fullPath).isFile();
const hasValidExt = extensions.includes(ext);
const notModified = !file.includes('MODIFIED') && !file.includes('MERGED');
return isFile && hasValidExt && notModified;
});
if (files.length === 0) {
console.log('\n⚠ 未找到符合条件的图片文件');
return;
}
console.log(`\n📋 找到 ${files.length} 个文件:`);
files.forEach((file, index) => {
const inputPath = path.join(sourceDir, file);
const dimensions = getImageDimensions(inputPath);
const { type, reason } = detectImageType(inputPath, dimensions);
console.log(` ${index + 1}. ${file}${IMAGE_TYPE_LABELS[type]} (${reason})`);
});
const confirm = await question(rl, '\n❓ 是否开始处理? (y/n): ');
if (confirm.toLowerCase() !== 'y' && confirm.toLowerCase() !== 'yes') {
console.log('❌ 已取消');
return;
}
console.log('\n🚀 开始处理...\n');
let processed = 0;
let skipped = 0;
let failed = 0;
for (let i = 0; i < files.length; i++) {
const file = files[i];
const inputPath = path.join(sourceDir, file);
const outputPath = path.join(targetDir, file);
console.log(`\n[${i + 1}/${files.length}]`);
try {
const result = processImage(inputPath, outputPath);
if (result) {
processed++;
} else {
skipped++;
}
} catch (error) {
console.error(`❌ 处理失败: ${file}`);
failed++;
}
}
console.log('\n' + '='.repeat(50));
console.log('📊 处理完成!');
console.log(` ✅ 成功: ${processed}`);
console.log(` ⏭️ 跳过: ${skipped}`);
console.log(` ❌ 失败: ${failed}`);
console.log(` 📁 输出目录: ${targetDir}`);
}
module.exports = { runFormatTool };