diff --git a/buildcache.py b/buildcache.py index 8c14338a..617b1829 100755 --- a/buildcache.py +++ b/buildcache.py @@ -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, diff --git a/ui/compatibility.js b/ui/compatibility.js index 616d34e9..24557a47 100755 --- a/ui/compatibility.js +++ b/ui/compatibility.js @@ -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) }) diff --git a/ui/data.js b/ui/data.js index 9e299189..5013f9d7 100755 --- a/ui/data.js +++ b/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 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 = {} diff --git a/ui/files.js b/ui/files.js index ab0ad52e..b687ba35 100755 --- a/ui/files.js +++ b/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 : */