Solved

how to get the pixel data from a canvas filter it and create a 2 canvas.

Posted on 2014-03-17
9
277 Views
Last Modified: 2014-03-19
Hello,


My question is how can I get the values of the pixels in a canvas stored in a 1 dimension array.

I have been able to know the values of the pixel of a photo and transform them in canvas.

It seems stupid but I cannot find on the web how to get the data of a canvas.

In the example here I load a first canvas from images=> OK (thanks to EE)

Now I want to get the data from the first canvas to filter it and create a second canvas.

Can some one help me please?



<!DOCTYPE html>
<html>
<head>
<title> EE Q_28383720 </title>
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>

.icone
{
margin-left:0px;
}


.icone-1 { background-position: left top }
.icone-2 { background-position: 14.2857% top }
.icone-3 { background-position: 28.5714% top }
.icone-4 { background-position: 42.8571% top }
.icone-5 { background-position: 57.1428% top }
.icone-6 { background-position: 71.4285% top }
.icone-7 { background-position: 85.7142% top }
.icone-8 { background-position: right top }





ul
{
padding:0px;
border:3px solid blue;
display: inline-block;
}

.icone li {
  margin:auto;
  text-align:center; /* non*/	
  vertical-align:bottom;
  padding:0px;
  width: 75px;
  height: 100px;
  border-radius:16px;
  border: solid white 5px;
  color: white;
  opacity: 1;
  background-image: url("http://www.davidinlove.com/img/sprite_menu_DT.jpg");
  background-repeat: no-repeat;
  display: inline-block;
  list-style-type:none;
}

.menuli
{
display: inline-block;
margin-top: 60px;
padding: auto;
width: 99%;
text-align:center;
border-radius:5px;
bottom: 0;
background-color: rgb(24,24,24); /* Pour les anciens navigateurs */
background-color: rgba(24,24,24,0.6);
}
</style>
</head>
<body>
  <div id="id-menu" class="c-menu">
    SPRITE<br/>
    <ul class="icone">
      <a href="#" id = "IMG1" ><li class="icone-1" id = "IMG1child" ><div class="menuli">Draw the <br\>eiffel tower</div></li></a>
      <a href="#" id = "IMG2" ><li class="icone-2" id = "IMG2child" ></li></a>
      <a href="#" id = "IMG3" ><li class="icone-3" id = "IMG3child" ></li></a>
      <a href="#" id = "IMG4" ><li class="icone-4" id = "IMG4child" ></li></a>
      <a href="#" id = "IMG5" ><li class="icone-5" id = "IMG5child" ></li></a>
      <a href="#" id = "IMG6" ><li class="icone-6" id = "IMG6child" ></li></a>
      <a href="#" id = "IMG7" ><li class="icone-7" id = "IMG7child" ></li></a>
      <a href="#" id = "IMG8" ><li class="icone-8" id = "IMG8child" ></li></a>
      </ul>
    </ul>
    </div>

<hr>
CANVAS FROM PICTURE</br>
<canvas id="myCanvas_OUT0" width="75" height="100"></canvas>

</br>
FILTERING EFFECT ON CANVAS</br>
<canvas id="myCanvas_OUT21" width="75" height="100"></canvas>
	


<script>




function custompos(p, isY, cnv, img) {
  var ti, tc;
  if (isY) {
    ti = img.height;
    tc = 100; // cnv.height;
    p = p.replace('top', '0').replace('bottom', '100%'); // ti - tc
  } else {
    ti = img.width;
    tc = 75; // cnv.width;
    p = p.replace('left', '0').replace('right', '100%'); // ti - tc
  }
  if (p.substr(-1) == '%') {
    p = Number(p.substr(0, p.length - 1)) * (ti - tc) / 100;
  }
  return p;
}


