Merge branch 'release/1.0' into main
commit
502b671347
|
@ -0,0 +1,3 @@
|
|||
/node_modules
|
||||
*.lock
|
||||
*.md.backup
|
113
README.md
113
README.md
|
@ -22,24 +22,15 @@ npm i --save rawtherapee
|
|||
yarn add rawtherapee
|
||||
```
|
||||
|
||||
## Simple Usage
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const rawtherapee = require("rawtherapee");
|
||||
_Promise_ = rawtherapee(_url_ | _array_ `targets` [, _object_ `options`])
|
||||
|
||||
rawtherapee("/somewhere/something.NEF").then((files) => {
|
||||
// `files` is an array containing all processed file paths.
|
||||
console.log(files.length, "files processed.");
|
||||
});
|
||||
```
|
||||
* `targets`: files or directories
|
||||
* `options`: simple options _Object_
|
||||
|
||||
### Options
|
||||
|
||||
| option | format | values | default |
|
||||
|!===|===|===|===|
|
||||
| replace | _boolean_ | | |
|
||||
|
||||
|
||||
#### `replace`
|
||||
|
||||
*default: `false`*
|
||||
|
@ -51,12 +42,23 @@ Replace the existing output file.
|
|||
|
||||
*default: `false`*
|
||||
|
||||
Process all raw and non raw formats, igroring GUI parameters.
|
||||
|
||||
|
||||
#### `presets`
|
||||
|
||||
*default: `['default']`*
|
||||
|
||||
'sidecar', 'sidecar-strict', '<uri>'
|
||||
An array of pp3 presets files.
|
||||
|
||||
Possible opions:
|
||||
|
||||
* `'default'`: use the default preset selected in GUI.
|
||||
* `'sidecar'`: use the sidecar file of each image if available
|
||||
* `'sidecar-strict'`: like `'sidecar`, but return an error if there is no sidecar.
|
||||
* `<uri>`: any pp3 file in your system
|
||||
|
||||
`rawtherapee-cli` always use the neutral presets as base, then apply presets in the order you passed it.
|
||||
|
||||
|
||||
#### `ignoreBadPreset`
|
||||
|
@ -66,16 +68,20 @@ Replace the existing output file.
|
|||
If set to `false`, any non-existing preset file passed to the `presets` parameter will throw an error.
|
||||
If set to `true`, those files will be ignored (not passed to `rawtherapi-cli`) and print message in `sterr` if the `DEBUG` environment variable is set to any value.
|
||||
|
||||
|
||||
#### `output`
|
||||
|
||||
*default: `'/tmp/img'`*
|
||||
*default: `'.'`*
|
||||
|
||||
File or directory where the processed files will be stored (directory must exists).
|
||||
|
||||
|
||||
#### `format`
|
||||
|
||||
*default: `'jpg'`*
|
||||
|
||||
Possibles options:
|
||||
|
||||
`'jpg'`, `'png'` or `'tiff'`
|
||||
|
||||
|
||||
|
@ -83,13 +89,16 @@ If set to `true`, those files will be ignored (not passed to `rawtherapi-cli`) a
|
|||
|
||||
*default: `8`*
|
||||
|
||||
`16`, `16f` or `32`
|
||||
Only for TIFF and PNG output formats.
|
||||
Color depth of the output file. Only for TIFF and PNG formats.
|
||||
|
||||
Possibles options:
|
||||
|
||||
`8` or `16`
|
||||
|
||||
|
||||
#### `compression`
|
||||
|
||||
*default: `92`*
|
||||
*default: `90`*
|
||||
|
||||
Only for JPG output formats (PNG compression is hardcoded at 6 in `rawtherapi-cli`)
|
||||
|
||||
|
@ -98,9 +107,13 @@ Only for JPG output formats (PNG compression is hardcoded at 6 in `rawtherapi-cl
|
|||
|
||||
_string_ or _int_
|
||||
|
||||
*default:`'4:2:2'`*
|
||||
*default:`2`*
|
||||
|
||||
`1`, `'4:2:0'`, `2`, `'4:4:4'`, `3`
|
||||
Possibles options:
|
||||
|
||||
* `'4:2:2'` or `1`
|
||||
* `'4:2:0'` or `2`
|
||||
* `'4:4:4'` or `3`
|
||||
|
||||
|
||||
#### `zip`
|
||||
|
@ -109,7 +122,7 @@ _boolean_
|
|||
|
||||
*default: `false`*
|
||||
|
||||
Only for TIFF output format.
|
||||
Use TIFF zip compression.
|
||||
|
||||
|
||||
#### `onChange`
|
||||
|
@ -117,8 +130,62 @@ Only for TIFF output format.
|
|||
_function_
|
||||
*default: `() => {}`*
|
||||
|
||||
Callback _function_ fired every time the status is updated (not based on `EventListener`) :
|
||||
Callback _function_ fired every time the status is updated (not using `EventListeners`) :
|
||||
|
||||
Return a simple object who always contains `status` entry, and maybe `file` or `code`.
|
||||
Return a simple object who always contains `status`, and maybe `file` or `code`.
|
||||
|
||||
Status can be :
|
||||
|
||||
* `start`: start running `rawtherapee-cli`.
|
||||
* `skipped`: skip ignored `file` in a full directory process.
|
||||
* `processing`: start processing `file`.
|
||||
* `complete`: processing `file` completed.
|
||||
* `idle`: `rawtherapee-cli` stop with `code` code.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```js
|
||||
const rawtherapee = require('rawtherapee')
|
||||
|
||||
rawtherapee('/somewhere/something.NEF')
|
||||
.then((files) => {
|
||||
console.log(files.length, 'files processed.')
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
```js
|
||||
const fs = require('fs')
|
||||
const rawtherapee = require('rawtherapee')
|
||||
|
||||
const output = '/tmp/img'
|
||||
|
||||
if (!fs.existsSync(output)) fs.mkdirSync(output)
|
||||
|
||||
const onChange = (state) => {
|
||||
switch (state.status) {
|
||||
case 'complete':
|
||||
console.log(state.file, 'process done.')
|
||||
break
|
||||
case 'skipped':
|
||||
console.log(state.file, 'have been ignored.')
|
||||
break
|
||||
default:
|
||||
console.log('Event', state.status, 'fired.', state)
|
||||
}
|
||||
}
|
||||
|
||||
rawtherapee([
|
||||
'/somewhere/something.NEF',
|
||||
'/somewhereelse/somethingelse.NEF'
|
||||
], {
|
||||
onChange,
|
||||
output,
|
||||
format: 'tiff',
|
||||
depth: 16,
|
||||
zip: true,
|
||||
preset: ['sidecar']
|
||||
})
|
||||
.then((files) => console.log(files.length, 'files processed.'))
|
||||
```
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "rawtherapee",
|
||||
"version": "1.0.0",
|
||||
"description": "rawtherapee-cli wrapper to process RAW images in NodeJs",
|
||||
"repository": "https://github.com/clovfr/node-rawtherapee",
|
||||
"author": "Clovis Gauzy",
|
||||
"license": "BSD-3",
|
||||
"main": "rawtherapee.js",
|
||||
"scripts": {
|
||||
"test": "standard"
|
||||
},
|
||||
"devDependencies": {
|
||||
"standard": "*"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
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
|
Loading…
Reference in New Issue