How to save a canvas in an image on the server

Posted on 2014-03-19
Medium Priority
Last Modified: 2014-03-24

Going on with canvas now I want to save my canvas that I've created on the server in an image.

Here is the code that enables me to have the data of the canvas

var canvas = document.getElementById("myCanvas_OUT0");
var context = canvas.getContext("2d");
var pixout0 = context.getImageData(0, 0, 75, 100).data;

Open in new window

Does some one know how to convert this in a png or jpeg image and save it in a directory please?

Question by:DavidInLove
  • 5
  • 4
  • 2
LVL 111

Expert Comment

by:Ray Paseur
ID: 39939259
Please give us a bit of help with your question.  Set up the SSCCE* so that we can copy / paste your code into our code editors and save it on our servers.  Then we can run it and get the same results you get.  Once we have that foundation we can experiment with the test case and collaborate on a solution.  

Thanks, ~Ray

* Required reading for software developers!

Author Comment

ID: 39941917
HI here is a working code to create the canvas and get back the data.

I just now want to save it in an image on the server.

Thanks for your attention!

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

I want to save the canvas created in an image on the server when I click on it </br>

<canvas id="myCanvas_OUT21" width="75" height="100"></canvas>


var contextout0, contextout21;

	$("#myCanvas_OUT21").click ( function()
		alert("Here I want to save the canvas created in an image on the server");
		//Here is the data of the canvas How can I convert it in an image and save it on the server?
		var canvas = document.getElementById("myCanvas_OUT21");
		var context = canvas.getContext("2d");
		var pixout21 = context.getImageData(0, 0, 75, 100).data;


$("document").ready( function() {  

	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();

	//This I do here in a simple example 
			if (j%5)
			pixout21[j]=255 ;		
			pixout21[j+2]=255 ;		

			pixout21[j]=100/3 ;		
			pixout21[j+1]=100[j+1]/3 ;		
			pixout21[j+2]=100[j+2]/3 ;		
	//DISPLAY DATA IN The myCanvas_OUT21
		contextout21.putImageData(imgdout21, 0, 0);



Open in new window

LVL 111

Expert Comment

by:Ray Paseur
ID: 39942892
This will take me a while, but it's a great question and I'm fairly certain I can produce a demonstration script from the code you've provided.  The theory is this: Each pixel of the canvas is a pixel of the image.  Each pixel has 4 channels: Red, Green, Blue and Alpha (transparency).  The pixels are numbered from zero to "n" in modulo 4.  Pixel zero at the top left has 4 bytes associated with it, one for each channel. Pixel one, immediately to the right of pixel zero, has the next 4 bytes, etc.  To make an image in PHP you will have to know the canvas dimensions, width and height, so you can create an image resource of the correct dimensions.  Then it's just a matter of filling in the pixels of the image resource one at a time with the appropriate color and transparency.

In PHP the alpha channel values only go up to 127 (not 255) so that bit of data has to be interpolated.  My guess is that the RGB values are consistent across JS and PHP.
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.


Author Comment

ID: 39944787
Thanks for your time!

On the internet I see people speak of  base64_encode($str);  that seems to tell about image
coding but I don't know really what it is.

Wait a little I've found some code that create an image to download it from canvas.
Only I would like also to store it in a directory

I will put the PHP code tonight in this post.
You may find an easy way to store the image created on the server and not only download it.

Happy to hear from you!
LVL 111

Expert Comment

by:Ray Paseur
ID: 39945387
I've gotten some of this into a "sensible" model, but not all of it.  There may be a setting in my server that is causing trouble and more research is needed to figure that out.

I can capture the data from the canvas in four-byte chunks giving R, G, B, and A values.  But when I try to send this data to my server with an AJAX request, I only get the first 5,000 elements in the $_POST array.  I may need some other form of encoding to get all 30,000 of the data elements from the canvas in this test case.

I do not believe that base64_encode() is needed here.

More to follow...
LVL 35

Accepted Solution

Slick812 earned 2000 total points
ID: 39945608
greetings DavidInLove, this is not very difficult to do , , IF the many browsers out there would have a reasonable working javascript for the canvas.toDataURL() method, but due to different versions and browsers (this is a very recent addition to the canvas spec) it is not consistent.
Anyway there is a google code that can do this to get a base64 png file, it is called by -
<script src="http://todataurl-png-js.googlecode.com/svn/trunk/todataurl.js"></script>

below are two working Files to use this thing , first a html file, that is the canvas file -
<!doctype html><html><head><title>Canvas to PNG</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<script src="http://todataurl-png-js.googlecode.com/svn/trunk/todataurl.js"></script>
<script>/* <![CDATA[ */
function draw_square() {
   ctx.fillStyle = "#f08";
   ctx.fillRect(5, 5, 13, 13);
   var td = can.toDataURL();// h 22
   td = td.substr(22);//,iVBOR
   //alert(td.length+":length "+td);
   document.getElementById("ih").value = td;
/* ]]> */</script></head>
<canvas id="cv1" width="25" height="25" style="width:56px;height:56px;border:2px solid black;"></canvas><button id="bt1" onclick="draw_square();">CanvasUR</button>
<form name="pngF" action="canpng.php" method="post">
<input id="ih" type="hidden" name="png" value=" " />
<script>/* <![CDATA[ */
var can = document.getElementById("cv1");
var ctx = can.getContext("2d");
ctx.fillStyle = "#cdf";
ctx.fillRect(0, 0, 25, 25);
/* ]]> */</script>

Open in new window

next is the PHP file named canpng.php , It gets the base64 and writes it to a png file , shown on the return PHP page-
<!doctype html><html><head><title>Canvas to PNG PHP</title>
<body><h3>Canvas to PNG PHP</h3>
<?php ini_set("display_errors",1); error_reporting(E_ALL);

$png64 = (empty($_POST['png'])) ? 0 : $_POST['png'];
if (!$png64) {
  echo '<b>ERROR, the PNG base64 was NOT SENT in post!</b><br />';

$png64 = base64_decode($png64);
file_put_contents('canpng1.png', $png64);

/* below code if you want to experiment
$size_info = getimagesizefromstring($png64);
if (!$size_info) {
  echo '<b>ERROR, the PNG Image Data is Corupt</b><br />';
echo '<p>png Image height is '.$size_info[1].', width is '.$size_info[0].'</p><hr>';

$im = imagecreatefromstring($png64);
if ($im !== false) {
  }else echo 'An error occurred in imagecreatefromstring().';
<img src="canpng1.png" />

Open in new window

These two file work on my server.
ask questions if you need more information.

Author Closing Comment

ID: 39945789
Thanks Slick812,

Your solution works perfectly on my server too!

Sorry for other EE contribution but I must give all the points here to stay honest.

LVL 111

Expert Comment

by:Ray Paseur
ID: 39946585
Glad you're OK with the solution.  But I found that the images looked different after the transfer to the server.  Using Chrome at latest release.
LVL 35

Expert Comment

ID: 39947832
@ray, they are suppose to look different, examine the -
<canvas id="cv1" width="25" height="25" style="width:56px;height:56px;border:2px solid black;"></canvas>

which increases the actual height and width from 25 pixels to a displayed of 56 pixels

if you look at the javascript I add a violet-red rectangle to canvas just before server send.

I use a small canvas 25x25 just so I do not have to deal with large string debug for development.

works great in my chrome. If not work, do you have a fix?
LVL 111

Expert Comment

by:Ray Paseur
ID: 39947946
Hey, Slick812 - it's not up to me.  If the answer is good for the Author of the question, that's fine.  I was only offering an observation that the image in the canvas and the image stored on my server looked different.  Whether that's a "bug" or a "feature" is open to interpretation.  As long as the Author is happy, I'm happy.

Author Comment

ID: 39949707
I've included it in my website and haven't seen really buggs too.
It is true that I haven't tested all the browsers...
But It's OK for me.
Best regards
Thanks to both of you.

Featured Post

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.

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.

Join & Write a Comment

There are times when I have encountered the need to decompress a response from a PHP request. This is how it's done, but you must have control of the request and you can set the Accept-Encoding header.
I recently worked on a Wordpress site that utilized the popular ContactForm7 (https://contactform7.com/) plug-in that only sends an email and does not save data. The client wanted the data saved to a custom CRM database. This is my solution.
In this tutorial viewers will learn how to style elements, such a divs, with a "drop shadow" effect using the CSS box-shadow property Start with a normal styled element, such as a div.: In the element's style, type the box shadow property: "box-shad…
In this tutorial viewers will learn how to embed videos in a webpage using HTML5. Ensure your DOCTYPE declaration is set to HTML5: "<!DOCTYPE html>": Use the <video> tag to insert a video. Define the src as the URL of your video; this is similar to …

597 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