$("a").click( function(e) {
  e.preventDefault();
  img_srcout0="";
  img_srcout0= $(this).children(":first").css('background-image').replace(/^url\((['"]?)(.*?)\1\).*$/i, "$2");
  var bpos = $(this).children(":first").css('background-position');
  elemout0 = document.getElementById("myCanvas_OUT0");
  if (elemout0 && elemout0.getContext) 
  {
    contextout0 = elemout0.getContext("2d");
    if (contextout0) 
    {
      imgout0=new Image();
      imgout0.onload=function(){

        // some extra code to get position, this is not completely generic!
        var bposa = bpos.split(' ');
        var bposx = custompos(bposa[0], false, elemout0, imgout0);
        var bposy = custompos(bposa[1], true, elemout0, imgout0);
        contextout0.drawImage(imgout0,-bposx,-bposy);

        //imgdout0 = contextout0.getImageData(0, 0, 303,539);
        //pixout0 = imgdout0.data;
      };
      imgout0.src=img_srcout0;
    }
  }
});



$("#myCanvas_OUT0").on("click", function(e) {  

	//GET THE DATA OF THE myCanvas_OUT0

	var canvas_out0 = $("#myCanvas_OUT0");
	var canvasout0Position = {
		x: canvas_out0.offset().left,
		y: canvas_out0.offset().top
	};


	var elemout0 = document.getElementById("myCanvas_OUT0");
	if (elemout0 && elemout0.getContext) 
		{
		var contextout0 = elemout0.getContext("2d");
		}

	//********** It seems here is the problem
	//I need to know how to get the array with the values of the pixels of the canvas
	//This codes seems OK to take the data from a photo but my website will process data of canvas
	
	var imgdout0 = contextout0.getImageData(0, 0, 150,200);
	var pixout0 = imgdout0.data;
	
	
	//Define the second canvas
	
	
	var canvas_out21 = $("#myCanvas_OUT21");
	var canvasout21Position = {
		x: canvas_out21.offset().left,
		y: canvas_out21.offset().top
	};
	var elemout21 = document.getElementById("myCanvas_OUT21");
	if (elemout21 && elemout21.getContext) 
		{
		  var contextout21 = elemout21.getContext("2d");
		  

			
		}
	
	var imgdout21 = contextout21.getImageData(0, 0, 150,200);
	var pixout21 = new Array();

	
	//FILTER THE DATA
	//This I do here in a simple example 
	
		for(j=0;j<pixout0.length;j+=4)
		{ 
			pixout21[j]=pixout0[j]/2 ;		
			pixout21[j+1]=pixout0[j+1]/2 ;		
			pixout21[j+2]=pixout0[j+2]/2 ;		
			pixout21[j+3]=255;	
		}
	
	
	
	//DISPLAY DATA IN The myCanvas_OUT21
	
		contextout21.putImageData(imgdout21, 0, 0);
	
		});

</script>

</body>
</html>

Open in new window

0
Comment
Question by:DavidInLove
  • 5
  • 4
9 Comments
 
LVL 35

Accepted Solution

by:
Robert Schutt earned 500 total points
ID: 39935305
Below you find the code as it works for me.

The changes I made (not sure 100% which are optional ;-)

- use a local (sprite) picture, there can be a security error when you draw an external image on the canvas and then try to get the pixel data,
- use the correct size (75x100),
- moved var declaration up top (this one I know is optional),
- I used imgdout21.data (to overwrite existing data array) instead of new Array().
<!DOCTYPE html>
<html>
<head>
<title> EE Q_28383720 </title>
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>

.icone
{
margin-left:0px;
}


.icone-1 { background-position: left top }
.icone-2 { background-position: 14.2857% top }
.icone-3 { background-position: 28.5714% top }
.icone-4 { background-position: 42.8571% top }
.icone-5 { background-position: 57.1428% top }
.icone-6 { background-position: 71.4285% top }
.icone-7 { background-position: 85.7142% top }
.icone-8 { background-position: right top }





ul
{
padding:0px;
border:3px solid blue;
display: inline-block;
}

.icone li {
  margin:auto;
  text-align:center; /* non*/	
  vertical-align:bottom;
  padding:0px;
  width: 75px;
  height: 100px;
  border-radius:16px;
  border: solid white 5px;
  color: white;
  opacity: 1;
  background-image: url("./sprite_menu_DT.jpg");
  background-repeat: no-repeat;
  display: inline-block;
  list-style-type:none;
}

.menuli
{
display: inline-block;
margin-top: 60px;
padding: auto;
width: 99%;
text-align:center;
border-radius:5px;
bottom: 0;
background-color: rgb(24,24,24); /* Pour les anciens navigateurs */
background-color: rgba(24,24,24,0.6);
}
</style>
</head>
<body>
  <div id="id-menu" class="c-menu">
    SPRITE<br/>
    <ul class="icone">
      <a href="#" id = "IMG1" ><li class="icone-1" id = "IMG1child" ><div class="menuli">Draw the <br\>eiffel tower</div></li></a>
      <a href="#" id = "IMG2" ><li class="icone-2" id = "IMG2child" ></li></a>
      <a href="#" id = "IMG3" ><li class="icone-3" id = "IMG3child" ></li></a>
      <a href="#" id = "IMG4" ><li class="icone-4" id = "IMG4child" ></li></a>
      <a href="#" id = "IMG5" ><li class="icone-5" id = "IMG5child" ></li></a>
      <a href="#" id = "IMG6" ><li class="icone-6" id = "IMG6child" ></li></a>
      <a href="#" id = "IMG7" ><li class="icone-7" id = "IMG7child" ></li></a>
      <a href="#" id = "IMG8" ><li class="icone-8" id = "IMG8child" ></li></a>
      </ul>
    </ul>
    </div>

<hr>
CANVAS FROM PICTURE</br>
<canvas id="myCanvas_OUT0" width="75" height="100"></canvas>

</br>
FILTERING EFFECT ON CANVAS</br>
<canvas id="myCanvas_OUT21" width="75" height="100"></canvas>
	


<script>

var contextout0, contextout21;


function custompos(p, isY, cnv, img) {
  var ti, tc;
  if (isY) {
    ti = img.height;
    tc = 100; // cnv.height;
    p = p.replace('top', '0').replace('bottom', '100%'); // ti - tc
  } else {
    ti = img.width;
    tc = 75; // cnv.width;
    p = p.replace('left', '0').replace('right', '100%'); // ti - tc
  }
  if (p.substr(-1) == '%') {
    p = Number(p.substr(0, p.length - 1)) * (ti - tc) / 100;
  }
  return p;
}


$("a").click( function(e) {
  e.preventDefault();
  img_srcout0="";
  img_srcout0= $(this).children(":first").css('background-image').replace(/^url\((['"]?)(.*?)\1\).*$/i, "$2");
  var bpos = $(this).children(":first").css('background-position');
  elemout0 = document.getElementById("myCanvas_OUT0");
  if (elemout0 && elemout0.getContext) 
  {
    contextout0 = elemout0.getContext("2d");
    if (contextout0) 
    {
      imgout0=new Image();
      imgout0.onload=function(){

        // some extra code to get position, this is not completely generic!
        var bposa = bpos.split(' ');
        var bposx = custompos(bposa[0], false, elemout0, imgout0);
        var bposy = custompos(bposa[1], true, elemout0, imgout0);
        contextout0.drawImage(imgout0,-bposx,-bposy);

        //imgdout0 = contextout0.getImageData(0, 0, 303,539);
        //pixout0 = imgdout0.data;
      };
      imgout0.src=img_srcout0;
    }
  }
});



$("#myCanvas_OUT0").on("click", function(e) {  

	//GET THE DATA OF THE myCanvas_OUT0

	var canvas_out0 = $("#myCanvas_OUT0");
	var canvasout0Position = {
		x: canvas_out0.offset().left,
		y: canvas_out0.offset().top
	};


	var elemout0 = document.getElementById("myCanvas_OUT0");
	if (elemout0 && elemout0.getContext) 
		{
		contextout0 = elemout0.getContext("2d");
		}

	//********** It seems here is the problem
	//I need to know how to get the array with the values of the pixels of the canvas
	//This codes seems OK to take the data from a photo but my website will process data of canvas
	
	var imgdout0 = contextout0.getImageData(0, 0, 75, 100); // was 150,200
	var pixout0 = imgdout0.data;
	
	
	//Define the second canvas
	
	
	var canvas_out21 = $("#myCanvas_OUT21");
	var canvasout21Position = {
		x: canvas_out21.offset().left,
		y: canvas_out21.offset().top
	};
	var elemout21 = document.getElementById("myCanvas_OUT21");
	if (elemout21 && elemout21.getContext) 
		{
		  contextout21 = elemout21.getContext("2d");
		  

			
		}
	
	var imgdout21 = contextout21.getImageData(0, 0, 75, 100);
	var pixout21 = imgdout21.data; //new Array();

	
	//FILTER THE DATA
	//This I do here in a simple example 
	
		for(j=0;j<pixout0.length;j+=4)
		{ 
			pixout21[j]=pixout0[j]/2 ;		
			pixout21[j+1]=pixout0[j+1]/2 ;		
			pixout21[j+2]=pixout0[j+2]/2 ;		
			pixout21[j+3]=255;	
		}
	
	
	
	//DISPLAY DATA IN The myCanvas_OUT21
	
		contextout21.putImageData(imgdout21, 0, 0);
	
		});

</script>

</body>
</html>

Open in new window

0
 

Author Comment

by:DavidInLove
ID: 39936704
Robert,

The code doesn't work.

Here to simplify only one question:

How can I get the array data of pixel from the canvas that you draw from sprite.

Since your code enables draw this canvas you must know how to get them?


So, I suggest We come back to your code and I just ask this question
I defined a global array pixelout0

How can I put the data in it when you draw the first canvas from the sprite

In this way I can hope to take back the data from the global array in my second function to filter and draw the second canvas

I have just added

var pixelout0 = new Array();

Open in new window


in the begining


and I would like you to tell me how to store the data of the canvas you created from sprite
in

//************B/ store the data in pixelout0 array

in the code
var pixelout0 = new Array();
function custompos(p, isY, cnv, img) {
  var ti, tc;
  if (isY) {
    ti = img.height;
    tc = 100; // cnv.height;
    p = p.replace('top', '0').replace('bottom', '100%'); // ti - tc
  } else {
    ti = img.width;
    tc = 75; // cnv.width;
    p = p.replace('left', '0').replace('right', '100%'); // ti - tc
  }
  if (p.substr(-1) == '%') {
    p = Number(p.substr(0, p.length - 1)) * (ti - tc) / 100;
  }
  return p;
}


$("a").click( function(e) {
  e.preventDefault();
  img_srcout0="";
  img_srcout0= $(this).children(":first").css('background-image').replace(/^url\((['"]?)(.*?)\1\).*$/i, "$2");
  var bpos = $(this).children(":first").css('background-position');

  elemout0 = document.getElementById("myCanvas_OUT0");
  if (elemout0 && elemout0.getContext) 
  {
    contextout0 = elemout0.getContext("2d");
    if (contextout0) 
    {
      imgout0=new Image();
      imgout0.onload=function(){

        // some extra code to get position, this is not completely generic!

       
        var bposa = bpos.split(' ');
        var bposx = custompos(bposa[0], false, elemout0, imgout0);
        var bposy = custompos(bposa[1], true, elemout0, imgout0);
        contextout0.drawImage(imgout0,-bposx,-bposy);

//************B/ store the data in pixelout0 array

      };
      imgout0.src=img_srcout0;
    }
  }
});

Open in new window

0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 39936804
The data is not taken from the sprite image directly, but from the canvas, your existing code is fine for that. Here is a screen capture to show it works, it halves every pixel color value creating a darker version of the image, for now I assumed this is what you were after?
captureHave you checked each of the 4 points? using the sprite image from your other website is not an option apparently, make it local to the test page. Using new Array() also did not work for me, so instead I used the code to get .data for the 2nd canvas.

Which browser are you using? For testing, I also uploaded it here: http://schutt.nl/ee/Q_28390058/
0
 

Author Closing Comment

by:DavidInLove
ID: 39936865
Hi Robert,


I don't want we loose time on this.
Your code is OK with the link to your site for every browser

When I am on local with the source code you gave (I've copied from your site) it is not working for me with GOOGLE CHROME (Version 33.0.1750.154 m) and OPERA
but it is true that with IE FireFox and Safari for windows it is OK.
I wasn't using those for first tests.


I don't know why this problem appears only on local with Google chrome but not for FF?

The first step sprite to canvas is always OK
just the second fails sometimes.


Maybe it is because of loading time for the DOM?


Thanks for your answer.
David
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 35

Expert Comment

by:Robert Schutt
ID: 39937117
I can confirm now that in LOCAL testing, in Chrome (I use the same, latest version, but I don't have Opera), the security error still occurs even while the image is right there in the same directory.

The url for the image is represented as "file:///X:/..." (on my system) which is not standard perhaps but is recognised ok otherwise.

I have tried changing the image url to things like file://localhost/./sprite_menu_DT.jpg etc but nothing helps...

In the end, I assume you want this on your website, so hopefully this is not a show-stopper? Maybe there is a setting specific to ignore (for your localhost) security measures like this?
0
 

Author Comment

by:DavidInLove
ID: 39937159
"In the end, I assume you want this on your website, so hopefully this is not a show-stopper? "

Yes it is the most important, I'll take care to test that on every devices-browser  I can from my website.
Thanks really for your help!
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 39937171
Glad to help.

BTW, I looked around for the error and found most people advise to run from a web server even when doing local testing, so install Apache or IIS (express) and test via http://localhost/...
0
 

Author Comment

by:DavidInLove
ID: 39937184
OK thanks I'll try tonight home.
0
 

Author Comment

by:DavidInLove
ID: 39939178
Robert,

That is fine.
I've opened a new question related to our previous conversation.
That is to get the canvas from sprite.

But I need have a canvas from different size.

I wanted to change with CSS attributes but it doesn't work.
In the example I try to have canvas 150 / 200 with sprite image 75 / 100


Since you did this code you may be able to improve it.

How to get a canvas from sprite image with zooming


Thanks if you have an idea.

It is quite important for the site to have bigger canvas...

Happy to hear from you.


David
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
lastpass auto fill login form 5 23
Urgent Help with HTML CSS Positioning 9 20
Element alignment and word wrapping 9 24
SVG Star 4 16
Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
This article discusses four methods for overlaying images in a container on a web page
In this tutorial viewers will learn how to style transparent/translucent elements using alpha transparency in CSS Start with a normal styled element, such as a div.: Define its "background-color" property as "rgba (255, 255, 255, .5): The numbers in…
In this tutorial viewers will learn how to style a corner ribbon overlay for an image using CSS Create a new class by typing ".Ribbon":  Define the class' "display:" as "inline-block": Define its "position:" as "relative": Define its "overflow:" as …

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now