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:
Alex A. Naanou 2013-07-08 01:59:30 +04:00
parent efbdac7e9d
commit 37d89854b8
4 changed files with 190 additions and 34 deletions

View File

@ -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,

View File

@ -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)
}) })

View File

@ -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 = {}

View File

@ -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 : */