mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 18:30:09 +00:00
reworked metadata caching + updated peer feature (not done yet)...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
f9398462c8
commit
49245ba9d1
@ -57,8 +57,7 @@ var MetadataActions = actions.Actions({
|
|||||||
if(this.images && this.images[gid]){
|
if(this.images && this.images[gid]){
|
||||||
return this.images[gid].metadata || {}
|
return this.images[gid].metadata || {}
|
||||||
}
|
}
|
||||||
return null
|
return null }],
|
||||||
}],
|
|
||||||
setMetadata: ['- Image/Set metadata data',
|
setMetadata: ['- Image/Set metadata data',
|
||||||
function(image, metadata, merge){
|
function(image, metadata, merge){
|
||||||
var that = this
|
var that = this
|
||||||
@ -70,12 +69,8 @@ var MetadataActions = actions.Actions({
|
|||||||
Object.keys(metadata).forEach(function(k){
|
Object.keys(metadata).forEach(function(k){
|
||||||
m[k] = metadata[k]
|
m[k] = metadata[k]
|
||||||
})
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.images[gid].metadata = metadata
|
this.images[gid].metadata = metadata } } }]
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
var Metadata =
|
var Metadata =
|
||||||
@ -119,21 +114,19 @@ var MetadataReaderActions = actions.Actions({
|
|||||||
var img = this.images && this.images[gid]
|
var img = this.images && this.images[gid]
|
||||||
|
|
||||||
if(!image && !img){
|
if(!image && !img){
|
||||||
return false
|
return false }
|
||||||
}
|
|
||||||
|
|
||||||
//var full_path = path.normalize(img.base_path +'/'+ img.path)
|
//var full_path = path.normalize(img.base_path +'/'+ img.path)
|
||||||
var full_path = this.getImagePath(gid)
|
var full_path = this.getImagePath(gid)
|
||||||
|
|
||||||
return new Promise(function(resolve, reject){
|
return new Promise(function(resolve, reject){
|
||||||
if(!force && img.metadata){
|
if(!force
|
||||||
return resolve(img.metadata)
|
&& !(img.metadata || {}).ImageGridPartialMetadata){
|
||||||
}
|
return resolve(img.metadata) }
|
||||||
|
|
||||||
fs.readFile(full_path, function(err, file){
|
fs.readFile(full_path, function(err, file){
|
||||||
if(err){
|
if(err){
|
||||||
return reject(err)
|
return reject(err) }
|
||||||
}
|
|
||||||
|
|
||||||
// read stat...
|
// read stat...
|
||||||
if(!that.images[gid].birthtime){
|
if(!that.images[gid].birthtime){
|
||||||
@ -173,10 +166,7 @@ var MetadataReaderActions = actions.Actions({
|
|||||||
that.markChanged
|
that.markChanged
|
||||||
&& that.markChanged('images', [gid]) }
|
&& that.markChanged('images', [gid]) }
|
||||||
|
|
||||||
resolve(data) })
|
resolve(data) }) }) }) }],
|
||||||
})
|
|
||||||
})
|
|
||||||
}],
|
|
||||||
|
|
||||||
// XXX STUB: add support for this to .readMetadata(..)
|
// XXX STUB: add support for this to .readMetadata(..)
|
||||||
readAllMetadata: ['File/Read all metadata',
|
readAllMetadata: ['File/Read all metadata',
|
||||||
@ -202,8 +192,7 @@ var MetadataReaderActions = actions.Actions({
|
|||||||
q.enqueue('metadata', read(gid))
|
q.enqueue('metadata', read(gid))
|
||||||
})
|
})
|
||||||
|
|
||||||
return q
|
return q }],
|
||||||
}],
|
|
||||||
|
|
||||||
// XXX take image Metadata and write it to target...
|
// XXX take image Metadata and write it to target...
|
||||||
writeMetadata: ['- Image/Set metadata data',
|
writeMetadata: ['- Image/Set metadata data',
|
||||||
@ -651,9 +640,7 @@ var MetadataUIActions = actions.Actions({
|
|||||||
&& (that.config['metadata-graph-config'] = {
|
&& (that.config['metadata-graph-config'] = {
|
||||||
graph: this.graph.graph,
|
graph: this.graph.graph,
|
||||||
mode: this.graph.mode,
|
mode: this.graph.mode,
|
||||||
})
|
}) }) })],
|
||||||
})
|
|
||||||
})],
|
|
||||||
|
|
||||||
metadataSection: ['- Image/',
|
metadataSection: ['- Image/',
|
||||||
{ sortedActionPriority: 'normal' },
|
{ sortedActionPriority: 'normal' },
|
||||||
@ -663,16 +650,18 @@ var MetadataUIActions = actions.Actions({
|
|||||||
var field_order = this.config['metadata-field-order'] || []
|
var field_order = this.config['metadata-field-order'] || []
|
||||||
var x = field_order.length + 1
|
var x = field_order.length + 1
|
||||||
|
|
||||||
|
// NOTE: this is called on showMetadata.pre in the .handlers
|
||||||
|
// feature section...
|
||||||
make.dialog.updateMetadata =
|
make.dialog.updateMetadata =
|
||||||
function(metadata){
|
function(metadata){
|
||||||
metadata = metadata || that.getMetadata()
|
metadata = metadata
|
||||||
|
|| that.getMetadata()
|
||||||
|
|
||||||
// build new data set and update view...
|
// build new data set and update view...
|
||||||
//this.options.data = _buildInfoList(image, metadata)
|
//this.options.data = _buildInfoList(image, metadata)
|
||||||
this.update()
|
this.update()
|
||||||
|
|
||||||
return this
|
return this }
|
||||||
}
|
|
||||||
|
|
||||||
// build fields...
|
// build fields...
|
||||||
var fields = []
|
var fields = []
|
||||||
@ -691,15 +680,12 @@ var MetadataUIActions = actions.Actions({
|
|||||||
return
|
return
|
||||||
|
|
||||||
} else if(mode == 'disabled') {
|
} else if(mode == 'disabled') {
|
||||||
opts.disabled = true
|
opts.disabled = true } }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fields.push([
|
fields.push([
|
||||||
[ n + ': ', metadata[k] ],
|
[ n + ': ', metadata[k] ],
|
||||||
opts,
|
opts,
|
||||||
])
|
]) })
|
||||||
})
|
|
||||||
|
|
||||||
// make fields...
|
// make fields...
|
||||||
fields
|
fields
|
||||||
@ -717,8 +703,7 @@ var MetadataUIActions = actions.Actions({
|
|||||||
this.length > 0
|
this.length > 0
|
||||||
&& make.Separator() })
|
&& make.Separator() })
|
||||||
.forEach(function(e){
|
.forEach(function(e){
|
||||||
make(...e) })
|
make(...e) }) })],
|
||||||
})],
|
|
||||||
|
|
||||||
|
|
||||||
// shorthands...
|
// shorthands...
|
||||||
|
|||||||
@ -19,114 +19,13 @@ var features = require('lib/features')
|
|||||||
var core = require('features/core')
|
var core = require('features/core')
|
||||||
|
|
||||||
var object = require('lib/object')
|
var object = require('lib/object')
|
||||||
|
var types = require('lib/types')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
// helpers...
|
// helpers...
|
||||||
|
|
||||||
// Cooperative promise object...
|
|
||||||
//
|
|
||||||
// This is like a promise but is not resolved internally, rather this
|
|
||||||
// resolves (is set) via a different promise of value passed to it via
|
|
||||||
// the .set(..) method...
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// // create a promise...
|
|
||||||
// var p = (new CooperativePromise())
|
|
||||||
// // bind normally...
|
|
||||||
// .then(function(){ .. })
|
|
||||||
//
|
|
||||||
// // this will resolve p and trigger all the .then(..) callbacks...
|
|
||||||
// p.set(new Promise(function(resolve, reject){ resolve() }))
|
|
||||||
//
|
|
||||||
// Note that .set(..) can be passed any value, passing a non-promise has
|
|
||||||
// the same effect as passing the same value to resolve(..) of a Promise
|
|
||||||
// object...
|
|
||||||
//
|
|
||||||
// XXX should this be a separate package???
|
|
||||||
// XXX can we make this an instance of Promise for passing the
|
|
||||||
// x instanceof Promise test???
|
|
||||||
var CooperativePromisePrototype = {
|
|
||||||
__base: null,
|
|
||||||
__promise: null,
|
|
||||||
|
|
||||||
// XXX error if already set...
|
|
||||||
set: function(promise){
|
|
||||||
if(this.__promise == null){
|
|
||||||
// setting a non-promise...
|
|
||||||
if(promise.catch == null && promise.then == null){
|
|
||||||
Object.defineProperty(this, '__promise', {
|
|
||||||
value: false,
|
|
||||||
enumerable: false,
|
|
||||||
})
|
|
||||||
this.__resolve(promise)
|
|
||||||
|
|
||||||
// setting a promise...
|
|
||||||
} else {
|
|
||||||
Object.defineProperty(this, '__promise', {
|
|
||||||
value: promise,
|
|
||||||
enumerable: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
// connect the base and the set promises...
|
|
||||||
promise.catch(this.__reject.bind(this))
|
|
||||||
promise.then(this.__resolve.bind(this))
|
|
||||||
|
|
||||||
// cleanup...
|
|
||||||
delete this.__base
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup...
|
|
||||||
delete this.__resolve
|
|
||||||
delete this.__reject
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// XXX throw err???
|
|
||||||
console.error('Setting a cooperative promise twice', this)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Promise API...
|
|
||||||
catch: function(func){
|
|
||||||
return (this.__promise || this.__base).catch(func) },
|
|
||||||
then: function(func){
|
|
||||||
return (this.__promise || this.__base).then(func) },
|
|
||||||
|
|
||||||
__init__: function(){
|
|
||||||
var that = this
|
|
||||||
var base = new Promise(function(resolve, reject){
|
|
||||||
Object.defineProperties(that, {
|
|
||||||
__resolve: {
|
|
||||||
value: resolve,
|
|
||||||
enumerable: false,
|
|
||||||
configurable: true,
|
|
||||||
},
|
|
||||||
__reject: {
|
|
||||||
value: reject,
|
|
||||||
enumerable: false,
|
|
||||||
configurable: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
Object.defineProperty(this, '__base', {
|
|
||||||
value: base,
|
|
||||||
enumerable: false,
|
|
||||||
configurable: true,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var CooperativePromise =
|
|
||||||
module.CooperativePromise =
|
|
||||||
object.Constructor('CooperativePromise',
|
|
||||||
Promise,
|
|
||||||
CooperativePromisePrototype)
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
|
|
||||||
// XXX would be nice to list the protocols supported by the action in
|
// XXX would be nice to list the protocols supported by the action in
|
||||||
// an action attr...
|
// an action attr...
|
||||||
var makeProtocolHandler =
|
var makeProtocolHandler =
|
||||||
@ -192,8 +91,7 @@ var PeerActions = actions.Actions({
|
|||||||
return that.getActionAttr(action, '__peer__') == id }
|
return that.getActionAttr(action, '__peer__') == id }
|
||||||
// get all peer actions...
|
// get all peer actions...
|
||||||
: function(action){
|
: function(action){
|
||||||
return that.getActionAttr(action, '__peer__') })
|
return that.getActionAttr(action, '__peer__') }) }],
|
||||||
}],
|
|
||||||
// XXX should this also check props???
|
// XXX should this also check props???
|
||||||
isPeerAction: ['- System/Peer/',
|
isPeerAction: ['- System/Peer/',
|
||||||
function(name){
|
function(name){
|
||||||
@ -208,9 +106,11 @@ var PeerActions = actions.Actions({
|
|||||||
// XXX the events should get called on the peer too -- who is
|
// XXX the events should get called on the peer too -- who is
|
||||||
// responsible for this???
|
// responsible for this???
|
||||||
peerConnect: ['- System/Peer/',
|
peerConnect: ['- System/Peer/',
|
||||||
function(id, options){ return new CooperativePromise() }],
|
function(id, options){
|
||||||
|
return new Promise.cooperative() }],
|
||||||
peerDisconnect: ['- System/Peer/',
|
peerDisconnect: ['- System/Peer/',
|
||||||
function(id){ return new CooperativePromise() }],
|
function(id){
|
||||||
|
return new Promise.cooperative() }],
|
||||||
|
|
||||||
// events...
|
// events...
|
||||||
// XXX do proper docs...
|
// XXX do proper docs...
|
||||||
@ -229,13 +129,14 @@ var PeerActions = actions.Actions({
|
|||||||
peerCall: ['- System/Peer/',
|
peerCall: ['- System/Peer/',
|
||||||
function(id, action){
|
function(id, action){
|
||||||
var args = [...arguments].slice(2)
|
var args = [...arguments].slice(2)
|
||||||
return this.peerApply(id, action, args)
|
return this.peerApply(id, action, args) }],
|
||||||
}],
|
|
||||||
peerApply: ['- System/Peer/',
|
peerApply: ['- System/Peer/',
|
||||||
function(id, action, args){ return new CooperativePromise() }],
|
function(id, action, args){
|
||||||
|
return new Promise.cooperative() }],
|
||||||
|
|
||||||
peerList: ['- System/Peer/',
|
peerList: ['- System/Peer/',
|
||||||
function(){ return Object.keys(this.__peers || {}) }],
|
function(){
|
||||||
|
return Object.keys(this.__peers || {}) }],
|
||||||
|
|
||||||
// XXX do we need these???
|
// XXX do we need these???
|
||||||
// XXX format spec!!!
|
// XXX format spec!!!
|
||||||
@ -287,8 +188,7 @@ var ChildProcessPeerActions = actions.Actions({
|
|||||||
if(this.__peers
|
if(this.__peers
|
||||||
&& id in this.__peers
|
&& id in this.__peers
|
||||||
&& this.__peers[id].peer.connected){
|
&& this.__peers[id].peer.connected){
|
||||||
return resolve(id)
|
return resolve(id) }
|
||||||
}
|
|
||||||
|
|
||||||
this.__peers = this.__peers || {}
|
this.__peers = this.__peers || {}
|
||||||
|
|
||||||
@ -307,13 +207,9 @@ var ChildProcessPeerActions = actions.Actions({
|
|||||||
|
|
||||||
callback
|
callback
|
||||||
&& (delete this.__peer_result_callbacks[msg.id])
|
&& (delete this.__peer_result_callbacks[msg.id])
|
||||||
&& callback(msg.value, msg.error)
|
&& callback(msg.value, msg.error) } }).bind(this))
|
||||||
}
|
|
||||||
}).bind(this))
|
|
||||||
|
|
||||||
resolve(id)
|
resolve(id) }).bind(this)) })],
|
||||||
}).bind(this))
|
|
||||||
})],
|
|
||||||
// XXX should this call .stop() on the child???
|
// XXX should this call .stop() on the child???
|
||||||
// ...does the child handle kill gracefully???
|
// ...does the child handle kill gracefully???
|
||||||
peerDisconnect: ['- System/Peer/',
|
peerDisconnect: ['- System/Peer/',
|
||||||
@ -329,8 +225,7 @@ var ChildProcessPeerActions = actions.Actions({
|
|||||||
that.__peers[id].peer.kill()
|
that.__peers[id].peer.kill()
|
||||||
delete that.__peers[id]
|
delete that.__peers[id]
|
||||||
|
|
||||||
}).bind(this))
|
}).bind(this)) })],
|
||||||
})],
|
|
||||||
|
|
||||||
// XXX can we do sync???
|
// XXX can we do sync???
|
||||||
// ...this would be useful to 100% match the action api and
|
// ...this would be useful to 100% match the action api and
|
||||||
@ -358,8 +253,7 @@ var ChildProcessPeerActions = actions.Actions({
|
|||||||
var handlers = this.__peer_result_callbacks = this.__peer_result_callbacks || {}
|
var handlers = this.__peer_result_callbacks = this.__peer_result_callbacks || {}
|
||||||
handlers[call_id] = function(res, err){ err ? reject(err) : resolve(res) }
|
handlers[call_id] = function(res, err){ err ? reject(err) : resolve(res) }
|
||||||
|
|
||||||
}).bind(this))
|
}).bind(this)) })],
|
||||||
})],
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -32,13 +32,19 @@ if(typeof(process) != 'undefined'){
|
|||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
// helpers...
|
||||||
|
|
||||||
if(typeof(process) != 'undefined'){
|
if(typeof(process) != 'undefined'){
|
||||||
var copy = file.denodeify(fse.copy)
|
var copy = file.denodeify(fse.copy)
|
||||||
var ensureDir = file.denodeify(fse.ensureDir)
|
var ensureDir = file.denodeify(fse.ensureDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeOrientation(orientation){
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
var normalizeOrientation =
|
||||||
|
module.normalizeOrientation =
|
||||||
|
function(orientation){
|
||||||
return {
|
return {
|
||||||
orientation: ({
|
orientation: ({
|
||||||
0: 0,
|
0: 0,
|
||||||
@ -65,9 +71,94 @@ function normalizeOrientation(orientation){
|
|||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
||||||
var exifReader2exiftool = {
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Convert image metadata from exif-reader output to format compatible
|
||||||
|
// with exiftool (features/metadata.js)
|
||||||
|
|
||||||
|
// Format:
|
||||||
|
// {
|
||||||
|
// // simple key-key pair...
|
||||||
|
// 'path.to.value': 'output-key',
|
||||||
|
//
|
||||||
|
// // key with value handler...
|
||||||
|
// 'path.to.other.value': ['output-key', handler],
|
||||||
|
//
|
||||||
|
// // alias to handler...
|
||||||
|
// 'path.to.yet.another.value': ['output-key', 'path.to.other.value'],
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
var EXIF_FORMAT =
|
||||||
|
module.EXIF_FORMAT = {
|
||||||
|
// camera / lens...
|
||||||
|
'image.Make': 'make',
|
||||||
|
'image.Model': 'cameraModelName',
|
||||||
|
'image.Software': 'software',
|
||||||
|
'exif.LensModel': 'lensModel',
|
||||||
|
|
||||||
|
// exposure...
|
||||||
|
'exif.ISO': 'iso',
|
||||||
|
'exif.FNumber': ['fNumber',
|
||||||
|
function(v){ return 'f/'+v }],
|
||||||
|
'exif.ExposureTime': ['exposureTime',
|
||||||
|
// NOTE: this is a bit of a brute-fore approach but for shutter
|
||||||
|
// speeds this should not matter...
|
||||||
|
function(v){
|
||||||
|
if(v > 0.5){
|
||||||
|
return ''+ v }
|
||||||
|
for(var d = 1; (v * d) % 1 != 0; d++){}
|
||||||
|
return (v * d) +'/'+ d }],
|
||||||
|
|
||||||
|
// dates...
|
||||||
|
'exif.DateTimeOriginal': ['date/timeOriginal',
|
||||||
|
function(v){
|
||||||
|
return v.toShortDate() }],
|
||||||
|
'image.ModifyDate': ['modifyDate',
|
||||||
|
'exif.DateTimeOriginal'],
|
||||||
|
|
||||||
|
// IPCT...
|
||||||
|
'image.Artist': 'artist',
|
||||||
|
'image.Copyright': 'copyright',
|
||||||
|
|
||||||
|
// XXX anything else???
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var exifReader2exiftool =
|
||||||
|
module.exifReader2exiftool =
|
||||||
|
function(data){
|
||||||
|
return Object.entries(EXIF_FORMAT)
|
||||||
|
// handle exif/image/...
|
||||||
|
.reduce(function(res, [path, to]){
|
||||||
|
var handler
|
||||||
|
;[to, handler] = to instanceof Array ?
|
||||||
|
to
|
||||||
|
: [to]
|
||||||
|
// resolve handler reference/alias...
|
||||||
|
while(typeof(handler) == typeof('str')){
|
||||||
|
handler = EXIF_FORMAT[handler][1] }
|
||||||
|
// resolve source path...
|
||||||
|
var value = path.split(/\./g)
|
||||||
|
.reduce(function(res, e){
|
||||||
|
return res && res[e] }, data)
|
||||||
|
// set the value...
|
||||||
|
if(value !== undefined){
|
||||||
|
res[to] = handler ?
|
||||||
|
handler(value)
|
||||||
|
: value }
|
||||||
|
return res }, {})
|
||||||
|
// handle xmp...
|
||||||
|
.run(function(){
|
||||||
|
var rating = data.xmp
|
||||||
|
// NOTE: we do not need the full XML
|
||||||
|
// fluff here, just get some values...
|
||||||
|
&& parseInt(
|
||||||
|
(data.xmp.toString()
|
||||||
|
.match(/(?<match><(xmp:Rating)[^>]*>(?<value>.*)<\/\2>)/i)
|
||||||
|
|| {groups: {}})
|
||||||
|
.groups.value)
|
||||||
|
rating
|
||||||
|
&& (this.rating = rating) }) }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -423,9 +514,10 @@ var SharpActions = actions.Actions({
|
|||||||
.flat()) }],
|
.flat()) }],
|
||||||
|
|
||||||
|
|
||||||
// XXX should this update all images or just the ones that have no metadata???
|
// XXX add support for offloading the processing to a thread/worker...
|
||||||
// XXX would be nice to be able to abort this...
|
// XXX would be nice to be able to abort this...
|
||||||
// ...and/or have a generic abort protocol triggered when loading...
|
// ...and/or have a generic abort protocol triggered when loading...
|
||||||
|
// ...use task queue???
|
||||||
// XXX make each section optional...
|
// XXX make each section optional...
|
||||||
// XXX revise name...
|
// XXX revise name...
|
||||||
cacheImageMetadata: ['- Sharp|Image/',
|
cacheImageMetadata: ['- Sharp|Image/',
|
||||||
@ -498,6 +590,20 @@ var SharpActions = actions.Actions({
|
|||||||
img.orientation = o.orientation || 0
|
img.orientation = o.orientation || 0
|
||||||
img.flipped = o.flipped
|
img.flipped = o.flipped
|
||||||
|
|
||||||
|
// read the metadata...
|
||||||
|
var exif = metadata.exif
|
||||||
|
&& exifReader(metadata.exif)
|
||||||
|
exif
|
||||||
|
&& Object.assign(
|
||||||
|
(img.metadata = img.metadata || {}),
|
||||||
|
exifReader2exiftool(exif),
|
||||||
|
// mark metadata as partial read...
|
||||||
|
//
|
||||||
|
// NOTE: partial metadata will get reread by
|
||||||
|
// the metadata feature upon request...
|
||||||
|
// XXX revise name...
|
||||||
|
{ ImageGridPartialMetadata: true })
|
||||||
|
|
||||||
// if image too large, generate preview(s)...
|
// if image too large, generate preview(s)...
|
||||||
// XXX EXPERIMENTAL...
|
// XXX EXPERIMENTAL...
|
||||||
var size_threshold = that.config['preview-generate-threshold']
|
var size_threshold = that.config['preview-generate-threshold']
|
||||||
@ -513,31 +619,11 @@ var SharpActions = actions.Actions({
|
|||||||
base_path,
|
base_path,
|
||||||
logger) }
|
logger) }
|
||||||
|
|
||||||
// XXX EXIF -- keep compatible with exiftool...
|
|
||||||
// - dates
|
|
||||||
// - camera / lens / ...
|
|
||||||
var exif = metadata.exif
|
|
||||||
&& exifReader(metadata.exif)
|
|
||||||
// XXX
|
|
||||||
|
|
||||||
// xmp:Rating...
|
|
||||||
var rating = metadata.xmp
|
|
||||||
// NOTE: we do not need the full XML
|
|
||||||
// fluff here, just get some values...
|
|
||||||
&& parseInt(
|
|
||||||
(metadata.xmp.toString()
|
|
||||||
.match(/(?<match><(xmp:Rating)[^>]*>(?<value>.*)<\/\2>)/i)
|
|
||||||
|| {groups: {}})
|
|
||||||
.groups.value)
|
|
||||||
rating
|
|
||||||
&& (img.metadata = img.metadata || {})
|
|
||||||
&& (img.metadata.rating = rating || 0)
|
|
||||||
|
|
||||||
that.markChanged('images', [gid])
|
that.markChanged('images', [gid])
|
||||||
|
|
||||||
logger && logger.emit('done', gid)
|
logger && logger.emit('done', gid)
|
||||||
|
|
||||||
// update image to use the orientation...
|
// update loaded image to use the orientation...
|
||||||
loaded
|
loaded
|
||||||
&& loaded.has(gid)
|
&& loaded.has(gid)
|
||||||
&& that.ribbons.updateImage(gid)
|
&& that.ribbons.updateImage(gid)
|
||||||
@ -564,9 +650,11 @@ module.Sharp = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
handlers: [
|
handlers: [
|
||||||
/* XXX not sure if we need this...
|
/* XXX not sure if we need this...
|
||||||
|
// XXX this is best done in a thread + needs to be abortable...
|
||||||
['loadImages',
|
['loadImages',
|
||||||
function(){
|
function(){
|
||||||
this.cacheImageMetadata('all', false) }],
|
//this.cacheImageMetadata('all', false) }],
|
||||||
|
this.cacheImageMetadata('all') }],
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
// set orientation if not defined...
|
// set orientation if not defined...
|
||||||
|
|||||||
6
Viewer/package-lock.json
generated
6
Viewer/package-lock.json
generated
@ -1117,9 +1117,9 @@
|
|||||||
"integrity": "sha512-EzT4CP6d6lI8bnknNgT3W8mUQhSVXflO0yPbKD4dKsFcINiC6npjoEBz+8m3VQmWJhc+36pXD4JLwNxUEgzi+Q=="
|
"integrity": "sha512-EzT4CP6d6lI8bnknNgT3W8mUQhSVXflO0yPbKD4dKsFcINiC6npjoEBz+8m3VQmWJhc+36pXD4JLwNxUEgzi+Q=="
|
||||||
},
|
},
|
||||||
"ig-types": {
|
"ig-types": {
|
||||||
"version": "2.0.21",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ig-types/-/ig-types-2.0.21.tgz",
|
"resolved": "https://registry.npmjs.org/ig-types/-/ig-types-3.0.1.tgz",
|
||||||
"integrity": "sha512-s+Hu9MU50iohoS/5SUwuoS+P2EHk7Z2zKx9wX3syiBsaL9HYq8g/0Yp/4yz9JkME1zpbS8r9aviR0O2rjBXwHQ==",
|
"integrity": "sha512-oa0Tq+LFyy/2SoQHfhRoa39AtttslJFm95FaF7wH5FNcjxRn3dJ/C/4LscXIoeGaDcXe2DyneVIPNnvg8IOsNw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ig-object": "^5.2.8",
|
"ig-object": "^5.2.8",
|
||||||
"object-run": "^1.0.1"
|
"object-run": "^1.0.1"
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
"ig-argv": "^2.15.0",
|
"ig-argv": "^2.15.0",
|
||||||
"ig-features": "^3.4.2",
|
"ig-features": "^3.4.2",
|
||||||
"ig-object": "^5.2.8",
|
"ig-object": "^5.2.8",
|
||||||
"ig-types": "^2.0.21",
|
"ig-types": "^3.0.1",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"object-run": "^1.0.1",
|
"object-run": "^1.0.1",
|
||||||
"requirejs": "^2.3.6",
|
"requirejs": "^2.3.6",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user