mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-28 18:00:09 +00:00
cleanup...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
9c72528908
commit
c750895a4a
@ -185,440 +185,9 @@ var SharpActions = actions.Actions({
|
||||
// from filesystem.IndexFormat...
|
||||
},
|
||||
|
||||
// XXX either make this a session task or make this survive loading
|
||||
// a new index...
|
||||
// XXX revise return values...
|
||||
// XXX make backup name pattern configurable...
|
||||
// XXX CROP ready for crop support...
|
||||
_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 / name pattern...
|
||||
//
|
||||
// NOTE: for multiple images this should be a pattern and not an
|
||||
// explicit name...
|
||||
// NOTE: if not given this defaults to: "%n"
|
||||
name: null | <str>,
|
||||
|
||||
// image name pattern data...
|
||||
//
|
||||
// NOTE: for more info on pattern see: .formatImageName(..)
|
||||
data: null | { .. },
|
||||
|
||||
// if true and image is smaller than size enlarge it...
|
||||
//
|
||||
// default: null / false
|
||||
enlarge: null | true,
|
||||
|
||||
// overwrite, backup or skip (default) existing images...
|
||||
//
|
||||
// default: null / false
|
||||
overwrite: null | true | 'backup',
|
||||
|
||||
// if true do not write an image if it's smaller than size...
|
||||
//
|
||||
// default: null / false
|
||||
skipSmaller: null | true,
|
||||
|
||||
// XXX not implemented...
|
||||
transform: ...,
|
||||
crop: ...,
|
||||
|
||||
timestamp: ...,
|
||||
logger: ...,
|
||||
, }
|
||||
|
||||
|
||||
NOTE: all options are optional.
|
||||
NOTE: this will not overwrite existing images.
|
||||
`,
|
||||
core.sessionQueueHandler('Make resized image',
|
||||
// get/normalize images...
|
||||
// XXX if this is to be a global task (i.e. .queueHandler(..)) we'll
|
||||
// need to get all the image data here...
|
||||
// ...paths and orientation data...
|
||||
function(queue, images, size, path, options){
|
||||
// sanity check...
|
||||
if(arguments.length < 4){
|
||||
throw new Error('.makeResizedImage(..): '
|
||||
+'need at least: images, size and path.') }
|
||||
return [
|
||||
(images == null || images == 'all') ?
|
||||
this.data.getImages('all')
|
||||
: images == 'current' ?
|
||||
[this.current]
|
||||
: images instanceof Array ?
|
||||
images
|
||||
: [images],
|
||||
...[...arguments].slice(2),
|
||||
]},
|
||||
function(gid, size, path, options={}){
|
||||
var that = this
|
||||
|
||||
// sizing...
|
||||
var fit =
|
||||
typeof(size) == typeof('str') ?
|
||||
(size.endsWith('px') ?
|
||||
'inside'
|
||||
: size.endsWith('p') ?
|
||||
'outside'
|
||||
: 'inside')
|
||||
: 'inside'
|
||||
size = parseInt(size)
|
||||
// options...
|
||||
var {
|
||||
// naming...
|
||||
name,
|
||||
data,
|
||||
|
||||
// file handling...
|
||||
enlarge,
|
||||
skipSmaller,
|
||||
overwrite,
|
||||
|
||||
// transformations...
|
||||
transform,
|
||||
// XXX CROP not implemented...
|
||||
//crop,
|
||||
|
||||
timestamp,
|
||||
//logger,
|
||||
} = options
|
||||
// defaults...
|
||||
name = name || '%n'
|
||||
transform = transform === undefined ?
|
||||
true
|
||||
: transform
|
||||
timestamp = timestamp || Date.timeStamp()
|
||||
|
||||
// backup...
|
||||
// XXX make backup name pattern configurable...
|
||||
var backupName = function(to){
|
||||
var i = 0
|
||||
while(fse.existsSync(`${to}.${timestamp}.bak`+ (i || ''))){
|
||||
i++ }
|
||||
return `${to}.${timestamp}.bak`+ (i || '') }
|
||||
|
||||
// skip non-images...
|
||||
if(!['image', null, undefined]
|
||||
.includes(this.images[gid].type)){
|
||||
// XXX what should we return???
|
||||
return Promise.resolve() }
|
||||
|
||||
// paths...
|
||||
var source = this.getImagePath(gid)
|
||||
var to = pathlib.resolve(
|
||||
this.location.path,
|
||||
pathlib.join(
|
||||
path,
|
||||
// if name is not a pattern do not re-format it...
|
||||
name.includes('%') ?
|
||||
this.formatImageName(name, gid, data || {})
|
||||
: name))
|
||||
|
||||
var img = sharp(source)
|
||||
return (skipSmaller ?
|
||||
// skip if smaller than size...
|
||||
img
|
||||
.metadata()
|
||||
.then(function(m){
|
||||
// skip...
|
||||
if((fit == 'inside'
|
||||
&& Math.max(m.width, m.height) < size)
|
||||
|| (fit == 'outside'
|
||||
&& Math.min(m.width, m.height) < size)){
|
||||
return }
|
||||
// continue...
|
||||
return img })
|
||||
: Promise.resolve(img))
|
||||
// prepare to write...
|
||||
.then(function(img){
|
||||
return img
|
||||
&& ensureDir(pathlib.dirname(to))
|
||||
.then(function(){
|
||||
// handle existing image...
|
||||
if(fse.existsSync(to)){
|
||||
// rename...
|
||||
if(overwrite == 'backup'){
|
||||
fse.renameSync(to, backupName(to))
|
||||
// remove...
|
||||
} else if(overwrite){
|
||||
fse.removeSync(to)
|
||||
// skip...
|
||||
} else {
|
||||
return Promise.reject('target exists') } }
|
||||
|
||||
// write...
|
||||
return img
|
||||
.clone()
|
||||
// handle transform (.orientation / .flip) and .crop...
|
||||
.run(function(){
|
||||
var img = that.images[gid]
|
||||
if(transform && (img.orientation || img.flipped)){
|
||||
img.orientation
|
||||
&& this.rotate(img.orientation)
|
||||
img.flipped
|
||||
&& img.flipped.includes('horizontal')
|
||||
&& this.flip() }
|
||||
img.flipped
|
||||
&& img.flipped.includes('vertical')
|
||||
&& this.flop()
|
||||
// XXX CROP
|
||||
//if(crop){
|
||||
// // XXX
|
||||
//}
|
||||
})
|
||||
.resize({
|
||||
width: size,
|
||||
height: size,
|
||||
fit: fit,
|
||||
withoutEnlargement: !enlarge,
|
||||
})
|
||||
.withMetadata()
|
||||
.toFile(to)
|
||||
.then(function(){
|
||||
// XXX what should we return???
|
||||
return to }) }) }) })],
|
||||
|
||||
_makeResizedImage2: ['- 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 / name pattern...
|
||||
//
|
||||
// NOTE: for multiple images this should be a pattern and not an
|
||||
// explicit name...
|
||||
// NOTE: if not given this defaults to: "%n"
|
||||
name: null | <str>,
|
||||
|
||||
// image name pattern data...
|
||||
//
|
||||
// NOTE: for more info on pattern see: .formatImageName(..)
|
||||
data: null | { .. },
|
||||
|
||||
// if true and image is smaller than size enlarge it...
|
||||
//
|
||||
// default: null / false
|
||||
enlarge: null | true,
|
||||
|
||||
// overwrite, backup or skip (default) existing images...
|
||||
//
|
||||
// default: null / false
|
||||
overwrite: null | true | 'backup',
|
||||
|
||||
// if true do not write an image if it's smaller than size...
|
||||
//
|
||||
// default: null / false
|
||||
skipSmaller: null | true,
|
||||
|
||||
// XXX not implemented...
|
||||
transform: ...,
|
||||
crop: ...,
|
||||
|
||||
timestamp: ...,
|
||||
logger: ...,
|
||||
, }
|
||||
|
||||
|
||||
NOTE: all options are optional.
|
||||
NOTE: this will not overwrite existing images.
|
||||
`,
|
||||
core.queueHandler('Make resized image',
|
||||
// queue the image data...
|
||||
// NOTE: after this runs we should be completely independent
|
||||
// of the current index...
|
||||
// XXX for a very large number of images this can block for
|
||||
// a substantial amount of time...
|
||||
function(queue, images, size, path, options){
|
||||
var that = this
|
||||
// sanity check...
|
||||
if(arguments.length < 4){
|
||||
throw new Error('.makeResizedImage(..): '
|
||||
+'need at least: images, size and path.') }
|
||||
// options...
|
||||
var {
|
||||
name,
|
||||
data,
|
||||
} = options || {}
|
||||
name = name || '%n'
|
||||
// [source, to, image], ...args
|
||||
return [
|
||||
((images == null || images == 'all') ?
|
||||
this.data.getimages('all')
|
||||
: images == 'current' ?
|
||||
[this.current]
|
||||
: images instanceof array ?
|
||||
images
|
||||
: [images])
|
||||
.map(function(gid){
|
||||
var image = that.images[gid]
|
||||
// skip non-images...
|
||||
if(!image || !['image', null, undefined]
|
||||
.includes(image.type)){
|
||||
return [] }
|
||||
return [[
|
||||
// source...
|
||||
that.getimagepath(gid),
|
||||
// target...
|
||||
pathlib.resolve(
|
||||
that.location.path,
|
||||
pathlib.join(
|
||||
path,
|
||||
// if name is not a pattern do not re-format it...
|
||||
name.includes('%') ?
|
||||
that.formatimagename(name, gid, data || {})
|
||||
: name)),
|
||||
// image data...
|
||||
// note: we include only the stuff we need...
|
||||
{
|
||||
orientation: image.orientation,
|
||||
flipped: image.flipped,
|
||||
// crop...
|
||||
},
|
||||
]] })
|
||||
.flat(),
|
||||
...[...arguments].slice(2),
|
||||
]},
|
||||
function([source, to, image], size, _, options={}){
|
||||
// sizing...
|
||||
var fit =
|
||||
typeof(size) == typeof('str') ?
|
||||
(size.endsWith('px') ?
|
||||
'inside'
|
||||
: size.endsWith('p') ?
|
||||
'outside'
|
||||
: 'inside')
|
||||
: 'inside'
|
||||
size = parseInt(size)
|
||||
// options...
|
||||
var {
|
||||
enlarge,
|
||||
skipSmaller,
|
||||
overwrite,
|
||||
transform,
|
||||
timestamp,
|
||||
backupImagePattern,
|
||||
//logger,
|
||||
} = options
|
||||
// defaults...
|
||||
transform = transform === undefined ?
|
||||
true
|
||||
: transform
|
||||
timestamp = timestamp || Date.timeStamp()
|
||||
// backup by default...
|
||||
overwrite = overwrite === undefined ?
|
||||
'backup'
|
||||
: overwrite
|
||||
backupImagePattern =
|
||||
(backupImagePattern
|
||||
|| '${PATH}.${TIMESTAMP}${COUNT}.bak')
|
||||
.replace(/\${PATH}|$PATH/, to)
|
||||
.replace(/\${TIMESTAMP}|$TIMESTAMP/, timestamp)
|
||||
// backup...
|
||||
// NOTE: we are doing the check at the very last moment and
|
||||
// not here to avoid race conditions as much as practical...
|
||||
var backupName = function(){
|
||||
var i = 0
|
||||
var n
|
||||
do{
|
||||
n = backupImagePattern
|
||||
.replace(/\${COUNT}|$COUNT/, i++ ? '.'+i : i)
|
||||
} while(fse.existsSync(n))
|
||||
return n }
|
||||
|
||||
var img = sharp(source)
|
||||
return (skipSmaller ?
|
||||
// skip if smaller than size...
|
||||
img
|
||||
.metadata()
|
||||
.then(function(m){
|
||||
// skip...
|
||||
if((fit == 'inside'
|
||||
&& Math.max(m.width, m.height) < size)
|
||||
|| (fit == 'outside'
|
||||
&& Math.min(m.width, m.height) < size)){
|
||||
return }
|
||||
// continue...
|
||||
return img })
|
||||
: Promise.resolve(img))
|
||||
// prepare to write...
|
||||
.then(function(img){
|
||||
return img
|
||||
&& ensureDir(pathlib.dirname(to))
|
||||
.then(function(){
|
||||
// handle existing image...
|
||||
if(fse.existsSync(to)){
|
||||
// rename...
|
||||
if(overwrite == 'backup'){
|
||||
fse.renameSync(to, backupName(to))
|
||||
// remove...
|
||||
} else if(overwrite){
|
||||
fse.removeSync(to)
|
||||
// skip...
|
||||
} else {
|
||||
return Promise.reject('target exists') } }
|
||||
// write...
|
||||
return img
|
||||
.clone()
|
||||
// handle transform (.orientation / .flip) and .crop...
|
||||
.run(function(){
|
||||
if(transform && (image.orientation || image.flipped)){
|
||||
image.orientation
|
||||
&& this.rotate(image.orientation)
|
||||
image.flipped
|
||||
&& image.flipped.includes('horizontal')
|
||||
&& this.flip() }
|
||||
image.flipped
|
||||
&& image.flipped.includes('vertical')
|
||||
&& this.flop()
|
||||
// XXX CROP
|
||||
//if(crop){
|
||||
// // XXX
|
||||
//}
|
||||
})
|
||||
.resize({
|
||||
width: size,
|
||||
height: size,
|
||||
fit: fit,
|
||||
withoutEnlargement: !enlarge,
|
||||
})
|
||||
.withMetadata()
|
||||
.toFile(to)
|
||||
.then(function(){
|
||||
// XXX what should we return???
|
||||
return to }) }) }) })],
|
||||
|
||||
// XXX we need to split this into two stages:
|
||||
// - session queue handler
|
||||
// - global queue handler
|
||||
// i.e. call the second queue generator when the first one completes...
|
||||
// or in other works chain queues -- essentially this is like
|
||||
// calling .then(..) on a queue but doing it at definition...
|
||||
makeResizedImage: ['- Image/',
|
||||
core.doc`Make resized image(s)...
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user