176 lines
4.2 KiB
JavaScript
176 lines
4.2 KiB
JavaScript
|
const fs = require('fs')
|
||
|
const { spawn } = require('child_process')
|
||
|
|
||
|
const defaultOptions = {
|
||
|
replace: false,
|
||
|
allFormats: false,
|
||
|
presets: ['default'],
|
||
|
ignoreBadPreset: false,
|
||
|
output: '.',
|
||
|
format: 'jpg',
|
||
|
depth: 8,
|
||
|
compression: 90,
|
||
|
subSampling: 2,
|
||
|
zip: false,
|
||
|
onChange: () => {}
|
||
|
}
|
||
|
|
||
|
const o2cli = (options) => {
|
||
|
const params = ['-q']
|
||
|
const {
|
||
|
replace,
|
||
|
allFormats,
|
||
|
presets,
|
||
|
ignoreBadPreset,
|
||
|
output,
|
||
|
format,
|
||
|
compression,
|
||
|
subSampling,
|
||
|
zip,
|
||
|
depth
|
||
|
} = options
|
||
|
if (replace) params.push('-Y')
|
||
|
if (allFormats) params.push('-a')
|
||
|
if (presets || presets.length) {
|
||
|
presets.forEach((preset) => {
|
||
|
switch (preset) {
|
||
|
case 'default':
|
||
|
return params.push('-d')
|
||
|
case 'sidecar':
|
||
|
return params.push('-s')
|
||
|
case 'sidecar-strict':
|
||
|
return params.push('-S')
|
||
|
default:
|
||
|
if (!fs.existsSync(preset)) {
|
||
|
const err = new Error(`Preset '${preset}' not found.`)
|
||
|
if (!ignoreBadPreset) throw err
|
||
|
else if (process.env.DEBUG) console.error(err)
|
||
|
} else {
|
||
|
params.push('-p')
|
||
|
params.push(preset)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
if (format) {
|
||
|
switch (format.toLowerCase()) {
|
||
|
case 'jpg':
|
||
|
case 'jpeg':
|
||
|
params.push(`-j${compression || ''}`)
|
||
|
if (subSampling) {
|
||
|
switch (subSampling) {
|
||
|
case '4:2:0':
|
||
|
case 1:
|
||
|
params.push('-js1')
|
||
|
break
|
||
|
case '4:2:2':
|
||
|
case 2:
|
||
|
params.push('-js2')
|
||
|
break
|
||
|
case '4:4:4':
|
||
|
case 3:
|
||
|
params.push('-js3')
|
||
|
break
|
||
|
default:
|
||
|
console.warn(
|
||
|
`Warning: subSampling '${subSampling}' is unknown. Option is ignored, 'rawtherapee-cli' will use his own default (4:2:2).`
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
break
|
||
|
case 'png':
|
||
|
params.push('-n')
|
||
|
break
|
||
|
case 'tif':
|
||
|
case 'tiff':
|
||
|
params.push(`-t${zip && 'z'}`)
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if (depth) params.push(`-b${depth}`)
|
||
|
if (output) {
|
||
|
params.push('-o')
|
||
|
params.push(output)
|
||
|
}
|
||
|
return params
|
||
|
}
|
||
|
|
||
|
const rawtherapee = (file, options = {}) => {
|
||
|
options = { ...defaultOptions, ...options }
|
||
|
const { onChange } = options
|
||
|
return new Promise((resolve, reject) => {
|
||
|
let ckf = file
|
||
|
let filename
|
||
|
if (!Array.isArray(file)) ckf = [file]
|
||
|
if ((filename = ckf.find((fl) => !fs.existsSync(fl)))) {
|
||
|
return reject(new Error(`File ${filename} not found`))
|
||
|
}
|
||
|
const params = o2cli(options)
|
||
|
params.push('-c')
|
||
|
params.push(file)
|
||
|
const rwtp = spawn('rawtherapee-cli', params)
|
||
|
|
||
|
const files = []
|
||
|
|
||
|
rwtp.stdout.on('data', (buf) => {
|
||
|
const data = buf.toString('utf8')
|
||
|
let ipath = /Processing: (.+)$/im.exec(data)
|
||
|
if (ipath) {
|
||
|
if (files.length) {
|
||
|
onChange({
|
||
|
status: 'complete',
|
||
|
file: files[files.length - 1]
|
||
|
})
|
||
|
}
|
||
|
files.push(ipath[1])
|
||
|
onChange({
|
||
|
status: 'processing',
|
||
|
file: ipath[1]
|
||
|
})
|
||
|
}
|
||
|
if (!ipath) {
|
||
|
ipath = /^RawTherapee, version ([0-9.]+), command line./im.exec(data)
|
||
|
if (ipath) {
|
||
|
onChange({
|
||
|
status: 'start',
|
||
|
version: ipath[1]
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
if (!ipath) {
|
||
|
ipath = /^"(.+)".*image skipped/im.exec(data)
|
||
|
if (ipath) {
|
||
|
onChange({
|
||
|
status: 'skipped',
|
||
|
file: ipath[1]
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
if (!ipath && process.env.DEBUG) console.warn('not handled', data)
|
||
|
})
|
||
|
|
||
|
rwtp.stderr.on('data', (data) => {
|
||
|
console.error(`stderr: ${data}`)
|
||
|
reject(new Error(data))
|
||
|
})
|
||
|
rwtp.on('error', (data) => {
|
||
|
console.error(`error: ${data}`)
|
||
|
reject(new Error(data))
|
||
|
})
|
||
|
|
||
|
rwtp.on('close', (code) => {
|
||
|
if (code > 0) return reject(new Error(`rawtherapee-cli process exited with code ${code}`))
|
||
|
if (files.length) {
|
||
|
onChange({
|
||
|
status: 'complete',
|
||
|
file: files[files.length - 1]
|
||
|
})
|
||
|
}
|
||
|
onChange({ status: 'idle', code })
|
||
|
resolve(files)
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
|
||
|
module.exports = rawtherapee
|