diff --git a/.gitignore b/.gitignore
index fc44ca6bd9f25d424b42fa24b1505899302a05d8..b9e5d43c8e464c07ca07e278fec9dbef7e83e52d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
 **/sol_*.js
 **/sol_*.html
+**/old*
+**/.DS_Store
diff --git a/data/16_02.JPG b/data/16_02.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..ed3a652cd660ddd9ad3414cc023c4fd8fdf51ca3
Binary files /dev/null and b/data/16_02.JPG differ
diff --git a/data/16_03.JPG b/data/16_03.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..567d529d5cfc909c21e14215db2412bf0feab849
Binary files /dev/null and b/data/16_03.JPG differ
diff --git a/data/16_04.JPG b/data/16_04.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..8144088eb781b9d3fb898bcc5207df66fa311cc6
Binary files /dev/null and b/data/16_04.JPG differ
diff --git a/data/16_05.JPG b/data/16_05.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..58a3a4125e4c59ef695fa51527121b8a12dbfa4f
Binary files /dev/null and b/data/16_05.JPG differ
diff --git a/data/16_06.JPG b/data/16_06.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..714a887141bfb91311d09d7627477e8a175d68c0
Binary files /dev/null and b/data/16_06.JPG differ
diff --git a/data/16_07.JPG b/data/16_07.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..cfeb0f786b81c458f977f5306ad8fb3a96f3317a
Binary files /dev/null and b/data/16_07.JPG differ
diff --git a/data/16_08.JPG b/data/16_08.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..1b575a2d9a0cfd92339af09f83a36fae167842a4
Binary files /dev/null and b/data/16_08.JPG differ
diff --git a/data/16_09.JPG b/data/16_09.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..d783241ed401d910ed9462a4f285082a6ab84dea
Binary files /dev/null and b/data/16_09.JPG differ
diff --git a/data/16_10.JPG b/data/16_10.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..7b9c6b9e60d3b1c6afe52f49669dbf92256a8fcf
Binary files /dev/null and b/data/16_10.JPG differ
diff --git a/data/16_11.JPG b/data/16_11.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..2e06317b1e860fccc943d9949d02262bcaff1412
Binary files /dev/null and b/data/16_11.JPG differ
diff --git a/data/16_12.JPG b/data/16_12.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..9fafb4d74c9bc2af927043fcb32930d4372ea606
Binary files /dev/null and b/data/16_12.JPG differ
diff --git a/data/16_13.JPG b/data/16_13.JPG
new file mode 100644
index 0000000000000000000000000000000000000000..b7c7b5017538ac25ffdafd0ca3dff00539abf7aa
Binary files /dev/null and b/data/16_13.JPG differ
diff --git a/data/I1.png b/data/I1.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a74690a129640bab53f072efc2b19c59198ae23
Binary files /dev/null and b/data/I1.png differ
diff --git a/data/I2.png b/data/I2.png
new file mode 100644
index 0000000000000000000000000000000000000000..c30b6ade5df09e8e65741a76ae35d38167e782a1
Binary files /dev/null and b/data/I2.png differ
diff --git a/data/I3.png b/data/I3.png
new file mode 100644
index 0000000000000000000000000000000000000000..775d0d2e8daffc9153a73186585d19aa3e9a4224
Binary files /dev/null and b/data/I3.png differ
diff --git a/data/I4.png b/data/I4.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f516d07fb86f460bce173be32b375f02cc361a1
Binary files /dev/null and b/data/I4.png differ
diff --git a/data/I5.png b/data/I5.png
new file mode 100644
index 0000000000000000000000000000000000000000..48ae0aba6e3afeb44d5d0cf998a0c0238ad57495
Binary files /dev/null and b/data/I5.png differ
diff --git a/data/I6.png b/data/I6.png
new file mode 100644
index 0000000000000000000000000000000000000000..0a8dd95e11942fc1e688a2d543ddccb98925bf3f
Binary files /dev/null and b/data/I6.png differ
diff --git a/data/I7.png b/data/I7.png
new file mode 100644
index 0000000000000000000000000000000000000000..b874a94dd053bd91e30c529ad776de021cd27d66
Binary files /dev/null and b/data/I7.png differ
diff --git a/data/I8.png b/data/I8.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b9710eda7e7ace2254bd83a4c623e2dda4d9fc7
Binary files /dev/null and b/data/I8.png differ
diff --git a/data/ii2d.png b/data/ii2d.png
new file mode 100644
index 0000000000000000000000000000000000000000..0a5cd802446f410c52168be74a31004a245ef706
Binary files /dev/null and b/data/ii2d.png differ
diff --git a/data/red.png b/data/red.png
new file mode 100644
index 0000000000000000000000000000000000000000..3353a820f9451ee0ff1170ecff2890a7c0ce1aa4
Binary files /dev/null and b/data/red.png differ
diff --git a/dataset/images.js b/dataset/images.js
new file mode 100644
index 0000000000000000000000000000000000000000..733ab76cfb6f2619c252cf0def0cc148e68e6ec2
--- /dev/null
+++ b/dataset/images.js
@@ -0,0 +1,51 @@
+var datasets={}
+
+/*
+  datasets.ImageDataset
+  - constructs a collection of images (this.imageDatas) based on image_ids
+  - ALL IMAGES SHOULD HAVE THE SAME WIDTH and HEIGHT
+  - it exports this.imageDatas and this.image_ids for accessing image information
+*/
+datasets.ImageDataset=function(image_ids){
+  this.image_ids=image_ids;
+  this.imageDatas=[];
+  for (var idx in this.image_ids) {
+    this.imageDatas[idx]=Tools.get_imageData_from_imgEltId(this.image_ids[idx]);
+  }
+}
+
+/*
+  datasets.ImageDataset
+  - constructs a collection of images (this.imageDatas) for a given imageData,
+    considering various sizes and steps related to floating windows
+  - it exports this.imageDatas and this.image_ids for accessing image information
+  - for debugging reasons, if the containing page has a div id="res",
+    the newly created dataset is displayed
+*/
+datasets.PartsOfImageDataset=function(imageData,sizes_and_steps){
+  if (document.getElementById("res")) {
+    document.getElementById("res").appendChild(document.createTextNode("Candidate windows"));
+    document.getElementById("res").appendChild(document.createElement("br"));
+  }
+  
+  this.imageDatas=[];
+  this.count=0;
+  for (var idx_s in sizes_and_steps) {
+    height=sizes_and_steps[idx_s].height; width=sizes_and_steps[idx_s].width;
+    for (var y=0;y<imageData.height-height;y+=sizes_and_steps[idx_s].y) {
+      for (var x=0;x<imageData.width-width;x+=sizes_and_steps[idx_s].x) {
+        this.imageDatas[this.count]=
+          Tools.get_region_from_imageData(
+              imageData,
+              x,y,width,height);
+
+        if (document.getElementById("res"))
+          document.getElementById("res").appendChild(Tools.create_canvasElt_from_imageData(this.imageDatas[this.count]));
+
+        this.count++;
+      }
+      if (document.getElementById("res"))
+        document.getElementById("res").appendChild(document.createElement("br"));
+    }
+  }
+}
diff --git a/multi/fusion.js b/effects/fusion.js
similarity index 93%
rename from multi/fusion.js
rename to effects/fusion.js
index 0889deb64d72953634cd049109bfb5fdfdefb8ac..6166f3894dc9e27ada598637813b0a297280a65d 100644
--- a/multi/fusion.js
+++ b/effects/fusion.js
@@ -5,7 +5,7 @@ MeanFuseMultiImagesTask.prototype.process_multi=function(imageDatas,fused) {
   for (var y=0;y<fused.height;y++) {
     for (var x=0;x<fused.width;x++) {
       fused.data[w]=0; fused.data[w+1]=0; fused.data[w+2]=0; fused.data[w+3]=0;
-      for (idx in imageDatas) {
+      for (var idx in imageDatas) {
         for (var i=0; i<4; i++) {
           fused.data[w+i]+=imageDatas[idx].data[w+i];
         }
diff --git a/effects/photo_fill.js b/effects/photo_fill.js
new file mode 100644
index 0000000000000000000000000000000000000000..541707f3d99b665192e6c6163e0fb9429314cc07
--- /dev/null
+++ b/effects/photo_fill.js
@@ -0,0 +1,29 @@
+var photo_fill={};
+
+photo_fill.PhotoFillPixelsFromDatasetTask=function(dataset,opt_options){
+  this.dataset=dataset;
+  this.similarity_task=new pixels_similarity.MeanRGBSimilarityTask(_dataset,{});
+;
+}
+
+photo_fill.PhotoFillPixelsFromDatasetTask.prototype.process=function(in_imageData,out_imageData) {
+  var w=0;
+  for (var y=0;y<in_imageData.height;y++) {
+    for (var x=0;x<in_imageData.width;x++,w+=4) {
+      if (in_imageData.data[w+3]==0)
+        continue;
+
+      var rgb_pixel=[in_imageData.data[w],in_imageData.data[w+1],in_imageData.data[w+2]];
+
+      var sim_res=this.similarity_task.process_descriptor(rgb_pixel);
+
+      var min_idx=sim_res[1].idx;
+
+      var pixel_image=this.similarity_task.dataset.imageDatas[min_idx];
+      x_dest=x*pixel_image.width;
+      y_dest=y*pixel_image.height;
+
+      Tools.copy_imageData_into_imageData(pixel_image,out_imageData,x_dest,y_dest);
+    }
+  }
+}
diff --git a/features/generic.js b/features/generic.js
new file mode 100644
index 0000000000000000000000000000000000000000..aaf04c0ae01d95b2007e54ed5d52611f1623d769
--- /dev/null
+++ b/features/generic.js
@@ -0,0 +1,35 @@
+var generic_features={};
+
+/*
+  generic_features.grid_descriptor
+  - generates grid-like descriptors considering for each cell descriptor_func
+  as a descriptor extractor
+  - it requires opt_options.nb_columns and opt_options.nb_lines for grid
+    construction
+  - opt_options may contain other options related to param extraction
+  - on each subsequent cell based descriptor called, x0,y0,dx,dy opt_options
+    are set
+  - it returns a grid object containing grid.nb_columns x grid.nb_lines
+    grid.cells array, where each grid.cells[i] corresponds to
+    the i-th cell descriptor
+*/
+generic_features.grid_descriptor=function(imageData,descriptor_func,opt_options) {
+
+  var grid={};
+  grid.cells=[];
+  grid.nb_columns=opt_options.nb_columns; grid.nb_lines=opt_options.nb_lines;
+  cell_width=imageData.width/grid.nb_columns;
+  cell_height=imageData.height/grid.nb_lines;
+
+  for (var i=0;i<grid.nb_columns;i++)
+    for (var j=0;j<grid.nb_lines; j++) {
+      opt_options.x0=i*cell_width;
+      opt_options.y0=j*cell_height;
+      opt_options.dx=cell_width;
+      opt_options.dy=cell_height;
+      grid.cells.push(
+        descriptor_func(imageData,opt_options)
+        );
+      }
+  return grid;
+}
diff --git a/features/pixels.js b/features/pixels.js
index 755c8f109e931bb609af8711bed380534a852851..d471e620af382abdda1e7f3a7b092472127e88ff 100644
--- a/features/pixels.js
+++ b/features/pixels.js
@@ -1,19 +1,55 @@
-GetPixelRGBATask=function(opt_options) {
-  this.x=opt_options.x;
-  this.y=opt_options.y;
-  this.output=opt_options.output;
+var pixels_features={};
+
+/*
+  pixels_features.mean_rgb
+  - computes RGB mean of all pixels having A>0 within imageData
+*/
+pixels_features.mean_rgb=function(imageData,opt_options) {
+  return pixels_features.mean_rgb_per_region(imageData,{x0:0,y0:0,dx:imageData.width,dy:imageData.height});
 }
 
-GetPixelRGBATask.prototype.process=function(imageData) {
-  var pos=(this.y*imageData.width+this.x)<<2;
-  var r=imageData.data[pos];
-  var g=imageData.data[pos+1];
-  var b=imageData.data[pos+2];
-  var a=imageData.data[pos+3];
+/*
+  pixels_features.mean_rgb_per_region
+  - computes RGB mean of all pixels having A>0 within opt_options.x0 .y0 .dx .dy
+  - if opt_options missing partially,
+      replace partially with defaults 0, 0, imageData.width, imageData.height
+  - returns undefined if none available
+*/
+pixels_features.mean_rgb_per_region=function(imageData,opt_options) {
+  x0=opt_options&&opt_options.x0?opt_options.x0:0;
+  y0=opt_options&&opt_options.y0?opt_options.y0:0;
+  dx=opt_options&&opt_options.dx?opt_options.dx:imageData.width;
+  dy=opt_options&&opt_options.dy?opt_options.dy:imageData.height;
+
+
+  var mean=[];
+  mean[0]=0; mean[1]=0; mean[2]=0;
+  var pos=0; var count=0;
+  for (var y=y0;y<y0+dy;y++)
+    for (var x=x0;x<x0+dx;x++) {
+      pos=(y*imageData.width+x)<<2;
+      if (imageData.data[pos+3]>0) {
+        for (var i=0;i<3;i++) {
+          mean[i]+=imageData.data[pos+i];
+        }
+        count++;
+      }
+    }
+  if (count>0) {
+    for (var i=0;i<3;i++) {
+      mean[i]=Math.round(mean[i]/count);
+    }
+    return mean;
+  }
+  return undefined;
+}
 
-  this.output.innerHTML=this.x+"x"+this.y+" : ";
-  this.output.innerHTML+="<font color='red'>"+r+"</font> | ";
-  this.output.innerHTML+="<font color='green'>"+g+"</font> | ";
-  this.output.innerHTML+="<font color='blue'>"+b+"</font> | ";
-  this.output.innerHTML+="<font color='gray'>"+a+"</font>";
+/*
+  pixels_features.grid_mean_rgb
+  - computes RGB mean of all pixels having A>0 in all grid cells
+  - grid params are defined as opt_options.nb_lines*opt_options.nb_columns
+  - returns a generic_features.grid_descriptor (grid.cells - array)
+*/
+pixels_features.grid_mean_rgb=function(imageData,opt_options) {
+  return generic_features.grid_descriptor(imageData,pixels_features.mean_rgb_per_region,opt_options);
 }
diff --git a/generateHtmlAllImages.sh b/generateHtmlAllImages.sh
new file mode 100644
index 0000000000000000000000000000000000000000..5db76b6ecfb5cc5ffd828eafee0fcc04aa6c4758
--- /dev/null
+++ b/generateHtmlAllImages.sh
@@ -0,0 +1,8 @@
+echo "<html><body>"
+count=1;
+while read img ;
+do 
+echo "<img id='input${count}' src='$img'></img>"
+count=$(( $count + 1 ))
+done
+echo "</body></html>"
diff --git a/lookup/windows.js b/lookup/windows.js
new file mode 100644
index 0000000000000000000000000000000000000000..77c7dd7a6fca736e7bb01f0a7bdc0525892a2f21
--- /dev/null
+++ b/lookup/windows.js
@@ -0,0 +1,41 @@
+var lookup_windows={};
+
+
+lookup_windows.MeanRGBSameSizeTemplate=function(
+  template_imgElt_id,threshold
+) {
+  this.template_imageData=Tools.get_imageData_from_imgEltId(template_imgElt_id);
+  this.threshold=threshold;
+}
+
+lookup_windows.MeanRGBSameSizeTemplate.prototype.process=function(in_imageData) {
+  var lookup_dataset=new datasets.PartsOfImageDataset(
+    in_imageData,
+    sizes_and_steps=
+      [{width:this.template_imageData.width,height:this.template_imageData.height,
+        x:this.template_imageData.width/4,y:this.template_imageData.height/4}]
+  );
+
+  var similarity_task=new pixels_similarity.MeanRGBSimilarityTask(lookup_dataset,{});
+
+  var sim_res=similarity_task.process(this.template_imageData);
+
+  if (document.getElementById("res")) {
+    document.getElementById("res").appendChild(document.createTextNode("Selected windows"));
+    document.getElementById("res").appendChild(document.createElement("br"));
+  }
+  
+  var windows=[];
+  for (idx in sim_res) {
+    if (sim_res[idx].sim>this.threshold)
+      break;
+    sim_imageData=lookup_dataset.imageDatas[sim_res[idx].idx];
+    windows.push({sim:sim_res[idx].sim,idx:sim_res[idx].idx,
+                  x:sim_imageData.orig_x,y:sim_imageData.orig_x,
+                  dx:sim_imageData.width,dy:sim_imageData.height});
+    document.getElementById("res")
+      .appendChild(Tools.create_canvasElt_from_imageData(sim_imageData));
+  }
+
+  return windows;
+}
diff --git a/metrics/generic.js b/metrics/generic.js
new file mode 100644
index 0000000000000000000000000000000000000000..f847b30266ddfd8abb56a07eb8205adddcd006af
--- /dev/null
+++ b/metrics/generic.js
@@ -0,0 +1,26 @@
+var generic_metrics={};
+
+/*
+  generic_metrics.euclidian_distance_btw_feature_vectors
+  - computes the euclidian distance between two feature vectors sharing
+    a common structure
+  - it requires feature_distance_func which computes the distance between
+    individual components of the descriptor
+  - return the euclidian distance in the R^n space,
+    where n is descriptor_array_1.length
+*/
+generic_metrics.euclidian_distance_btw_feature_vectors=function(
+  descriptor_array_1,
+  descriptor_array_2,
+  feature_distance_func) {
+  var sum=0, count=0;
+  for (var idx in descriptor_array_1) {
+    var dist=feature_distance_func(descriptor_array_1[idx],descriptor_array_2[idx]);
+    sum+=dist*dist;
+    count++;
+  }
+  if (count>0) {
+    return Math.sqrt(sum);
+  } else
+    return undefined;
+}
diff --git a/metrics/pixels.js b/metrics/pixels.js
new file mode 100644
index 0000000000000000000000000000000000000000..2a9441cc8e86d627da0cd0027b523e51480a7609
--- /dev/null
+++ b/metrics/pixels.js
@@ -0,0 +1,18 @@
+var pixel_metrics={};
+
+/*
+    pixel_metrics.rgb_edist - computes euclidian distance between two rgb pixels
+*/
+pixel_metrics.rgb_edist=function(pixel_rgb1, pixel_rgb2) {
+  var dist_fun=function(x,y){return x-y};
+  return generic_metrics.euclidian_distance_btw_feature_vectors(pixel_rgb1,pixel_rgb2,dist_fun);
+}
+
+/*
+    pixel_metrics.rgb_edist - computes euclidian distance between two grids
+    containing in each cell an rgb pixel
+*/
+pixel_metrics.grid_rgb_edist=function(pixels_rgb_grid1, pixels_rgb_grid2) {
+  var dist_fun=pixel_metrics.rgb_edist;
+  return generic_metrics.euclidian_distance_btw_feature_vectors(pixels_rgb_grid1.cells,pixels_rgb_grid2.cells,dist_fun);
+}
diff --git a/multi_processing.js b/multi_processing.js
index cafa8dc2e10f3798b1bcf2f6fb5aad9d5b975cfb..94505cd16cd42e53c48814e4886b072c6c4498e8 100644
--- a/multi_processing.js
+++ b/multi_processing.js
@@ -4,7 +4,7 @@ var multi_processing=function(elementIds,task_multi,outputCanvasId) {
   this.processing_canvas=[]; this.processing_context=[];
   this.imageDatas=[];
   var lastCanvasElt={};
-  for (idx in elementIds) {
+  for (var idx in elementIds) {
 
     this.element[idx]=document.getElementById(elementIds[idx]);
 
@@ -33,6 +33,7 @@ var multi_processing=function(elementIds,task_multi,outputCanvasId) {
     this.output_canvas=document.getElementById(outputCanvasId);
     this.output_context=this.output_canvas.getContext("2d");
   }
+  this.result={};
 }
 
 multi_processing.prototype.acquire_data_from_img=function(id) {
@@ -67,10 +68,14 @@ multi_processing.prototype.acquire_data=function() {
 
 multi_processing.prototype.do_process=function() {
   this.acquire_data();
-  this.task_multi.process_multi(this.imageDatas,this.imageData_fused);
+  this.result=this.task_multi.process_multi(this.imageDatas,this.imageData_fused);
   if (this.output_canvas) this.update_output();
 }
 
 multi_processing.prototype.update_output=function() {
   this.output_context.putImageData(this.imageData_fused,0,0);
 }
+
+multi_processing.prototype.get_result=function() {
+  return this.result;
+}
diff --git a/filters/gray_filters.js b/processing/filters/gray_filters.js
similarity index 100%
rename from filters/gray_filters.js
rename to processing/filters/gray_filters.js
diff --git a/processing/pixels.js b/processing/pixels.js
new file mode 100644
index 0000000000000000000000000000000000000000..14f981400c6ba1499fac45c44c7f032bd3e9e7da
--- /dev/null
+++ b/processing/pixels.js
@@ -0,0 +1,43 @@
+GetPixelRGBATask=function(opt_options) {
+  this.x=opt_options.x;
+  this.y=opt_options.y;
+  if (opt_options.output)
+    this.output=opt_options.output;
+
+}
+
+GetPixelRGBATask.prototype.process=function(imageData) {
+  var pos=(this.y*imageData.width+this.x)<<2;
+  var r=imageData.data[pos];
+  var g=imageData.data[pos+1];
+  var b=imageData.data[pos+2];
+  var a=imageData.data[pos+3];
+
+  if (this.output) {
+    this.output.innerHTML=this.x+"x"+this.y+" : ";
+    this.output.innerHTML+="<font color='red'>"+r+"</font> | ";
+    this.output.innerHTML+="<font color='green'>"+g+"</font> | ";
+    this.output.innerHTML+="<font color='blue'>"+b+"</font> | ";
+    this.output.innerHTML+="<font color='gray'>"+a+"</font>";
+  }
+  return [r,g,b,a];
+}
+
+GetMeanPixelRGBATask=function(opt_options) {
+  if (opt_options && opt_option.output_id)
+    this.output=document.getElementById(opt_options.output_id);
+}
+
+GetMeanPixelRGBATask.prototype.process=function(imageData) {
+    if (imageData.width==0)
+      return;
+
+    var mean=pixels_features.computeRGBMeanPixel(imageData);
+    if (this.output) {
+      this.output.style="background-color:rgb("+mean[0]+","+mean[1]+","+mean[2]+")";
+      this.output.innerHTML="{r:"+mean[0]+";";
+      this.output.innerHTML+="g:"+mean[1]+";";
+      this.output.innerHTML+="b:"+mean[2]+"}";
+    }
+    return mean;
+}
diff --git a/processing2.js b/processing2.js
new file mode 100644
index 0000000000000000000000000000000000000000..eba599fefdcc55278cb3fcaa1b54f5d1fc3c06dc
--- /dev/null
+++ b/processing2.js
@@ -0,0 +1,89 @@
+var processing2=function(elementId,task,outputCanvasId,opt_options) {
+
+
+  this.element=document.getElementById(elementId);
+  this.width = this.element.width;
+  this.height = this.element.height;
+
+  this.in_imageData = {};
+  this.out_imageData = {};
+
+  this.processing_canvas=document.createElement('canvas');
+  this.processing_canvas.width = this.width;
+  this.processing_canvas.height = this.height;
+
+  this.processing_context=this.processing_canvas.getContext("2d");
+
+  this.task=task;
+
+
+
+  if (opt_options && opt_options.in_region)
+    this.in_region=opt_options.in_region
+  else
+    this.in_region={x:0,y:0,width:this.width,height:this.height}
+
+  if (outputCanvasId) {
+    this.output_canvas=document.getElementById(outputCanvasId);
+    this.output_context=this.output_canvas.getContext("2d");
+
+    if (opt_options && opt_options.out_region)
+    this.out_region=opt_options.out_region
+    else
+      this.out_region={x:0,y:0,width:this.output_canvas.width,height:this.output_canvas.height}
+  }
+  this.result={}
+}
+
+processing2.prototype.acquire_data_from_img=function() {
+  this.processing_context.drawImage(this.element,0,0,this.width,this.height);
+  this.in_imageData = this.processing_context.getImageData(0, 0, this.width, this.height);
+}
+
+processing2.prototype.acquire_data_from_video=function() {
+  this.processing_context.drawImage(this.element,0,0,this.width,this.height);
+  this.in_imageData = this.processing_context.getImageData(0, 0, this.width, this.height);
+}
+
+processing2.prototype.acquire_data_from_canvas=function() {
+  this.processing_context.drawImage(this.element,0,0,this.width,this.height);
+  this.in_imageData = this.processing_context.getImageData(this.in_region.x, this.in_region.y, this.in_region.width, this.in_region.height);
+}
+
+processing2.prototype.acquire_data=function() {
+  if (this.output_canvas)
+    this.out_imageData=this.output_context.getImageData(this.out_region.x,this.out_region.y,this.out_region.width,this.out_region.height);
+
+  switch (this.element.nodeName.toLowerCase()) {
+      case 'canvas':
+        this.acquire_data_from_canvas(); break;
+      case 'img':
+        this.acquire_data_from_img(); break;
+      case 'video':
+        this.acquire_data_from_video(); break;
+      default:
+        throw new Error('Element not supported!');
+    }
+}
+
+processing2.prototype.do_process=function() {
+  this.acquire_data();
+  this.result=this.task.process(this.in_imageData,this.out_imageData);
+  if (this.output_canvas) this.update_output();
+}
+
+processing2.prototype.update_output=function() {
+  this.output_context.putImageData(this.out_imageData,this.out_region.x,this.out_region.y);
+}
+
+processing2.prototype.get_result=function() {
+  return this.result;
+}
+
+processing2.prototype.get_processing_canvas=function() {
+  return this.processing_canvas;
+}
+
+processing2.prototype.get_in_imageData=function() {
+  return this.in_imageData;
+}
diff --git a/samples/lookup_template.html b/samples/lookup_template.html
new file mode 100644
index 0000000000000000000000000000000000000000..09393ee519e7411fe9808a3b2110884ed73ca205
--- /dev/null
+++ b/samples/lookup_template.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+  <script lang="js" src="../tools.js"></script>
+  <script lang="js" src="../features/generic.js"></script>
+  <script lang="js" src="../features/pixels.js"></script>
+  <script lang="js" src="../metrics/generic.js"></script>
+  <script lang="js" src="../metrics/pixels.js"></script>
+  <script lang="js" src="../dataset/images.js"></script>
+  <script lang="js" src="../similarity/generic.js"></script>
+  <script lang="js" src="../similarity/pixels.js"></script>
+  <script lang="js" src="../lookup/windows.js"></script>
+</head>
+<body>
+<img width="84" height="84" id='input1' src='../data/I1.png'></img>
+<img width="32" height="32" id='model' src='../data/red.png'></img>
+<div id="res"></div>
+<script lang="javascript">
+var task=[];
+
+_task=new lookup_windows.MeanRGBSameSizeTemplate('model',10);
+console.log(_task.process(Tools.get_imageData_from_imgEltId('input1')));
+
+</script>
+</body></html>
diff --git a/samples/photo_fill_pixels.html b/samples/photo_fill_pixels.html
new file mode 100644
index 0000000000000000000000000000000000000000..eb0cbff19fc52f2facdcaae38cebc002fdc9fb18
--- /dev/null
+++ b/samples/photo_fill_pixels.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+  <script lang="js" src="../tools.js"></script>
+  <script lang="js" src="../dataset/images.js"></script>
+  <script lang="js" src="../features/generic.js"></script>
+  <script lang="js" src="../features/pixels.js"></script>
+  <script lang="js" src="../metrics/generic.js"></script>
+  <script lang="js" src="../metrics/pixels.js"></script>
+  <script lang="js" src="../similarity/generic.js"></script>
+  <script lang="js" src="../similarity/pixels.js"></script>
+  <script lang="js" src="../effects/photo_fill.js"></script>
+  <script lang="js" src="../processing2.js"></script>
+</head>
+<body>
+<img width="16" height="16" id='input1' src='../data/16_02.JPG'></img>
+<img width="16" height="16" id='input2' src='../data/16_03.JPG'></img>
+<img width="16" height="16" id='input3' src='../data/16_04.JPG'></img>
+<img width="16" height="16" id='input4' src='../data/16_05.JPG'></img>
+<img width="16" height="16" id='input5' src='../data/16_06.JPG'></img>
+<img width="16" height="16" id='input6' src='../data/16_07.JPG'></img>
+<img width="16" height="16" id='input7' src='../data/16_08.JPG'></img>
+<img width="16" height="16" id='input8' src='../data/16_09.JPG'></img>
+<img width="16" height="16" id='input9' src='../data/16_10.JPG'></img>
+<img width="16" height="16" id='input10' src='../data/16_11.JPG'></img>
+<img width="16" height="16" id='input11' src='../data/16_12.JPG'></img>
+<img width="16" height="16" id='input12' src='../data/16_13.JPG'></img>
+<br></br>
+<img id="img0" src="../data/ii2d.png" width="40" height="20"></img>
+<br></br>
+<img id="big0" src="../data/ii2d.png" width="640" height="320"></img>
+<canvas id="output0" width="640" height="320"></canvas>
+<br></br>
+<img id="img1" src="../data/16_02.jpg" width="40" height="20"></img>
+<br></br>
+<img id="big1" src="../data/16_02.jpg" width="640" height="320"></img>
+<canvas id="output1" width="640" height="320"></canvas>
+
+<script lang="javascript">
+var proc=[],task=[],inputs=[];
+for (var i=1;i<13;i++) inputs[i]="input"+i;
+
+_dataset=new datasets.ImageDataset(inputs);
+_task=new photo_fill.PhotoFillPixelsFromDatasetTask(_dataset,{});
+
+proc=new processing2("img0",_task,"output0");
+proc.do_process();
+
+proc=new processing2("img1",_task,"output1");
+proc.do_process();
+
+</script>
+</body></html>
diff --git a/samples/similarity_image.html b/samples/similarity_image.html
new file mode 100644
index 0000000000000000000000000000000000000000..88f6e85d46e1c195301166004a73c053ea6f8dfd
--- /dev/null
+++ b/samples/similarity_image.html
@@ -0,0 +1,47 @@
+<html>
+<head>
+  <script lang="js" src="../tools.js"></script>
+  <script lang="js" src="../features/generic.js"></script>
+  <script lang="js" src="../features/pixels.js"></script>
+  <script lang="js" src="../metrics/generic.js"></script>
+  <script lang="js" src="../metrics/pixels.js"></script>
+  <script lang="js" src="../dataset/images.js"></script>
+  <script lang="js" src="../similarity/generic.js"></script>
+  <script lang="js" src="../similarity/pixels.js"></script>
+</head>
+<body>
+<img border="1" width="32" height="32" id='input1' src='../data/I1.png'></img>
+<img border="1" width="32" height="32" id='input2' src='../data/I2.png'></img>
+<img border="1" width="32" height="32" id='input3' src='../data/I3.png'></img>
+<img border="1" width="32" height="32" id='input4' src='../data/I4.png'></img>
+<img border="1" width="32" height="32" id='input5' src='../data/I5.png'></img>
+<img border="1" width="32" height="32" id='input6' src='../data/I6.png'></img>
+<img border="1" width="32" height="32" id='input7' src='../data/I7.png'></img>
+<img border="1" width="32" height="32" id='input8' src='../data/I8.png'></img>
+<div id="res"></div>
+<script lang="javascript">
+var inputs=[];
+for (var i=1;i<9;i++) inputs[i]="input"+i;
+_dataset=new datasets.ImageDataset(inputs);
+
+_task=new pixels_similarity.MeanRGBSimilarityTask(_dataset,{
+  desc_opt_options:{},
+  metric_opt_options:{}
+});
+
+imgData=_dataset.imageDatas[1];
+document.getElementById("res").appendChild(
+  Tools.create_canvasElt_from_imageData(imgData));
+document.getElementById("res").appendChild(document.createElement("br"));
+
+res=_task.process(imgData);
+console.log("for image id : "+imgData.orig_id);
+for (var j=1;j<6;j++) {
+  console.log(res[j]);
+  document.getElementById("res").appendChild(
+    Tools.create_canvasElt_from_imageData(_dataset.imageDatas[res[j].idx]));
+}
+document.getElementById("res").appendChild(document.createElement("br"));
+
+</script>
+</body></html>
diff --git a/samples/similarity_image_grid.html b/samples/similarity_image_grid.html
new file mode 100644
index 0000000000000000000000000000000000000000..73147630567384c64b75adebff349a8c6a1ebf98
--- /dev/null
+++ b/samples/similarity_image_grid.html
@@ -0,0 +1,47 @@
+<html>
+<head>
+  <script lang="js" src="../tools.js"></script>
+  <script lang="js" src="../features/generic.js"></script>
+  <script lang="js" src="../features/pixels.js"></script>
+  <script lang="js" src="../metrics/generic.js"></script>
+  <script lang="js" src="../metrics/pixels.js"></script>
+  <script lang="js" src="../dataset/images.js"></script>
+  <script lang="js" src="../similarity/generic.js"></script>
+  <script lang="js" src="../similarity/pixels.js"></script>
+</head>
+<body>
+<img border="1" width="32" height="32" id='input1' src='../data/I1.png'></img>
+<img border="1" width="32" height="32" id='input2' src='../data/I2.png'></img>
+<img border="1" width="32" height="32" id='input3' src='../data/I3.png'></img>
+<img border="1" width="32" height="32" id='input4' src='../data/I4.png'></img>
+<img border="1" width="32" height="32" id='input5' src='../data/I5.png'></img>
+<img border="1" width="32" height="32" id='input6' src='../data/I6.png'></img>
+<img border="1" width="32" height="32" id='input7' src='../data/I7.png'></img>
+<img border="1" width="32" height="32" id='input8' src='../data/I8.png'></img>
+<div id="res"></div>
+<script lang="javascript">
+var inputs=[];
+for (var i=1;i<9;i++) inputs[i]="input"+i;
+_dataset=new datasets.ImageDataset(inputs);
+
+_task=new pixels_similarity.GridMeanRGBSimilarityTask(_dataset,{
+  desc_opt_options:{nb_lines:2,nb_columns:2},
+  metric_opt_options:{}
+});
+
+imgData=_dataset.imageDatas[1];
+document.getElementById("res").appendChild(
+  Tools.create_canvasElt_from_imageData(imgData));
+document.getElementById("res").appendChild(document.createElement("br"));
+
+res=_task.process(imgData);
+console.log("for image id : "+imgData.orig_id);
+for (var j=1;j<6;j++) {
+  console.log(res[j]);
+  document.getElementById("res").appendChild(
+    Tools.create_canvasElt_from_imageData(_dataset.imageDatas[res[j].idx]));
+}
+document.getElementById("res").appendChild(document.createElement("br"));
+
+</script>
+</body></html>
diff --git a/samples/similarity_images_1.html b/samples/similarity_images_1.html
new file mode 100644
index 0000000000000000000000000000000000000000..d93fd529563d08dd051717be6aac71e677bbb023
--- /dev/null
+++ b/samples/similarity_images_1.html
@@ -0,0 +1,69 @@
+<html>
+<head>
+  <script lang="js" src="../tools.js"></script>
+  <script lang="js" src="../features/generic.js"></script>
+  <script lang="js" src="../features/pixels.js"></script>
+  <script lang="js" src="../metrics/generic.js"></script>
+  <script lang="js" src="../metrics/pixels.js"></script>
+  <script lang="js" src="../dataset/images.js"></script>
+  <script lang="js" src="../similarity/generic.js"></script>
+  <script lang="js" src="../similarity/pixels.js"></script>
+</head>
+<body>
+<img width="32" height="32" id='input1' src='../data/I1.png'></img>
+<img width="32" height="32" id='input2' src='../data/I2.png'></img>
+<img width="32" height="32" id='input3' src='../data/I3.png'></img>
+<img width="32" height="32" id='input4' src='../data/I4.png'></img>
+<img width="32" height="32" id='input5' src='../data/I5.png'></img>
+<img width="32" height="32" id='input6' src='../data/I6.png'></img>
+<img width="32" height="32" id='input7' src='../data/I7.png'></img>
+<img width="32" height="32" id='input8' src='../data/I8.png'></img>
+<div id="res"></div>
+<script lang="javascript">
+var task=[],inputs=[];
+for (var i=1;i<9;i++) inputs[i]="input"+i;
+_dataset=new datasets.ImageDataset(inputs);
+
+_task=new pixels_similarity.MeanRGBSimilarityTask(_dataset,{
+  desc_opt_options:{},
+  metric_opt_options:{}
+});
+
+_task_grid_1x2=new pixels_similarity.GridMeanRGBSimilarityTask(_dataset,{
+  dataset_image_ids:inputs,
+  desc_opt_options:{nb_columns:1,nb_lines:2},
+  metric_opt_options:{}
+});
+
+_task_grid_2x1=new pixels_similarity.GridMeanRGBSimilarityTask(_dataset,{
+  dataset_image_ids:inputs,
+  desc_opt_options:{nb_columns:2,nb_lines:1},
+  metric_opt_options:{}
+});
+
+_task_grid_2x2=new pixels_similarity.GridMeanRGBSimilarityTask(_dataset,{
+  dataset_image_ids:inputs,
+  desc_opt_options:{nb_columns:2,nb_lines:2},
+  metric_opt_options:{}
+});
+
+_tasks=[_task,_task_grid_1x2,_task_grid_2x1,_task_grid_2x2];
+
+for (var i=1;i<8;i++) {
+  imgData=_dataset.imageDatas[i];
+  document.getElementById("res").appendChild(Tools.create_canvasElt_from_imageData(imgData));
+  document.getElementById("res").appendChild(document.createElement("br"));
+  for (var taskid in _tasks) {
+    res=_tasks[taskid].process(imgData);
+    console.log("for image id : "+imgData.orig_id+" and task id : "+taskid);
+    for (var j=1;j<6;j++) {
+      console.log(res[j]);
+      document.getElementById("res").appendChild(Tools.create_canvasElt_from_imageData(_dataset.imageDatas[res[j].idx]));
+    }
+    document.getElementById("res").appendChild(document.createElement("br"));
+  }
+  document.getElementById("res").appendChild(document.createElement("hr"));
+}
+
+</script>
+</body></html>
diff --git a/samples/similarity_images_2.html b/samples/similarity_images_2.html
new file mode 100644
index 0000000000000000000000000000000000000000..a8190c003e87f76b46c7eefb42a7a6db1b367274
--- /dev/null
+++ b/samples/similarity_images_2.html
@@ -0,0 +1,59 @@
+<html>
+<head>
+  <script lang="js" src="../tools.js"></script>
+  <script lang="js" src="../features/generic.js"></script>
+  <script lang="js" src="../features/pixels.js"></script>
+  <script lang="js" src="../metrics/generic.js"></script>
+  <script lang="js" src="../metrics/pixels.js"></script>
+  <script lang="js" src="../dataset/images.js"></script>
+  <script lang="js" src="../similarity/generic.js"></script>
+  <script lang="js" src="../similarity/pixels.js"></script>
+</head>
+<body>
+<img width="16" height="16" id='input1' src='../data/16_02.JPG'></img>
+<img width="16" height="16" id='input2' src='../data/16_03.JPG'></img>
+<img width="16" height="16" id='input3' src='../data/16_04.JPG'></img>
+<img width="16" height="16" id='input4' src='../data/16_05.JPG'></img>
+<img width="16" height="16" id='input5' src='../data/16_06.JPG'></img>
+<img width="16" height="16" id='input6' src='../data/16_07.JPG'></img>
+<img width="16" height="16" id='input7' src='../data/16_08.JPG'></img>
+<img width="16" height="16" id='input8' src='../data/16_09.JPG'></img>
+<img width="16" height="16" id='input9' src='../data/16_10.JPG'></img>
+<img width="16" height="16" id='input10' src='../data/16_11.JPG'></img>
+<img width="16" height="16" id='input11' src='../data/16_12.JPG'></img>
+<img width="16" height="16" id='input12' src='../data/16_13.JPG'></img>
+<div id="res"></div>
+<script lang="javascript">
+var task=[],inputs=[];
+for (var i=1;i<13;i++) inputs[i]="input"+i;
+_dataset=new datasets.ImageDataset(inputs);
+
+_task=new pixels_similarity.MeanRGBSimilarityTask(_dataset,{
+  desc_opt_options:{},
+  metric_opt_options:{}
+});
+
+_task_grid=new pixels_similarity.GridMeanRGBSimilarityTask(_dataset,{
+  desc_opt_options:{nb_columns:2,nb_lines:2},
+  metric_opt_options:{}
+});
+
+for (var i=1;i<13;i++) {
+  imgData=_dataset.imageDatas[i];
+  document.getElementById("res").appendChild(Tools.create_canvasElt_from_imageData(imgData));
+  document.getElementById("res").appendChild(document.createElement("br"));
+  res=_task.process(imgData);
+  for (var j=1;j<6;j++) {
+    document.getElementById("res").appendChild(Tools.create_canvasElt_from_imageData(_dataset.imageDatas[res[j].idx]));
+  }
+  document.getElementById("res").appendChild(document.createElement("br"));
+
+  res=_task_grid.process(imgData);
+  for (var j=1;j<6;j++) {
+    document.getElementById("res").appendChild(Tools.create_canvasElt_from_imageData(_dataset.imageDatas[res[j].idx]));
+  }
+  document.getElementById("res").appendChild(document.createElement("hr"));
+}
+
+</script>
+</body></html>
diff --git a/similarity/generic.js b/similarity/generic.js
new file mode 100644
index 0000000000000000000000000000000000000000..beec1ff77af01f864715e6317055ce6f013938b2
--- /dev/null
+++ b/similarity/generic.js
@@ -0,0 +1,48 @@
+var generic_similarity={}
+
+generic_similarity.SimilarityTask=
+  function(dataset, descriptor_func,similarity_metric_func, opt_options){
+
+  this.dataset=dataset;
+
+  this.descriptor_func=descriptor_func;
+  this.desc_opt_options=opt_options.desc_opt_options;
+
+  this.dataset_descriptors=[];
+  for (var idx in this.dataset.imageDatas) {
+    this.dataset_descriptors[idx]=
+      this.descriptor_func(this.dataset.imageDatas[idx],this.desc_opt_options);
+    console.log(this.dataset_descriptors[idx]);
+  }
+
+  this.similarity_metric_func=similarity_metric_func;
+  this.similarity_metric_opt_options=opt_options.similarity_metric_opt_options;
+}
+
+generic_similarity.SimilarityTask.prototype.process_descriptor=function(in_descriptor)
+{
+  var sim=[],order=[];
+  for (var idx in this.dataset_descriptors) {
+    sim[idx]=this.similarity_metric_func(
+      in_descriptor,this.dataset_descriptors[idx],this.metric_opt_options);
+    order[idx]=idx;
+  }
+  for (var idx1 in order)
+    for (var idx2 in order)
+      if (sim[order[idx1]]<sim[order[idx2]])
+      { aux=order[idx1]; order[idx1]=order[idx2]; order[idx2]=aux; }
+
+  var res=[];
+  for (var idx in order) res[idx]={idx:order[idx],sim:sim[order[idx]]}
+  return res;
+}
+
+generic_similarity.SimilarityTask.prototype.process=function(in_imageData){
+  var in_descriptor=this.descriptor_func(in_imageData,this.desc_opt_options);
+  return this.process_descriptor(in_descriptor);
+}
+
+
+generic_similarity.SimilarityTask.prototype.get_dataset_descriptor=function(idx) {
+  return this.dataset_descriptors[idx];
+}
diff --git a/similarity/pixels.js b/similarity/pixels.js
new file mode 100644
index 0000000000000000000000000000000000000000..4ea46054ae40a57436e20e2e7f76669fa01a3dd6
--- /dev/null
+++ b/similarity/pixels.js
@@ -0,0 +1,19 @@
+var pixels_similarity={}
+
+pixels_similarity.MeanRGBSimilarityTask=function(dataset,opt_options) {
+  this.__proto__.__proto__=new generic_similarity.SimilarityTask(
+    dataset,
+    pixels_features.mean_rgb,
+    pixel_metrics.rgb_edist,
+    opt_options
+  );
+}
+
+pixels_similarity.GridMeanRGBSimilarityTask=function(dataset,opt_options){
+  this.__proto__.__proto__=new generic_similarity.SimilarityTask(
+    dataset,
+    pixels_features.grid_mean_rgb,
+    pixel_metrics.grid_rgb_edist,
+    opt_options
+  );
+}
diff --git a/tools.js b/tools.js
index e51ccca06f6d8344278dd68a61e6cb15a3c0724b..40860ad494c3a8c5dc8e81e5e3fe97ed2b1ae75a 100644
--- a/tools.js
+++ b/tools.js
@@ -1,15 +1,72 @@
-var tools=function(){
-  this.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
-    navigator.mozGetUserMedia || navigator.msGetUserMedia;
-}
+var Tools={}
 
-tools.prototype.initUserMedia=function(element,opt_options) {
+Tools.init_user_media=function(element,opt_options) {
   window.navigator.mediaDevices.getUserMedia({
     video: true,
     audio: (opt_options && opt_options.audio) ? true : false,
   }).then(function(stream) {
-    element.srcObject = stream;
+    element.inObject = stream;
   }).catch(function(err) {
     throw Error('Cannot capture user camera.');
   });
 }
+
+Tools.get_imageData_from_imgEltId=function(img_elt_id) {
+  return Tools.get_partial_imageData_from_imgEltId(img_elt_id);
+}
+
+Tools.get_partial_imageData_from_imgEltId=function(img_elt_id,x=0,y=0,dx=undefined,dy=undefined) {
+  var img=document.getElementById(img_elt_id);
+  if (!dx) dx=img.width-x;
+  if (!dy) dy=img.height-y;
+  var cvs=document.createElement("canvas");
+  cvs.width=dx;cvs.height=dy;
+  var ctxt=cvs.getContext("2d");
+  ctxt.drawImage(img,x,y,dx,dy);
+  var imageData=ctxt.getImageData(0,0,dx,dy);
+  imageData.ctxt=ctxt;
+  imageData.orig_id=img_elt_id
+  imageData.orig_x=x;
+  imageData.orig_y=y;
+  return imageData;
+}
+
+Tools.create_canvasElt_from_imageData=function(imageData) {
+  var cvs_elt=document.createElement("canvas");
+  cvs_elt.width=imageData.width;
+  cvs_elt.height=imageData.height;
+  cvs_elt.style="border:1px solid #000000";
+  cvs_elt.alt=imageData.orig_id;
+  Tools.update_canvasElt_from_imageData(cvs_elt,imageData)
+  return cvs_elt;
+}
+
+Tools.update_canvasElt_from_imageData=function(cvs_elt,imageData,x=0,y=0) {
+  var ctxt=cvs_elt.getContext("2d");
+  ctxt.putImageData(imageData,x,y);
+}
+
+Tools.copy_imageData_into_imageData=function(src_imageData,dest_imageData,x0,y0) {
+  var w_src=0;
+  for (var src_y=0; src_y<src_imageData.height; src_y++)
+    for (var src_x=0; src_x < src_imageData.width; src_x++) {
+      w_out=(y0+src_y)*dest_imageData.width+(x0+src_x)<<2;
+      dest_imageData.data[w_out]=src_imageData.data[w_src];
+      dest_imageData.data[w_out+1]=src_imageData.data[w_src+1];
+      dest_imageData.data[w_out+2]=src_imageData.data[w_src+2];
+      dest_imageData.data[w_out+3]=src_imageData.data[w_src+3];
+      w_src+=4
+    }
+}
+
+Tools.get_region_from_imageData=function(src_imageData,x0,y0,dx,dy) {
+  var reg_imageData=src_imageData.ctxt.getImageData(
+      src_imageData.orig_x+x0,src_imageData.orig_y+y0,
+      dx,dy);
+  reg_imageData.orig_x=src_imageData.orig_x+x0;
+  reg_imageData.orig_y=src_imageData.orig_y+x0;
+  reg_imageData.ctxt = src_imageData.ctxt;
+  reg_imageData.orig_id = src_imageData.orig_id;
+
+  return reg_imageData;
+}