added bulk data tags import/export from/to images + some plyfils...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2014-12-07 16:58:06 +03:00
parent 555ac6ec85
commit 4e44480c1f
3 changed files with 185 additions and 2 deletions

View File

@ -231,7 +231,7 @@ var DataPrototype = {
}
gids.forEach(function(e){
i = order.indexOf(e)
var i = order.indexOf(e)
if(i >= 0){
var o = target[i]
// save overwritten target items if keep_target_items
@ -2284,6 +2284,154 @@ var DataWithTagsPrototype = {
// ....is there a way not to say DataPrototype here???
__gid_lists: DataPrototype.__gid_lists.concat(['tags']),
// Load tags from images...
//
// Merge image tags to data...
// .tagsFromImages(images)
// -> data
//
// Load image tags to data dropping any changes in data...
// .tagsFromImages(images, 'reset')
// -> data
//
// XXX should this be here???
// XXX this depend on image structure...
tagsFromImages: function(images, mode){
if(mode == 'reset'){
this.tags = {}
}
for(var gid in images){
var img = images[gid]
if(img.tags != null){
this.tag(img.tags, gid)
}
}
return this
.sortTags()
},
// Transfer tags to images...
//
// Merge data tags to images...
// .tagsToImages(images)
// .tagsToImages(images, true)
// .tagsToImages(images, 'merge')
// -> data
//
// Merge data tags to images without buffering...
// .tagsToImages(images, 'unbuffered')
// -> data
//
// Reset image tags from data...
// .tagsToImages(images, 'rest')
// -> data
//
// XXX should this be here???
// XXX this depend on image structure...
// XXX should this use image API for creating images???
tagsToImages: function(images, mode, updated){
mode = mode || 'merge'
updated = updated || []
// mark gid as updated...
var _updated = function(gid){
if(updated != null && updated.indexOf(gid) < 0){
updated.push(gid)
}
}
// get or create an image with tags...
// XXX should this use image API for creating???
var _get = function(images, gid){
var img = images[gid]
// create a new image...
if(img == null){
img = images[gid] = {}
_updated(gid)
}
var tags = img.tags
// no prior tags...
if(tags == null){
tags = img.tags = []
_updated(gid)
}
return img
}
// buffered mode...
// - uses more memory
// + one write mer image
if(mode != 'unbuffered'){
// build the buffer...
var buffer = {}
this.tagsToImages(buffer, 'unbuffered')
// reset mode...
if(mode == 'reset'){
// iterate through all the gids (both images and buffer/data)
for(var gid in Object.keys(images)
.concat(Object.keys(buffer))
.unique()){
// no tags / remove...
if(buffer[gid] == null || buffer[gid].tags.length == 0){
// the image exists and has tags...
if(images[gid] != null && images[gid].tags != null){
delete images[gid].tags
_updated(gid)
}
// tags / set...
} else {
var img = _get(images, gid)
var before = img.tags.slice()
img.tags = buffer[gid].tags
// check if we actually changed anything...
if(!before.setCmp(img.tags)){
_updated(gid)
}
}
}
// merge mode...
} else {
for(var gid in buffer){
var img = _get(images, gid)
var l = img.tags.length
img.tags = img.tags.concat(buffer[gid].tags).unique()
// we are updated iff length changed...
// NOTE: this is true as we are not removing anything
// thus the length can only increase if changes are
// made...
if(l != img.tags.length){
_updated(gid)
}
}
}
// unbuffered (brain-dead) mode...
// + no extra memory
// - multiple writes per image (one per tag)
} else {
var tagset = this.tags
for(var tag in tagset){
tagset[tag].forEach(function(gid){
var img = _get(images, gid)
if(img.tags.indexOf(tag) < 0){
img.tags.push(tag)
_updated(gid)
}
})
}
}
return this
},
// NOTE: this is here only to make the tags mutable...
crop: function(){
var crop = DataWithTagsPrototype.__proto__.crop.apply(this, arguments)

View File

@ -222,7 +222,8 @@ module.FeatureSet = {
var l = lst.length
lst = lst
// remove duplicates, keeping only the first occurance...
.filter(function(e, i, l){ return l.indexOf(e) == i })
//.filter(function(e, i, l){ return l.indexOf(e) == i })
.unique()
// remove undefined features...
.filter(function(e){ return that[e] != null })
// build the sort table: [ <priority>, <rev-index>, <elem> ]

View File

@ -1335,6 +1335,40 @@ Array.prototype.compact = function(){
}
// return an array with duplicate elements removed...
//
Array.prototype.unique = function(){
return this.filter(function(e, i, a){ return a.indexOf(e) == i })
}
// Compare two arrays...
//
Array.prototype.cmp = function(other){
if(this === other){
return true
}
if(this.length != other.length){
return false
}
for(var i=0; i<this.length; i++){
if(this[i] != other[i]){
return false
}
}
return true
}
// Compare two Arrays as sets...
//
// This will ignore order
Array.prototype.setCmp = function(other){
return this === other
|| this.unique().sort().cmp(other.unique().sort())
}
// like .length but for sparse arrays will return the element count...
// XXX make this a prop...
/*