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'''
__sub_version__ = '''20130706023530'''
__sub_version__ = '''20130707233437'''
__copyright__ = '''(c) Alex A. Naanou 2011'''
@ -311,7 +311,7 @@ def build_images(path, config=CONFIG, gid_generator=hash_gid, verbosity=0):
8: 270,
}[orientation],
'flipped': {
0: 0,
0: None,
1: None,
2: ['horizontal'],
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...
//
// possible modes:
@ -147,10 +195,9 @@ if(window.CEF_dumpJSON != null){
// NOTE: rscale should be used for exactly tuned preview sizes...
// 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 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
var img = IMAGES[gid]
@ -172,26 +219,7 @@ if(window.CEF_dumpJSON != null){
cache_path = cache_path.replace(fp, '')
// get cur image size...
var size_getter = $.Deferred()
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))
})
var size_getter = _getImageSize('max', source)
for(var i=0; i < sizes.length; 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
// invocations, usually the later ones...
var _f = function(size, target_path, deferred){
[function(size, target_path, deferred){
// wait for current image size if needed...
size_getter.done(function(source_size){
@ -255,8 +283,8 @@ if(window.CEF_dumpJSON != null){
// XXX make this compatible with other image processors...
var cmd = 'vips im_shrink "$IN:$RSCALE" "$OUT:$COMPRESSION" $FACTOR $FACTOR'
.replace(/\$RSCALE/g, rscale)
.replace(/\$IN/g, source.replace(fp, ''))
.replace(/\$RSCALE/g, rscale)
.replace(/\$OUT/g, preview_path)
.replace(/\$COMPRESSION/g, compression)
.replace(/\$FACTOR/g, factor)
@ -288,16 +316,38 @@ if(window.CEF_dumpJSON != null){
})
})
})
}
// 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)
}(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
// Queued version of makeImagesPreviews(...)
//
// XXX is this robust enough???
// of one deferred hangs or breaks without finalizing this will
// 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
// clearing the "log" of previous operations, unless keep_log
// 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 = []
$.each(gids, function(i, e){
@ -329,7 +380,7 @@ if(window.CEF_dumpJSON != null){
// append to deffered queue...
last.always(function(){
makeImagePreviews(e, null, mode)
makeImagePreviews(e, sizes, mode)
.progress(function(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 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...
//
// NOTE: changing a base URL will trigger a baseURLChanged event...
@ -410,6 +439,7 @@ function setBaseURL(url){
url = url.replace(/\/*$/, '/')
BASE_URL = url
$('.viewer').trigger('baseURLChanged', [old_url, url])
return url
}
function getBaseURL(){
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
@ -608,6 +648,8 @@ function updateRibbonOrder(no_reload_viewer){
// Construct an IMAGES object from list of urls.
//
// 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){
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 : */