mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 18:30:09 +00:00
added image resizing to export, still needs UI and details...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
43f0499843
commit
a34591065a
@ -2082,8 +2082,10 @@ var FileSystemWriterActions = actions.Actions({
|
|||||||
// XXX handle .image.path and other stack files...
|
// XXX handle .image.path and other stack files...
|
||||||
// XXX local collections???
|
// XXX local collections???
|
||||||
//
|
//
|
||||||
// XXX BUG: seems to ignore max_size...
|
// XXX BUG: max_size is measured by preview size and ignores main
|
||||||
// ...'preview-size' does not affect the base image size...
|
// image size...
|
||||||
|
// ...this results in exported images being previews ONLY IF
|
||||||
|
// they have previews larger than max_size...
|
||||||
// XXX BUG: this does not remove previews correctly...
|
// XXX BUG: this does not remove previews correctly...
|
||||||
// to reproduce:
|
// to reproduce:
|
||||||
// open: L:\media\img\my\2019
|
// open: L:\media\img\my\2019
|
||||||
@ -2123,10 +2125,14 @@ var FileSystemWriterActions = actions.Actions({
|
|||||||
path = path || './exported'
|
path = path || './exported'
|
||||||
path = util.normalizePath(path)
|
path = util.normalizePath(path)
|
||||||
|
|
||||||
max_size = parseInt(max_size || settings['preview-size-limit']) || null
|
max_size = parseInt(max_size
|
||||||
|
|| settings['preview-size-limit'])
|
||||||
|
|| null
|
||||||
// XXX make this dependant on max_size....
|
// XXX make this dependant on max_size....
|
||||||
include_orig = include_orig || true
|
include_orig = include_orig || true
|
||||||
|
|
||||||
|
var resize = max_size && this.makeResizedImage
|
||||||
|
|
||||||
// clear/backup target...
|
// clear/backup target...
|
||||||
clean_target_dir = clean_target_dir === undefined ?
|
clean_target_dir = clean_target_dir === undefined ?
|
||||||
settings['clean-target']
|
settings['clean-target']
|
||||||
@ -2258,8 +2264,12 @@ var FileSystemWriterActions = actions.Actions({
|
|||||||
// we are using as the primary image to
|
// we are using as the primary image to
|
||||||
// save space...
|
// save space...
|
||||||
: null })
|
: null })
|
||||||
// add primary image...
|
// add primary image (copy)...
|
||||||
.concat(include_orig && img.path ?
|
// XXX check if any of the previews/main images
|
||||||
|
// matches the size and copy instead of resize...
|
||||||
|
.concat((!resize
|
||||||
|
&& include_orig
|
||||||
|
&& img.path) ?
|
||||||
[[
|
[[
|
||||||
(replace_orig && max != null) ?
|
(replace_orig && max != null) ?
|
||||||
// replace the base image with the
|
// replace the base image with the
|
||||||
@ -2306,18 +2316,25 @@ var FileSystemWriterActions = actions.Actions({
|
|||||||
// XXX do we queue these or let the OS handle it???
|
// XXX do we queue these or let the OS handle it???
|
||||||
// ...needs testing, if node's fs queues the io
|
// ...needs testing, if node's fs queues the io
|
||||||
// internally then we do not need to bother...
|
// internally then we do not need to bother...
|
||||||
queue.push(copy(from, to)
|
queue
|
||||||
.then(function(){
|
.push(copy(from, to)
|
||||||
logger && logger.emit('done', to) })
|
.then(function(){
|
||||||
.catch(function(err){
|
logger && logger.emit('done', to) })
|
||||||
logger && logger.emit('error', err) })) } }) } })
|
.catch(function(err){
|
||||||
|
logger && logger.emit('error', err) })) } }) } })
|
||||||
|
|
||||||
// prep the index...
|
// primary image (resize)...
|
||||||
|
resize
|
||||||
|
&& include_orig
|
||||||
|
&& queue
|
||||||
|
.push(this.makeResizedImage(gids, max_size, path, { logger }))
|
||||||
|
|
||||||
|
// index...
|
||||||
var index = this.prepareIndexForWrite(json, true)
|
var index = this.prepareIndexForWrite(json, true)
|
||||||
|
|
||||||
// NOTE: if we are to use .saveIndex(..) here, do not forget
|
// NOTE: if we are to use .saveIndex(..) here, do not forget
|
||||||
// to reset .changes
|
// to reset .changes
|
||||||
queue.push(
|
queue
|
||||||
|
.push(
|
||||||
file.writeIndex(
|
file.writeIndex(
|
||||||
index.index,
|
index.index,
|
||||||
index_path,
|
index_path,
|
||||||
@ -2335,8 +2352,7 @@ var FileSystemWriterActions = actions.Actions({
|
|||||||
|
|
||||||
return Promise.all(queue) }],
|
return Promise.all(queue) }],
|
||||||
|
|
||||||
// XXX BUG: seems to ignore max_size...
|
// XXX ASAP add option to control copy/resize -> .makeResizedImage(..)...
|
||||||
// ...'preview-size' does not affect the base image size...
|
|
||||||
// XXX might also be good to save/load the export options to .ImageGrid-export.json
|
// XXX might also be good to save/load the export options to .ImageGrid-export.json
|
||||||
// XXX resolve env variables in path... (???)
|
// XXX resolve env variables in path... (???)
|
||||||
// XXX make custom previews (option)...
|
// XXX make custom previews (option)...
|
||||||
@ -2458,8 +2474,14 @@ var FileSystemWriterActions = actions.Actions({
|
|||||||
&& !fse.existsSync(to)
|
&& !fse.existsSync(to)
|
||||||
&& outputFile(to, img.text || '')
|
&& outputFile(to, img.text || '')
|
||||||
|
|
||||||
// normal images...
|
// normal images (resize)...
|
||||||
|
} else if(that.makeResizedImage){
|
||||||
|
// XXX can we make this batch...
|
||||||
|
return that.makeResizedImage(gid, size, img_dir, { name, logger })
|
||||||
|
|
||||||
|
// normal images (copy)...
|
||||||
} else {
|
} else {
|
||||||
|
//*/
|
||||||
// NOTE: we are intentionally losing image dir
|
// NOTE: we are intentionally losing image dir
|
||||||
// name here -- we do not need to preserve
|
// name here -- we do not need to preserve
|
||||||
// topology when exporting...
|
// topology when exporting...
|
||||||
@ -2470,10 +2492,6 @@ var FileSystemWriterActions = actions.Actions({
|
|||||||
+'/'
|
+'/'
|
||||||
+ that.images.getBestPreview(gid, size).url
|
+ that.images.getBestPreview(gid, size).url
|
||||||
|
|
||||||
|
|
||||||
// XXX see if we need to make a preview (sharp)
|
|
||||||
// XXX
|
|
||||||
|
|
||||||
var to = img_dir +'/'+ name
|
var to = img_dir +'/'+ name
|
||||||
|
|
||||||
logger && logger.emit('queued', to)
|
logger && logger.emit('queued', to)
|
||||||
|
|||||||
@ -34,6 +34,7 @@ if(typeof(process) != 'undefined'){
|
|||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
if(typeof(process) != 'undefined'){
|
if(typeof(process) != 'undefined'){
|
||||||
|
var copy = file.denodeify(fse.copy)
|
||||||
var ensureDir = file.denodeify(fse.ensureDir)
|
var ensureDir = file.denodeify(fse.ensureDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,15 +113,184 @@ var SharpActions = actions.Actions({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.previewConstructorWorker.__post_handlers = {}
|
this.previewConstructorWorker.__post_handlers = {} }],
|
||||||
}],
|
|
||||||
stopPreviewWorker: ['- Sharp/',
|
stopPreviewWorker: ['- Sharp/',
|
||||||
function(){
|
function(){
|
||||||
this.previewConstructorWorker && this.previewConstructorWorker.kill()
|
this.previewConstructorWorker && this.previewConstructorWorker.kill()
|
||||||
delete this.previewConstructorWorker
|
delete this.previewConstructorWorker }],
|
||||||
}],
|
|
||||||
|
// XXX should this resize up??? ...option???
|
||||||
|
// XXX add transform/crop support...
|
||||||
|
// XXX revise logging...
|
||||||
|
makeResizedImage: ['- Image/',
|
||||||
|
core.doc`Make resized image(s)...
|
||||||
|
|
||||||
|
.makeResizedImage(gid, size, path[, options])
|
||||||
|
.makeResizedImage(gids, size, path[, options])
|
||||||
|
-> promise
|
||||||
|
|
||||||
|
|
||||||
|
Image size formats:
|
||||||
|
500px - resize to make image's *largest* dimension 500 pixels (default).
|
||||||
|
500p - resize to make image's *smallest* dimension 500 pixels.
|
||||||
|
500 - same as 500px
|
||||||
|
|
||||||
|
|
||||||
|
options format:
|
||||||
|
{
|
||||||
|
// output image name...
|
||||||
|
//
|
||||||
|
// Used if processing a single image, ignored otherwise.
|
||||||
|
name: <str>,
|
||||||
|
|
||||||
|
// image name pattern and data...
|
||||||
|
//
|
||||||
|
// NOTE: for more info on pattern see: .formatImageName(..)
|
||||||
|
pattern: <str>,
|
||||||
|
data: { .. },
|
||||||
|
|
||||||
|
// overwrite, backup or skip (default) existing images...
|
||||||
|
//
|
||||||
|
// default: null / false
|
||||||
|
overwrite: true | 'backup' | false,
|
||||||
|
|
||||||
|
// XXX not implemented...
|
||||||
|
transform: ...,
|
||||||
|
crop: ...,
|
||||||
|
|
||||||
|
logger: ...
|
||||||
|
, }
|
||||||
|
|
||||||
|
|
||||||
|
NOTE: this will not overwrite existing images.
|
||||||
|
`,
|
||||||
|
function(images, size, path, options={}){
|
||||||
|
var that = this
|
||||||
|
|
||||||
|
// sanity check...
|
||||||
|
if(arguments.length < 3){
|
||||||
|
throw new Error('.makeResizedImage(..): '
|
||||||
|
+'need at least images, size and path.') }
|
||||||
|
// get/normalize images...
|
||||||
|
//images = images || this.current
|
||||||
|
images = images
|
||||||
|
|| 'all'
|
||||||
|
// keywords...
|
||||||
|
images = images == 'all' ?
|
||||||
|
this.data.getImages('all')
|
||||||
|
: images == 'current' ?
|
||||||
|
this.current
|
||||||
|
: images
|
||||||
|
images = images instanceof Array ?
|
||||||
|
images
|
||||||
|
: [images]
|
||||||
|
// sizing...
|
||||||
|
var fit =
|
||||||
|
typeof(size) == typeof('str') ?
|
||||||
|
(size.endsWith('px') ?
|
||||||
|
'inside'
|
||||||
|
: size.endsWith('p') ?
|
||||||
|
'outside'
|
||||||
|
: 'inside')
|
||||||
|
: 'inside'
|
||||||
|
size = parseInt(size)
|
||||||
|
// options...
|
||||||
|
var {
|
||||||
|
// naming...
|
||||||
|
name,
|
||||||
|
pattern,
|
||||||
|
data,
|
||||||
|
// file handling...
|
||||||
|
overwrite,
|
||||||
|
// transformations...
|
||||||
|
// XXX not implemented...
|
||||||
|
transform,
|
||||||
|
// XXX not implemented...
|
||||||
|
crop,
|
||||||
|
|
||||||
|
logger,
|
||||||
|
} = options
|
||||||
|
// defaults...
|
||||||
|
pattern = pattern || '%n'
|
||||||
|
/* XXX
|
||||||
|
transform = transform === undefined ?
|
||||||
|
true
|
||||||
|
: transform
|
||||||
|
//*/
|
||||||
|
logger = logger || this.logger
|
||||||
|
logger = logger && logger.push('Resize')
|
||||||
|
|
||||||
|
var timestamp = Date.timeStamp()
|
||||||
|
|
||||||
|
return Promise.all(images
|
||||||
|
.map(function(gid){
|
||||||
|
// skip non-images...
|
||||||
|
if(that.images[gid].type != undefined){
|
||||||
|
return }
|
||||||
|
|
||||||
|
// paths...
|
||||||
|
var source = that.getImagePath(gid)
|
||||||
|
var to = pathlib.join(
|
||||||
|
path,
|
||||||
|
(images.length == 1 && name) ?
|
||||||
|
name
|
||||||
|
: that.formatImageName(pattern, gid, data || {}))
|
||||||
|
|
||||||
|
logger && logger.emit('queued', to)
|
||||||
|
|
||||||
|
// existing image...
|
||||||
|
if(fse.existsSync(to)){
|
||||||
|
// rename...
|
||||||
|
if(overwrite == 'backup'){
|
||||||
|
var i = 0
|
||||||
|
while(fse.existsSync(`${to}.${timestamp}'-bak`+ (i || ''))){
|
||||||
|
i++ }
|
||||||
|
fse.renameSync(
|
||||||
|
to,
|
||||||
|
fse.existsSync(`${to}.${timestamp}'-bak`+ (i || '')))
|
||||||
|
// remove...
|
||||||
|
} else if(overwrite){
|
||||||
|
fse.removeSync(to)
|
||||||
|
// skip...
|
||||||
|
} else {
|
||||||
|
logger && logger.emit('skipping', to)
|
||||||
|
return } }
|
||||||
|
|
||||||
|
return ensureDir(pathlib.dirname(to))
|
||||||
|
.then(function(){
|
||||||
|
return sharp(source)
|
||||||
|
.clone()
|
||||||
|
// handle transform (.orientation / .flip) and .crop...
|
||||||
|
.run(function(){
|
||||||
|
// XXX
|
||||||
|
if(transform || crop){
|
||||||
|
throw new Error('.makeResizedImage(..): '
|
||||||
|
+[
|
||||||
|
transform ? 'transform' : [],
|
||||||
|
crop ? 'crop' : [],
|
||||||
|
].flat().join(' and ')
|
||||||
|
+' not implemented...') }
|
||||||
|
// XXX need clear spec defining what
|
||||||
|
// order transforms are applied
|
||||||
|
// and in which coordinates we
|
||||||
|
// crop (i.e. pre/post transform)...
|
||||||
|
if(transform){
|
||||||
|
}
|
||||||
|
if(crop){
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.resize({
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
fit: fit,
|
||||||
|
})
|
||||||
|
.withMetadata()
|
||||||
|
.toFile(to)
|
||||||
|
.then(function(){
|
||||||
|
logger
|
||||||
|
&& logger.emit('done', to) })}) })) }],
|
||||||
|
|
||||||
|
// XXX use .makeResizedImage(..)
|
||||||
// XXX should this account for non-jpeg images???
|
// XXX should this account for non-jpeg images???
|
||||||
// XXX BUG?: this breaks on PNG images...
|
// XXX BUG?: this breaks on PNG images...
|
||||||
// XXX log: count gids and not specific images...
|
// XXX log: count gids and not specific images...
|
||||||
@ -150,12 +320,17 @@ var SharpActions = actions.Actions({
|
|||||||
|
|
||||||
// get/normalize images...
|
// get/normalize images...
|
||||||
//images = images || this.current
|
//images = images || this.current
|
||||||
images = images || 'all'
|
images = images
|
||||||
|
|| 'all'
|
||||||
// keywords...
|
// keywords...
|
||||||
images = images == 'all' ? this.data.getImages('all')
|
images = images == 'all' ?
|
||||||
: images == 'current' ? this.current
|
this.data.getImages('all')
|
||||||
|
: images == 'current' ?
|
||||||
|
this.current
|
||||||
: images
|
: images
|
||||||
images = images instanceof Array ? images : [images]
|
images = images instanceof Array ?
|
||||||
|
images
|
||||||
|
: [images]
|
||||||
|
|
||||||
//
|
//
|
||||||
// Format:
|
// Format:
|
||||||
@ -203,8 +378,7 @@ var SharpActions = actions.Actions({
|
|||||||
.unique()
|
.unique()
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
sizes = cfg_sizes
|
sizes = cfg_sizes }
|
||||||
}
|
|
||||||
|
|
||||||
var path_tpl = that.config['preview-path-template']
|
var path_tpl = that.config['preview-path-template']
|
||||||
.replace(/\$INDEX|\$\{INDEX\}/g, that.config['index-dir'] || '.ImageGrid')
|
.replace(/\$INDEX|\$\{INDEX\}/g, that.config['index-dir'] || '.ImageGrid')
|
||||||
@ -280,8 +454,7 @@ var SharpActions = actions.Actions({
|
|||||||
sizes,
|
sizes,
|
||||||
base_path,
|
base_path,
|
||||||
path_tpl,
|
path_tpl,
|
||||||
post_handler) }))}
|
post_handler) }))} }],
|
||||||
}],
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -80,8 +80,7 @@ function(images, sizes, base_path, target_tpl, callback){
|
|||||||
.map(function(res){
|
.map(function(res){
|
||||||
// skip if image is smaller than res...
|
// skip if image is smaller than res...
|
||||||
if(res >= orig_res){
|
if(res >= orig_res){
|
||||||
return
|
return }
|
||||||
}
|
|
||||||
|
|
||||||
var rel = target
|
var rel = target
|
||||||
.replace(/\$RESOLUTION|\$\{RESOLUTION\}/g, res)
|
.replace(/\$RESOLUTION|\$\{RESOLUTION\}/g, res)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user