mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-30 02:40:08 +00:00
read orientation from file (via vips) and several improvements to preview loading/creating, needs revision and tuning...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
efbdac7e9d
commit
37d89854b8
@ -1,7 +1,7 @@
|
|||||||
#=======================================================================
|
#=======================================================================
|
||||||
|
|
||||||
__version__ = '''0.0.01'''
|
__version__ = '''0.0.01'''
|
||||||
__sub_version__ = '''20130706023530'''
|
__sub_version__ = '''20130707233437'''
|
||||||
__copyright__ = '''(c) Alex A. Naanou 2011'''
|
__copyright__ = '''(c) Alex A. Naanou 2011'''
|
||||||
|
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ def build_images(path, config=CONFIG, gid_generator=hash_gid, verbosity=0):
|
|||||||
8: 270,
|
8: 270,
|
||||||
}[orientation],
|
}[orientation],
|
||||||
'flipped': {
|
'flipped': {
|
||||||
0: 0,
|
0: None,
|
||||||
1: None,
|
1: None,
|
||||||
2: ['horizontal'],
|
2: ['horizontal'],
|
||||||
3: None,
|
3: None,
|
||||||
|
|||||||
@ -125,6 +125,54 @@ if(window.CEF_dumpJSON != null){
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX this uses vips...
|
||||||
|
// XXX handle errors...
|
||||||
|
// NOTE: source can be either gid or a path...
|
||||||
|
window._getImageSize = function(dimension, source){
|
||||||
|
if(source in IMAGES){
|
||||||
|
var img = IMAGES[gid]
|
||||||
|
var source = normalizePath(img.path)
|
||||||
|
}
|
||||||
|
var getter = $.Deferred()
|
||||||
|
if(dimension == 'max' || dimension == 'min'){
|
||||||
|
$.when(
|
||||||
|
_getImageSize('width', source),
|
||||||
|
_getImageSize('height', source))
|
||||||
|
.done(function(w, h){
|
||||||
|
getter.resolve(Math[dimension](w, h))
|
||||||
|
})
|
||||||
|
|
||||||
|
} else if(dimension == 'width' || dimension == 'height') {
|
||||||
|
var cmd = 'vips im_header_int $DIM "$IN"'
|
||||||
|
.replace(/\$IN/g, source.replace(fp, ''))
|
||||||
|
.replace(/\$DIM/g, dimension)
|
||||||
|
proc.exec(cmd, function(error, stdout, stderr){
|
||||||
|
getter.resolve(parseInt(stdout.trim()))
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// wrong dimension...
|
||||||
|
return getter.reject('unknown dimension:' + dimension)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getter
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: source can be either gid or a path...
|
||||||
|
window.getImageOrientation = function(source){
|
||||||
|
if(source in IMAGES){
|
||||||
|
var img = IMAGES[source]
|
||||||
|
var source = normalizePath(img.path)
|
||||||
|
}
|
||||||
|
var getter = $.Deferred()
|
||||||
|
var cmd = 'vips im_header_string exif-ifd0-Orientation "$IN"'
|
||||||
|
.replace(/\$IN/g, source.replace(fp, ''))
|
||||||
|
proc.exec(cmd, function(error, stdout, stderr){
|
||||||
|
getter.resolve(orientationExif2ImageGrid(parseInt(stdout.trim())))
|
||||||
|
})
|
||||||
|
return getter
|
||||||
|
}
|
||||||
|
|
||||||
// preview generation...
|
// preview generation...
|
||||||
//
|
//
|
||||||
// possible modes:
|
// possible modes:
|
||||||
@ -147,10 +195,9 @@ if(window.CEF_dumpJSON != null){
|
|||||||
// NOTE: rscale should be used for exactly tuned preview sizes...
|
// NOTE: rscale should be used for exactly tuned preview sizes...
|
||||||
// NOTE: this will add already existing previews to IMAGES[gid]...
|
// NOTE: this will add already existing previews to IMAGES[gid]...
|
||||||
//
|
//
|
||||||
// XXX get image size without loading the image...
|
|
||||||
// XXX make this not just vips-specific...
|
// XXX make this not just vips-specific...
|
||||||
// XXX path handling is a mess...
|
// XXX path handling is a mess...
|
||||||
window.makeImagePreviews = function(gid, sizes, mode){
|
window.makeImagePreviews = function(gid, sizes, mode, no_update_loaded){
|
||||||
mode = mode == null ? 'optimized' : mode
|
mode = mode == null ? 'optimized' : mode
|
||||||
|
|
||||||
var img = IMAGES[gid]
|
var img = IMAGES[gid]
|
||||||
@ -172,26 +219,7 @@ if(window.CEF_dumpJSON != null){
|
|||||||
cache_path = cache_path.replace(fp, '')
|
cache_path = cache_path.replace(fp, '')
|
||||||
|
|
||||||
// get cur image size...
|
// get cur image size...
|
||||||
var size_getter = $.Deferred()
|
var size_getter = _getImageSize('max', source)
|
||||||
|
|
||||||
var width_getter = $.Deferred()
|
|
||||||
var cmd = 'vips im_header_int width "$IN"'
|
|
||||||
.replace(/\$IN/g, source.replace(fp, ''))
|
|
||||||
proc.exec(cmd, function(error, stdout, stderr){
|
|
||||||
width_getter.resolve(parseInt(stdout.trim()))
|
|
||||||
})
|
|
||||||
var height_getter = $.Deferred()
|
|
||||||
var cmd = 'vips im_header_int height "$IN"'
|
|
||||||
.replace(/\$IN/g, source.replace(fp, ''))
|
|
||||||
proc.exec(cmd, function(error, stdout, stderr){
|
|
||||||
height_getter.resolve(parseInt(stdout.trim()))
|
|
||||||
})
|
|
||||||
|
|
||||||
$.when(width_getter, height_getter)
|
|
||||||
.done(function(w, h){
|
|
||||||
size_getter.resolve(Math.max(w, h))
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
for(var i=0; i < sizes.length; i++){
|
for(var i=0; i < sizes.length; i++){
|
||||||
var size = sizes[i]
|
var size = sizes[i]
|
||||||
@ -207,7 +235,7 @@ if(window.CEF_dumpJSON != null){
|
|||||||
// }(...))
|
// }(...))
|
||||||
// produces a "undefined is not a function" in part of the
|
// produces a "undefined is not a function" in part of the
|
||||||
// invocations, usually the later ones...
|
// invocations, usually the later ones...
|
||||||
var _f = function(size, target_path, deferred){
|
[function(size, target_path, deferred){
|
||||||
// wait for current image size if needed...
|
// wait for current image size if needed...
|
||||||
size_getter.done(function(source_size){
|
size_getter.done(function(source_size){
|
||||||
|
|
||||||
@ -255,8 +283,8 @@ if(window.CEF_dumpJSON != null){
|
|||||||
|
|
||||||
// XXX make this compatible with other image processors...
|
// XXX make this compatible with other image processors...
|
||||||
var cmd = 'vips im_shrink "$IN:$RSCALE" "$OUT:$COMPRESSION" $FACTOR $FACTOR'
|
var cmd = 'vips im_shrink "$IN:$RSCALE" "$OUT:$COMPRESSION" $FACTOR $FACTOR'
|
||||||
.replace(/\$RSCALE/g, rscale)
|
|
||||||
.replace(/\$IN/g, source.replace(fp, ''))
|
.replace(/\$IN/g, source.replace(fp, ''))
|
||||||
|
.replace(/\$RSCALE/g, rscale)
|
||||||
.replace(/\$OUT/g, preview_path)
|
.replace(/\$OUT/g, preview_path)
|
||||||
.replace(/\$COMPRESSION/g, compression)
|
.replace(/\$COMPRESSION/g, compression)
|
||||||
.replace(/\$FACTOR/g, factor)
|
.replace(/\$FACTOR/g, factor)
|
||||||
@ -288,16 +316,38 @@ if(window.CEF_dumpJSON != null){
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}(size, target_path, deferred)]
|
||||||
// NOTE: wrapping this in a closure saves the specific data that would
|
|
||||||
// otherwise be overwritten by the next loop iteration...
|
|
||||||
_f(size, target_path, deferred)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $.when.apply(null, previews)
|
var res = $.when.apply(null, previews)
|
||||||
|
|
||||||
|
// update loaded images...
|
||||||
|
if(!no_update_loaded){
|
||||||
|
res.done(function(){
|
||||||
|
var o = getImage(gid)
|
||||||
|
if(o.length > 0){
|
||||||
|
updateImage(o)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX needs more testing...
|
||||||
|
// - for some reason this is a bit slower than the queued version
|
||||||
|
// ...in spite of being managed by node.js
|
||||||
|
// - will this be faster on SMP/multi-core?
|
||||||
|
window.makeImagesPreviews = function(gids, sizes, mode){
|
||||||
|
gids = gids == null ? getClosestGIDs() : gids
|
||||||
|
return $.when.apply(null, gids.map(function(gid){
|
||||||
|
return makeImagePreviews(gid, sizes, mode)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
window._PREVIW_CREATE_QUEUE = null
|
window._PREVIW_CREATE_QUEUE = null
|
||||||
|
// Queued version of makeImagesPreviews(...)
|
||||||
|
//
|
||||||
// XXX is this robust enough???
|
// XXX is this robust enough???
|
||||||
// of one deferred hangs or breaks without finalizing this will
|
// of one deferred hangs or breaks without finalizing this will
|
||||||
// stall the whole queue...
|
// stall the whole queue...
|
||||||
@ -308,7 +358,8 @@ if(window.CEF_dumpJSON != null){
|
|||||||
// NOTE: this will remove the old deferred if it us resolved, thus
|
// NOTE: this will remove the old deferred if it us resolved, thus
|
||||||
// clearing the "log" of previous operations, unless keep_log
|
// clearing the "log" of previous operations, unless keep_log
|
||||||
// is set to true...
|
// is set to true...
|
||||||
window.makeImagesPreviewsQ = function(gids, keep_log, mode){
|
window.makeImagesPreviewsQ = function(gids, sizes, mode, keep_log){
|
||||||
|
gids = gids == null ? getClosestGIDs() : gids
|
||||||
var previews = []
|
var previews = []
|
||||||
|
|
||||||
$.each(gids, function(i, e){
|
$.each(gids, function(i, e){
|
||||||
@ -329,7 +380,7 @@ if(window.CEF_dumpJSON != null){
|
|||||||
|
|
||||||
// append to deffered queue...
|
// append to deffered queue...
|
||||||
last.always(function(){
|
last.always(function(){
|
||||||
makeImagePreviews(e, null, mode)
|
makeImagePreviews(e, sizes, mode)
|
||||||
.progress(function(state){
|
.progress(function(state){
|
||||||
deferred.notify(state)
|
deferred.notify(state)
|
||||||
})
|
})
|
||||||
|
|||||||
44
ui/data.js
44
ui/data.js
@ -191,7 +191,7 @@ function makeImageGIDDistanceCmp(gid, get, order){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE: essentially this is a 2D distance compatison from gid...
|
// NOTE: essentially this is a 2D distance comparison from gid...
|
||||||
//
|
//
|
||||||
// XXX make this faster...
|
// XXX make this faster...
|
||||||
// XXX this is fun, but do we actually need this?
|
// XXX this is fun, but do we actually need this?
|
||||||
@ -402,6 +402,35 @@ Array.prototype.binSearch = function(target, cmp, get){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Orientation transaltion...
|
||||||
|
function orientationExif2ImageGrid(orientation){
|
||||||
|
return {
|
||||||
|
orientation: {
|
||||||
|
0: 0,
|
||||||
|
1: 0,
|
||||||
|
2: 0,
|
||||||
|
3: 180,
|
||||||
|
4: 0,
|
||||||
|
5: 90,
|
||||||
|
6: 90,
|
||||||
|
7: 90,
|
||||||
|
8: 270,
|
||||||
|
}[orientation],
|
||||||
|
flipped: {
|
||||||
|
0: null,
|
||||||
|
1: null,
|
||||||
|
2: ['horizontal'],
|
||||||
|
3: null,
|
||||||
|
4: ['vertical'],
|
||||||
|
5: ['vertical'],
|
||||||
|
6: null,
|
||||||
|
7: ['horizontal'],
|
||||||
|
8: null,
|
||||||
|
}[orientation]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Base URL interface...
|
// Base URL interface...
|
||||||
//
|
//
|
||||||
// NOTE: changing a base URL will trigger a baseURLChanged event...
|
// NOTE: changing a base URL will trigger a baseURLChanged event...
|
||||||
@ -410,6 +439,7 @@ function setBaseURL(url){
|
|||||||
url = url.replace(/\/*$/, '/')
|
url = url.replace(/\/*$/, '/')
|
||||||
BASE_URL = url
|
BASE_URL = url
|
||||||
$('.viewer').trigger('baseURLChanged', [old_url, url])
|
$('.viewer').trigger('baseURLChanged', [old_url, url])
|
||||||
|
return url
|
||||||
}
|
}
|
||||||
function getBaseURL(){
|
function getBaseURL(){
|
||||||
return BASE_URL
|
return BASE_URL
|
||||||
@ -600,6 +630,16 @@ function updateRibbonOrder(no_reload_viewer){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get list of gids sorted by proximity to current gid
|
||||||
|
//
|
||||||
|
// NOTE: the distance used is the actual 2D distance...
|
||||||
|
function getClosestGIDs(gid){
|
||||||
|
gid = gid == null ? getImageGID() : gid
|
||||||
|
//return DATA.order.slice().sort(makeImageGIDDistanceCmp(gid))
|
||||||
|
return DATA.order.slice().sort(makeImageRibbonDistanceCmp(gid))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Constructors
|
* Constructors
|
||||||
@ -608,6 +648,8 @@ function updateRibbonOrder(no_reload_viewer){
|
|||||||
// Construct an IMAGES object from list of urls.
|
// Construct an IMAGES object from list of urls.
|
||||||
//
|
//
|
||||||
// NOTE: this depends on that the base dir contains ALL the images...
|
// NOTE: this depends on that the base dir contains ALL the images...
|
||||||
|
// NOTE: if base is not given, this will not read image to get
|
||||||
|
// orientation data...
|
||||||
function imagesFromUrls(lst){
|
function imagesFromUrls(lst){
|
||||||
var res = {}
|
var res = {}
|
||||||
|
|
||||||
|
|||||||
63
ui/files.js
63
ui/files.js
@ -634,5 +634,68 @@ function exportTo(path, im_name, dir_name, size){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
|
||||||
|
// XXX this depends on getImageOrientation(...)
|
||||||
|
function updateImageOrientation(gid, no_update_loaded){
|
||||||
|
gid = gid == null ? getImageGID() : gid
|
||||||
|
var img = IMAGES[gid]
|
||||||
|
|
||||||
|
return getImageOrientation(normalizePath(img.path))
|
||||||
|
.done(function(o){
|
||||||
|
img.orientation = o.orientation
|
||||||
|
img.flipped = o.flipped
|
||||||
|
|
||||||
|
// update loaded images...
|
||||||
|
if(!no_update_loaded){
|
||||||
|
var o = getImage(gid)
|
||||||
|
if(o.length > 0){
|
||||||
|
updateImage(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function updateImagesOrientation(gids, no_update_loaded){
|
||||||
|
gids = gids == null ? getClosestGIDs() : gids
|
||||||
|
var res = []
|
||||||
|
|
||||||
|
$.each(gids, function(_, gid){
|
||||||
|
res.push(updateImageOrientation(gid, no_update_loaded))
|
||||||
|
})
|
||||||
|
|
||||||
|
return $.when.apply(null, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// queued version of updateImagesOrientation(...)
|
||||||
|
function updateImagesOrientationQ(gids, no_update_loaded){
|
||||||
|
gids = gids == null ? getClosestGIDs() : gids
|
||||||
|
var res = []
|
||||||
|
|
||||||
|
if(window.getImageOrientation == null){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var last = $.Deferred().resolve()
|
||||||
|
|
||||||
|
$.each(gids, function(_, gid){
|
||||||
|
var cur = $.Deferred()
|
||||||
|
last.done(function(){
|
||||||
|
last = updateImageOrientation(gid, no_update_loaded)
|
||||||
|
.done(function(o){
|
||||||
|
cur.resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
res.push(cur)
|
||||||
|
})
|
||||||
|
|
||||||
|
return $.when.apply(null, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* vim:set ts=4 sw=4 : */
|
* vim:set ts=4 sw=4 : */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user