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

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

DavidInLoveAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
Robert SchuttConnect With a Mentor Software EngineerCommented:
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
 
DavidInLoveAuthor Commented:
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
 
Robert SchuttSoftware EngineerCommented:
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
Get 10% Off Your First Squarespace Website

Ready to showcase your work, publish content or promote your business online? With Squarespace’s award-winning templates and 24/7 customer service, getting started is simple. Head to Squarespace.com and use offer code ‘EXPERTS’ to get 10% off your first purchase.

 
DavidInLoveAuthor Commented:
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
 
Robert SchuttSoftware EngineerCommented:
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
 
DavidInLoveAuthor Commented:
"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
 
Robert SchuttSoftware EngineerCommented:
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
 
DavidInLoveAuthor Commented:
OK thanks I'll try tonight home.
0
 
DavidInLoveAuthor Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.