diff --git a/.gitignore b/.gitignore
index 1f5c3d21e834692aa6bae6b3935bbd88f5f6604d..fc44ca6bd9f25d424b42fa24b1505899302a05d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-**/sol**.js
-**/sol**.html
+**/sol_*.js
+**/sol_*.html
diff --git a/data/happy.mp4 b/data/happy.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..1e235f7d16af452587d4ccb0c09f7b66135aaef3
Binary files /dev/null and b/data/happy.mp4 differ
diff --git a/data/rgb.png b/data/rgb.png
new file mode 100644
index 0000000000000000000000000000000000000000..1d7a20a5e1f47a32fc238dab0d0ffde4219768a2
Binary files /dev/null and b/data/rgb.png differ
diff --git a/data/surprise.mp4 b/data/surprise.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..c632ab00cda36a8979f19294dcb85aa90b34b584
Binary files /dev/null and b/data/surprise.mp4 differ
diff --git a/data/tambour.png b/data/tambour.png
new file mode 100644
index 0000000000000000000000000000000000000000..58674e9ed29fe8fb5105a2424e588ea7a4c239d7
Binary files /dev/null and b/data/tambour.png differ
diff --git a/filters/gray_filters.js b/filters/gray_filters.js
new file mode 100644
index 0000000000000000000000000000000000000000..56c159359d5e977b1f4ae78eec5606d7f2176e58
--- /dev/null
+++ b/filters/gray_filters.js
@@ -0,0 +1,48 @@
+ToGrayTask=function(opt_options) { }
+
+ToGrayTask.prototype.process=function(imageData) {
+  var pixels=imageData.data;
+  var w=0;
+  for (var i = 0; i < imageData.height; i++)
+      for (var j = 0; j < imageData.width; j++) {
+        var mean=(pixels[w+1]+pixels[w+2]+pixels[w+3])/3;
+        pixels[w]=mean; pixels[w+1]=mean; pixels[w+2]=mean;
+        w+=4;
+      }
+}
+
+PartialGrayTask=function(opt_options) {
+  this.reg_x=opt_options.reg_x; this.reg_y=opt_options.reg_y;
+  this.reg_w=opt_options.reg_w; this.reg_h=opt_options.reg_h;
+}
+
+PartialGrayTask.prototype.process=function(imageData) {
+  var pixels=imageData.data;
+  for (var i = this.reg_y; i < this.reg_y+this.reg_h; i++)
+      for (var j = this.reg_x; j < this.reg_x+this.reg_w; j++) {
+        var pos=(i*imageData.width+j)<<2;
+        var mean=(pixels[pos+1]+pixels[pos+2]+pixels[pos+3])/3;
+        pixels[pos]=mean; pixels[pos+1]=mean; pixels[pos+2]=mean;
+      }
+}
+
+RandomPartialGrayTask=function(opt_options) {
+  this.reg_x=opt_options.reg_x; this.reg_y=opt_options.reg_y;
+  this.reg_w=opt_options.reg_w; this.reg_h=opt_options.reg_h;
+  this.cvs_w=opt_options.cvs_w; this.cvs_h=opt_options.csv_h;
+}
+
+RandomPartialGrayTask.prototype.process=function(imageData) {
+  var pixels=imageData.data;
+  for (var i = this.reg_y; i < this.reg_y+this.reg_h; i++)
+      for (var j = this.reg_x; j < this.reg_x+this.reg_w; j++) {
+        var pos=(i*imageData.width+j)<<2;
+        var mean=(pixels[pos+1]+pixels[pos+2]+pixels[pos+3])/3;
+        pixels[pos]=mean; pixels[pos+1]=mean; pixels[pos+2]=mean;
+      }
+}
+
+RandomPartialGrayTask.prototype.random_focus=function() {
+    this.reg_y=Math.trunc(Math.random()*(this.cvs_h-this.reg_h));
+    this.reg_x=Math.trunc(Math.random()*(this.cvs_w-this.reg_w));
+}
diff --git a/processing.js b/processing.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f262d9a44da8f77bfc0f710fde4e0fa518e1466
--- /dev/null
+++ b/processing.js
@@ -0,0 +1,58 @@
+var processing=function(elementId,task,outputCanvasId) {
+  this.element=document.getElementById(elementId);
+  this.width = this.element.width;
+  this.height = this.element.height;
+
+  this.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 (outputCanvasId) {
+    this.output_canvas=document.getElementById(outputCanvasId);
+    this.output_context=this.output_canvas.getContext("2d");
+  }
+}
+
+processing.prototype.acquire_data_from_img=function() {
+  this.processing_context.drawImage(this.element,0,0,this.width,this.height);
+  this.imageData = this.processing_context.getImageData(0, 0, this.width, this.height);
+}
+
+processing.prototype.acquire_data_from_video=function() {
+  this.processing_context.drawImage(this.element,0,0,this.width,this.height);
+  this.imageData = this.processing_context.getImageData(0, 0, this.width, this.height);
+}
+
+processing.prototype.acquire_data_from_canvas=function() {
+  this.processing_context.drawImage(this.element,0,0,this.width,this.height);
+  this.imageData = this.processing_context.getImageData(0, 0, this.width, this.height);
+}
+
+processing.prototype.acquire_data=function() {
+  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!');
+    }
+}
+
+processing.prototype.do_process=function() {
+  this.acquire_data();
+  this.task.process(this.imageData);
+  if (this.output_canvas) this.update_output();
+}
+
+processing.prototype.update_output=function() {
+  this.output_context.putImageData(this.imageData,0,0);
+}
diff --git a/samples/image_get_pixel.html b/samples/image_get_pixel.html
new file mode 100644
index 0000000000000000000000000000000000000000..38eb1e39ebc123cbeea0aa147ffeffc0979db5ab
--- /dev/null
+++ b/samples/image_get_pixel.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<script lang="js" src="../tools.js"></script>
+<script lang="js" src="../features/pixels.js"></script>
+<script lang="js" src="../processing.js"></script>
+</head>
+<body>
+  <img autoplay loop src="../data/tambour.png" id="input" height="240" width="240"></img>
+  <br></br>
+  <div id="output"></p>
+
+  <script lang="javascript">
+    var _output=document.getElementById("output");
+    var _opt_options={x:100,y:100,output:_output};
+    var _task=new GetPixelRGBATask(_opt_options)
+    var _proc=new processing("input",_task);
+    var loop=function() {
+      _proc.do_process();
+      requestAnimationFrame(loop);
+    }
+    loop();
+  </script>
+</body>
+</html>
diff --git a/samples/video_gray_0.html b/samples/video_gray_0.html
new file mode 100644
index 0000000000000000000000000000000000000000..de8fa81bef3879e247da6270b5f355800a13f940
--- /dev/null
+++ b/samples/video_gray_0.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<script lang="js" src="../tools.js"></script>
+<script lang="js" src="../filters/gray_filters.js"></script>
+<script lang="js" src="../processing.js"></script>
+</head>
+<body>
+  <video autoplay loop src="../data/happy.mp4" id="input" width="320" height="180"></video>
+  <canvas id="output" width="320" height="180"></canvas>
+
+  <script lang="javascript">
+    var _opt_options={reg_x:0,reg_y:0,reg_w:160,reg_h:90,cvs_w:320,csv_h:180};
+    var _task=new ToGrayTask(_opt_options)
+    var _proc=new processing("input",_task,"output");
+    var loop=function() {
+      _proc.do_process();
+      requestAnimationFrame(loop);
+    }
+    loop();
+  </script>
+</body>
+</html>
diff --git a/samples/video_gray_1.html b/samples/video_gray_1.html
new file mode 100644
index 0000000000000000000000000000000000000000..03ccb322ee0aa0c438d22bb8824629e062c86c79
--- /dev/null
+++ b/samples/video_gray_1.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<script lang="js" src="../tools.js"></script>
+<script lang="js" src="../filters/gray_filters.js"></script>
+<script lang="js" src="../processing.js"></script>
+</head>
+<body>
+  <video autoplay loop src="../data/happy.mp4" id="input" width="320" height="180"></video>
+  <canvas id="output" width="320" height="180"></canvas>
+
+  <script lang="javascript">
+    var _opt_options={reg_x:0,reg_y:0,reg_w:160,reg_h:90,cvs_w:320,csv_h:180};
+    var _task=new PartialGrayTask(_opt_options)
+    var _proc=new processing("input",_task,"output");
+    var loop=function() {
+      _proc.do_process();
+      requestAnimationFrame(loop);
+    }
+    loop();
+  </script>
+</body>
+</html>
diff --git a/samples/video_gray_2.html b/samples/video_gray_2.html
new file mode 100644
index 0000000000000000000000000000000000000000..910c7544dafc09046e45b97247e390046063b108
--- /dev/null
+++ b/samples/video_gray_2.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<script lang="js" src="../tools.js"></script>
+<script lang="js" src="../filters/gray_filters.js"></script>
+<script lang="js" src="../processing.js"></script>
+</head>
+<body>
+  <video autoplay loop src="../data/happy.mp4" id="input" width="320" height="180"></video>
+  <canvas id="output" width="320" height="180"></canvas>
+
+  <script lang="javascript">
+    var _opt_options={reg_x:0,reg_y:0,reg_w:160,reg_h:90,cvs_w:320,csv_h:180};
+    var _task=new RandomPartialGrayTask(_opt_options)
+    var _proc=new processing("input",_task,"output");
+    var loop=function() {
+      _proc.do_process();_task.random_focus();
+      requestAnimationFrame(loop);
+    }
+    loop();
+  </script>
+</body>
+</html>
diff --git a/tools.js b/tools.js
new file mode 100644
index 0000000000000000000000000000000000000000..e51ccca06f6d8344278dd68a61e6cb15a3c0724b
--- /dev/null
+++ b/tools.js
@@ -0,0 +1,15 @@
+var tools=function(){
+  this.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
+    navigator.mozGetUserMedia || navigator.msGetUserMedia;
+}
+
+tools.prototype.initUserMedia=function(element,opt_options) {
+  window.navigator.mediaDevices.getUserMedia({
+    video: true,
+    audio: (opt_options && opt_options.audio) ? true : false,
+  }).then(function(stream) {
+    element.srcObject = stream;
+  }).catch(function(err) {
+    throw Error('Cannot capture user camera.');
+  });
+}