Solved

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

Posted on 2014-03-17
9
280 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
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 

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
 
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

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article discusses how to create an extensible mechanism for linked drop downs.
Is your Office 365 signature not working the way you want it to? Are signature updates taking up too much of your time? Let's run through the most common problems that an IT administrator can encounter when dealing with Office 365 email signatures.
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…
The viewer will receive an overview of the basics of CSS showing inline styles. In the head tags set up your style tags: (CODE) Reference the nav tag and set your properties.: (CODE) Set the reference for the UL element and styles for it to ensu…

825 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