Related
I have created a paint app using JavaScript and Flask. When I store the images drawn by the user using the canvas.toDataURL() and then try to display them together in another /finish domain using the PIL, I get a black image as follows:
This is my code for storing the canvas data on the press of the Save button:
function save(){
var filename = document.getElementById("fname").value;
var data = JSON.stringify(canvas_data);
var image = canvas.toDataURL();
var targetX = document.getElementById("targetX").value;
var targetY = document.getElementById("targetY").value;
var sizeX = document.getElementById("sizeX").value;
var sizeY = document.getElementById("sizeY").value;
$.post("/", { save_fname: filename, save_cdata: data, save_image: image, save_targetX: targetX, save_targetY: targetY, save_sizeX: sizeX, save_sizeY: sizeY });
alert(filename + " saved");
document.getElementById("fname").value = ''
reset();
}
And this is the function I use for decoding the encoding:
def stringToRGB(base64_string):
imgdata = base64.b64decode(str(base64_string))
image = Image.open(io.BytesIO(imgdata))
return cv2.cvtColor(np.array(image), cv2.COLOR_BGR2RGB)
This is how I call the function:
img_arrays.append(stringToRGB(base64_string.split(',')[1]))
This is a common error that mainly has the reasons that the user is trying to save them as JPEG images or there's some error with the base54 encoding/decoding but I am not able to find out the exact issue for my code. I used a similar answer (can't find the link) to write the snippets for conversion of the base64 image to a PIL image.
Here's a sample base64 string sample:
svg_arr='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAu4AAAHCCAYAAACwm0waAAAAAXNSR0IArs4c6QAAIABJREFUeF7t3U+odXtZB/DHe6/eTLnXqNRrk5SiJhoakUKCowIdFToooSZZoJAYBA2EdCBNwkhQSJsUUgOFmijUsAItSEsnRaFN0mtZqJji1Wux6mzd7nvO2f/WWvv3fPfnhQvKu/48z+f5nbW/Z71r7/208ocAAQIECBAgQIAAgeEFnjZ8hQokQIAAAQIECBAgQKAEd4uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQIECBAQHC3BggQIECAAAECBAg0EBDcGwxJiQQIECBAgAABAgQEd2uAAAECBAgQIECAQAMBwb3BkJRIgAABAgQI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KCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgADTmLrGAAAJUklEQVQBAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnECgnvcSDVEgAABAgQIECCQKCC4J05VTwQIECBAgAABAnEC/wttGW/hY4MvrAAAAABJRU5ErkJggg=='
I'm working on a generative art project where I would like to allow users to save the resulting images from an algorithm. The general idea is:
Create an image on an HTML5 Canvas using a generative algorithm
When the image is completed, allow users to save the canvas as an image file to the server
Allow the user to either download the image or add it to a gallery of pieces of produced using the algorithm.
However, I’m stuck on the second step. After some help from Google, I found this blog post, which seemed to be exactly what I wanted:
Which led to the JavaScript code:
function saveImage() {
var canvasData = canvas.toDataURL("image/png");
var ajax = new XMLHttpRequest();
ajax.open("POST", "testSave.php", false);
ajax.onreadystatechange = function() {
console.log(ajax.responseText);
}
ajax.setRequestHeader("Content-Type", "application/upload");
ajax.send("imgData=" + canvasData);
}
and corresponding PHP (testSave.php):
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
$imageData = $GLOBALS['HTTP_RAW_POST_DATA'];
$filteredData = substr($imageData, strpos($imageData, ",") + 1);
$unencodedData = base64_decode($filteredData);
$fp = fopen('/path/to/file.png', 'wb');
fwrite($fp, $unencodedData);
fclose($fp);
}
?>
But this doesn’t seem to do anything at all.
More Googling turns up this blog post which is based off of the previous tutorial. Not very different, but perhaps worth a try:
$data = $_POST['imgData'];
$file = "/path/to/file.png";
$uri = substr($data,strpos($data, ",") + 1);
file_put_contents($file, base64_decode($uri));
echo $file;
This one creates a file (yay) but it’s corrupted and doesn’t seem to contain anything. It also appears to be empty (file size of 0).
Is there anything really obvious that I’m doing wrong? The path where I’m storing my file is writable, so that isn’t an issue, but nothing seems to be happening and I’m not really sure how to debug this.
Edit
Following Salvidor Dali’s link I changed the AJAX request to be:
function saveImage() {
var canvasData = canvas.toDataURL("image/png");
var xmlHttpReq = false;
if (window.XMLHttpRequest) {
ajax = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
}
ajax.open("POST", "testSave.php", false);
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajax.onreadystatechange = function() {
console.log(ajax.responseText);
}
ajax.send("imgData=" + canvasData);
}
And now the image file is created and isn’t empty! It seems as if the content type matters and that changing it to x-www-form-urlencoded allowed the image data to be sent.
The console returns the (rather large) string of base64 code and the datafile is ~140 kB. However, I still can’t open it and it seems to not be formatted as an image.
Here is an example of how to achieve what you need:
Draw something (taken from canvas tutorial)
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
// begin custom shape
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.fillStyle = '#8ED6FF';
context.fill();
context.strokeStyle = 'blue';
context.stroke();
</script>
Convert canvas image to URL format (base64)
// script
var dataURL = canvas.toDataURL();
Send it to your server via Ajax
$.ajax({
type: "POST",
url: "script.php",
data: {
imgBase64: dataURL
}
}).done(function(o) {
console.log('saved');
// If you want the file to be visible in the browser
// - please modify the callback in javascript. All you
// need is to return the url to the file, you just saved
// and than put the image in your browser.
});
Save base64 on your server as an image (here is how to do this in PHP, the same ideas is in every language. Server side in PHP can be found here):
I played with this two weeks ago, it's very simple. The only problem is that all the tutorials just talk about saving the image locally. This is how I did it:
1) I set up a form so I can use a POST method.
2) When the user is done drawing, he can click the "Save" button.
3) When the button is clicked I take the image data and put it into a hidden field. After that I submit the form.
document.getElementById('my_hidden').value = canvas.toDataURL('image/png');
document.forms["form1"].submit();
4) When the form is submited I have this small php script:
<?php
$upload_dir = somehow_get_upload_dir(); //implement this function yourself
$img = $_POST['my_hidden'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = $upload_dir."image_name.png";
$success = file_put_contents($file, $data);
header('Location: '.$_POST['return_url']);
?>
I think you should convert the image to base64 and then to Blob and send it to the server. When you use base64 images, a lot of lines will be sent to server. With blob, it's only the file.
You can use this code bellow:
function dataURLtoBlob(dataURL) {
let array, binary, i, len;
binary = atob(dataURL.split(',')[1]);
array = [];
i = 0;
len = binary.length;
while (i < len) {
array.push(binary.charCodeAt(i));
i++;
}
return new Blob([new Uint8Array(array)], {
type: 'image/png'
});
};
And canvas code here:
const canvas = document.getElementById('canvas');
const file = dataURLtoBlob( canvas.toDataURL() );
After that you can use ajax with Form:
const fd = new FormData;
fd.append('image', file);
$.ajax({
type: 'POST',
url: '/url-to-save',
data: fd,
processData: false,
contentType: false
});
The code in CoffeeScript syntax:
dataURLtoBlob = (dataURL) ->
# Decode the dataURL
binary = atob(dataURL.split(',')[1])
# Create 8-bit unsigned array
array = []
i = 0
while i < binary.length
array.push binary.charCodeAt(i)
i++
# Return our Blob object
new Blob([ new Uint8Array(array) ], type: 'image/png')
And canvas code here:
canvas = document.getElementById('canvas')
file = dataURLtoBlob(canvas.toDataURL())
After that you can use ajax with Form:
fd = new FormData
# Append our Canvas image file to the form data
fd.append 'image', file
$.ajax
type: 'POST'
url: '/url-to-save'
data: fd
processData: false
contentType: false
Send canvas image to PHP:
var photo = canvas.toDataURL('image/jpeg');
$.ajax({
method: 'POST',
url: 'photo_upload.php',
data: {
photo: photo
}
});
Here's PHP script:
photo_upload.php
<?php
$data = $_POST['photo'];
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
mkdir($_SERVER['DOCUMENT_ROOT'] . "/photos");
file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/photos/".time().'.png', $data);
die;
?>
I've worked on something similar.
Had to convert canvas Base64-encoded image to Uint8Array Blob.
function b64ToUint8Array(b64Image) {
var img = atob(b64Image.split(',')[1]);
var img_buffer = [];
var i = 0;
while (i < img.length) {
img_buffer.push(img.charCodeAt(i));
i++;
}
return new Uint8Array(img_buffer);
}
var b64Image = canvas.toDataURL('image/jpeg');
var u8Image = b64ToUint8Array(b64Image);
var formData = new FormData();
formData.append("image", new Blob([ u8Image ], {type: "image/jpg"}));
var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/upload", true);
xhr.send(formData);
If you want to save data that is derived from a Javascript canvas.toDataURL() function, you have to convert blanks into plusses. If you do not do that, the decoded data is corrupted:
<?php
$encodedData = str_replace(' ','+',$encodedData);
$decocedData = base64_decode($encodedData);
?>
http://php.net/manual/ro/function.base64-decode.php
In addition to Salvador Dali's answer:
on the server side don't forget that the data comes in base64 string format. It's important because in some programming languages you need to explisitely say that this string should be regarded as bytes not simple Unicode string.
Otherwise decoding won't work: the image will be saved but it will be an unreadable file.
I just made an imageCrop and Upload feature with
https://www.npmjs.com/package/react-image-crop
to get the ImagePreview ( the cropped image rendering in a canvas)
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
canvas.toBlob(function(blob){...}, 'image/jpeg', 0.95);
I prefer sending data in blob with content type image/jpeg rather than toDataURL ( a huge base64 string`
My implementation for uploading to Azure Blob using SAS URL
axios.post(azure_sas_url, image_in_blob, {
headers: {
'x-ms-blob-type': 'BlockBlob',
'Content-Type': 'image/jpeg'
}
})
I know how to load image from data uri into fabric js. But i am not able to figure out how to load image if the data uri is coming from another url. I have a PHP script which accepts the image URL and returns the base64 image data.
<?php
$path = $_REQUEST['url'];
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = file_get_contents($path);
$base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);
echo $base64;
?>
Lets assume the url is http://example.com/encodeImage.php?url=http://example.com/image.png. I am trying to use this URL into this function
fabric.Image.fromURL('http://example.com/encodeImage.php?url=http://example.com/image.png', function(img) {
But it is not able to load the image. In the console it says unable to load the image
Is it something even possible to do with fabric js?
Add image in this way:
var img = new Image();
img.onload = function () {
var imgbase64 = new fabric.Image(img, {
scaleX: 0.2,
scaleY: 0.2
})
canvas.add(imgbase64);
canvas.deactivateAll().renderAll();
}
$.ajax({url: "http://example.com/encodeImage.php?url=http://example.com/image.png", success: function(result){
img.src = result;
}});
fabric.Image.fromURL(url, function (img, callback) {
img.id = imageId;
img.filters = [new fabric.Image.filters.HueRotation()];
img.applyFilters()
var cor = img.set(
{
left: left,
top: top,
selectable: false,
}
)
canvas.add(img);
});
I'm working on a generative art project where I would like to allow users to save the resulting images from an algorithm. The general idea is:
Create an image on an HTML5 Canvas using a generative algorithm
When the image is completed, allow users to save the canvas as an image file to the server
Allow the user to either download the image or add it to a gallery of pieces of produced using the algorithm.
However, I’m stuck on the second step. After some help from Google, I found this blog post, which seemed to be exactly what I wanted:
Which led to the JavaScript code:
function saveImage() {
var canvasData = canvas.toDataURL("image/png");
var ajax = new XMLHttpRequest();
ajax.open("POST", "testSave.php", false);
ajax.onreadystatechange = function() {
console.log(ajax.responseText);
}
ajax.setRequestHeader("Content-Type", "application/upload");
ajax.send("imgData=" + canvasData);
}
and corresponding PHP (testSave.php):
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
$imageData = $GLOBALS['HTTP_RAW_POST_DATA'];
$filteredData = substr($imageData, strpos($imageData, ",") + 1);
$unencodedData = base64_decode($filteredData);
$fp = fopen('/path/to/file.png', 'wb');
fwrite($fp, $unencodedData);
fclose($fp);
}
?>
But this doesn’t seem to do anything at all.
More Googling turns up this blog post which is based off of the previous tutorial. Not very different, but perhaps worth a try:
$data = $_POST['imgData'];
$file = "/path/to/file.png";
$uri = substr($data,strpos($data, ",") + 1);
file_put_contents($file, base64_decode($uri));
echo $file;
This one creates a file (yay) but it’s corrupted and doesn’t seem to contain anything. It also appears to be empty (file size of 0).
Is there anything really obvious that I’m doing wrong? The path where I’m storing my file is writable, so that isn’t an issue, but nothing seems to be happening and I’m not really sure how to debug this.
Edit
Following Salvidor Dali’s link I changed the AJAX request to be:
function saveImage() {
var canvasData = canvas.toDataURL("image/png");
var xmlHttpReq = false;
if (window.XMLHttpRequest) {
ajax = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
}
ajax.open("POST", "testSave.php", false);
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajax.onreadystatechange = function() {
console.log(ajax.responseText);
}
ajax.send("imgData=" + canvasData);
}
And now the image file is created and isn’t empty! It seems as if the content type matters and that changing it to x-www-form-urlencoded allowed the image data to be sent.
The console returns the (rather large) string of base64 code and the datafile is ~140 kB. However, I still can’t open it and it seems to not be formatted as an image.
Here is an example of how to achieve what you need:
Draw something (taken from canvas tutorial)
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
// begin custom shape
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.fillStyle = '#8ED6FF';
context.fill();
context.strokeStyle = 'blue';
context.stroke();
</script>
Convert canvas image to URL format (base64)
// script
var dataURL = canvas.toDataURL();
Send it to your server via Ajax
$.ajax({
type: "POST",
url: "script.php",
data: {
imgBase64: dataURL
}
}).done(function(o) {
console.log('saved');
// If you want the file to be visible in the browser
// - please modify the callback in javascript. All you
// need is to return the url to the file, you just saved
// and than put the image in your browser.
});
Save base64 on your server as an image (here is how to do this in PHP, the same ideas is in every language. Server side in PHP can be found here):
I played with this two weeks ago, it's very simple. The only problem is that all the tutorials just talk about saving the image locally. This is how I did it:
1) I set up a form so I can use a POST method.
2) When the user is done drawing, he can click the "Save" button.
3) When the button is clicked I take the image data and put it into a hidden field. After that I submit the form.
document.getElementById('my_hidden').value = canvas.toDataURL('image/png');
document.forms["form1"].submit();
4) When the form is submited I have this small php script:
<?php
$upload_dir = somehow_get_upload_dir(); //implement this function yourself
$img = $_POST['my_hidden'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = $upload_dir."image_name.png";
$success = file_put_contents($file, $data);
header('Location: '.$_POST['return_url']);
?>
I think you should convert the image to base64 and then to Blob and send it to the server. When you use base64 images, a lot of lines will be sent to server. With blob, it's only the file.
You can use this code bellow:
function dataURLtoBlob(dataURL) {
let array, binary, i, len;
binary = atob(dataURL.split(',')[1]);
array = [];
i = 0;
len = binary.length;
while (i < len) {
array.push(binary.charCodeAt(i));
i++;
}
return new Blob([new Uint8Array(array)], {
type: 'image/png'
});
};
And canvas code here:
const canvas = document.getElementById('canvas');
const file = dataURLtoBlob( canvas.toDataURL() );
After that you can use ajax with Form:
const fd = new FormData;
fd.append('image', file);
$.ajax({
type: 'POST',
url: '/url-to-save',
data: fd,
processData: false,
contentType: false
});
The code in CoffeeScript syntax:
dataURLtoBlob = (dataURL) ->
# Decode the dataURL
binary = atob(dataURL.split(',')[1])
# Create 8-bit unsigned array
array = []
i = 0
while i < binary.length
array.push binary.charCodeAt(i)
i++
# Return our Blob object
new Blob([ new Uint8Array(array) ], type: 'image/png')
And canvas code here:
canvas = document.getElementById('canvas')
file = dataURLtoBlob(canvas.toDataURL())
After that you can use ajax with Form:
fd = new FormData
# Append our Canvas image file to the form data
fd.append 'image', file
$.ajax
type: 'POST'
url: '/url-to-save'
data: fd
processData: false
contentType: false
Send canvas image to PHP:
var photo = canvas.toDataURL('image/jpeg');
$.ajax({
method: 'POST',
url: 'photo_upload.php',
data: {
photo: photo
}
});
Here's PHP script:
photo_upload.php
<?php
$data = $_POST['photo'];
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
mkdir($_SERVER['DOCUMENT_ROOT'] . "/photos");
file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/photos/".time().'.png', $data);
die;
?>
I've worked on something similar.
Had to convert canvas Base64-encoded image to Uint8Array Blob.
function b64ToUint8Array(b64Image) {
var img = atob(b64Image.split(',')[1]);
var img_buffer = [];
var i = 0;
while (i < img.length) {
img_buffer.push(img.charCodeAt(i));
i++;
}
return new Uint8Array(img_buffer);
}
var b64Image = canvas.toDataURL('image/jpeg');
var u8Image = b64ToUint8Array(b64Image);
var formData = new FormData();
formData.append("image", new Blob([ u8Image ], {type: "image/jpg"}));
var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/upload", true);
xhr.send(formData);
If you want to save data that is derived from a Javascript canvas.toDataURL() function, you have to convert blanks into plusses. If you do not do that, the decoded data is corrupted:
<?php
$encodedData = str_replace(' ','+',$encodedData);
$decocedData = base64_decode($encodedData);
?>
http://php.net/manual/ro/function.base64-decode.php
In addition to Salvador Dali's answer:
on the server side don't forget that the data comes in base64 string format. It's important because in some programming languages you need to explisitely say that this string should be regarded as bytes not simple Unicode string.
Otherwise decoding won't work: the image will be saved but it will be an unreadable file.
I just made an imageCrop and Upload feature with
https://www.npmjs.com/package/react-image-crop
to get the ImagePreview ( the cropped image rendering in a canvas)
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
canvas.toBlob(function(blob){...}, 'image/jpeg', 0.95);
I prefer sending data in blob with content type image/jpeg rather than toDataURL ( a huge base64 string`
My implementation for uploading to Azure Blob using SAS URL
axios.post(azure_sas_url, image_in_blob, {
headers: {
'x-ms-blob-type': 'BlockBlob',
'Content-Type': 'image/jpeg'
}
})
I'm working on a generative art project where I would like to allow users to save the resulting images from an algorithm. The general idea is:
Create an image on an HTML5 Canvas using a generative algorithm
When the image is completed, allow users to save the canvas as an image file to the server
Allow the user to either download the image or add it to a gallery of pieces of produced using the algorithm.
However, I’m stuck on the second step. After some help from Google, I found this blog post, which seemed to be exactly what I wanted:
Which led to the JavaScript code:
function saveImage() {
var canvasData = canvas.toDataURL("image/png");
var ajax = new XMLHttpRequest();
ajax.open("POST", "testSave.php", false);
ajax.onreadystatechange = function() {
console.log(ajax.responseText);
}
ajax.setRequestHeader("Content-Type", "application/upload");
ajax.send("imgData=" + canvasData);
}
and corresponding PHP (testSave.php):
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
$imageData = $GLOBALS['HTTP_RAW_POST_DATA'];
$filteredData = substr($imageData, strpos($imageData, ",") + 1);
$unencodedData = base64_decode($filteredData);
$fp = fopen('/path/to/file.png', 'wb');
fwrite($fp, $unencodedData);
fclose($fp);
}
?>
But this doesn’t seem to do anything at all.
More Googling turns up this blog post which is based off of the previous tutorial. Not very different, but perhaps worth a try:
$data = $_POST['imgData'];
$file = "/path/to/file.png";
$uri = substr($data,strpos($data, ",") + 1);
file_put_contents($file, base64_decode($uri));
echo $file;
This one creates a file (yay) but it’s corrupted and doesn’t seem to contain anything. It also appears to be empty (file size of 0).
Is there anything really obvious that I’m doing wrong? The path where I’m storing my file is writable, so that isn’t an issue, but nothing seems to be happening and I’m not really sure how to debug this.
Edit
Following Salvidor Dali’s link I changed the AJAX request to be:
function saveImage() {
var canvasData = canvas.toDataURL("image/png");
var xmlHttpReq = false;
if (window.XMLHttpRequest) {
ajax = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
}
ajax.open("POST", "testSave.php", false);
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajax.onreadystatechange = function() {
console.log(ajax.responseText);
}
ajax.send("imgData=" + canvasData);
}
And now the image file is created and isn’t empty! It seems as if the content type matters and that changing it to x-www-form-urlencoded allowed the image data to be sent.
The console returns the (rather large) string of base64 code and the datafile is ~140 kB. However, I still can’t open it and it seems to not be formatted as an image.
Here is an example of how to achieve what you need:
Draw something (taken from canvas tutorial)
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
// begin custom shape
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.fillStyle = '#8ED6FF';
context.fill();
context.strokeStyle = 'blue';
context.stroke();
</script>
Convert canvas image to URL format (base64)
// script
var dataURL = canvas.toDataURL();
Send it to your server via Ajax
$.ajax({
type: "POST",
url: "script.php",
data: {
imgBase64: dataURL
}
}).done(function(o) {
console.log('saved');
// If you want the file to be visible in the browser
// - please modify the callback in javascript. All you
// need is to return the url to the file, you just saved
// and than put the image in your browser.
});
Save base64 on your server as an image (here is how to do this in PHP, the same ideas is in every language. Server side in PHP can be found here):
I played with this two weeks ago, it's very simple. The only problem is that all the tutorials just talk about saving the image locally. This is how I did it:
1) I set up a form so I can use a POST method.
2) When the user is done drawing, he can click the "Save" button.
3) When the button is clicked I take the image data and put it into a hidden field. After that I submit the form.
document.getElementById('my_hidden').value = canvas.toDataURL('image/png');
document.forms["form1"].submit();
4) When the form is submited I have this small php script:
<?php
$upload_dir = somehow_get_upload_dir(); //implement this function yourself
$img = $_POST['my_hidden'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = $upload_dir."image_name.png";
$success = file_put_contents($file, $data);
header('Location: '.$_POST['return_url']);
?>
I think you should convert the image to base64 and then to Blob and send it to the server. When you use base64 images, a lot of lines will be sent to server. With blob, it's only the file.
You can use this code bellow:
function dataURLtoBlob(dataURL) {
let array, binary, i, len;
binary = atob(dataURL.split(',')[1]);
array = [];
i = 0;
len = binary.length;
while (i < len) {
array.push(binary.charCodeAt(i));
i++;
}
return new Blob([new Uint8Array(array)], {
type: 'image/png'
});
};
And canvas code here:
const canvas = document.getElementById('canvas');
const file = dataURLtoBlob( canvas.toDataURL() );
After that you can use ajax with Form:
const fd = new FormData;
fd.append('image', file);
$.ajax({
type: 'POST',
url: '/url-to-save',
data: fd,
processData: false,
contentType: false
});
The code in CoffeeScript syntax:
dataURLtoBlob = (dataURL) ->
# Decode the dataURL
binary = atob(dataURL.split(',')[1])
# Create 8-bit unsigned array
array = []
i = 0
while i < binary.length
array.push binary.charCodeAt(i)
i++
# Return our Blob object
new Blob([ new Uint8Array(array) ], type: 'image/png')
And canvas code here:
canvas = document.getElementById('canvas')
file = dataURLtoBlob(canvas.toDataURL())
After that you can use ajax with Form:
fd = new FormData
# Append our Canvas image file to the form data
fd.append 'image', file
$.ajax
type: 'POST'
url: '/url-to-save'
data: fd
processData: false
contentType: false
Send canvas image to PHP:
var photo = canvas.toDataURL('image/jpeg');
$.ajax({
method: 'POST',
url: 'photo_upload.php',
data: {
photo: photo
}
});
Here's PHP script:
photo_upload.php
<?php
$data = $_POST['photo'];
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
mkdir($_SERVER['DOCUMENT_ROOT'] . "/photos");
file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/photos/".time().'.png', $data);
die;
?>
I've worked on something similar.
Had to convert canvas Base64-encoded image to Uint8Array Blob.
function b64ToUint8Array(b64Image) {
var img = atob(b64Image.split(',')[1]);
var img_buffer = [];
var i = 0;
while (i < img.length) {
img_buffer.push(img.charCodeAt(i));
i++;
}
return new Uint8Array(img_buffer);
}
var b64Image = canvas.toDataURL('image/jpeg');
var u8Image = b64ToUint8Array(b64Image);
var formData = new FormData();
formData.append("image", new Blob([ u8Image ], {type: "image/jpg"}));
var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/upload", true);
xhr.send(formData);
If you want to save data that is derived from a Javascript canvas.toDataURL() function, you have to convert blanks into plusses. If you do not do that, the decoded data is corrupted:
<?php
$encodedData = str_replace(' ','+',$encodedData);
$decocedData = base64_decode($encodedData);
?>
http://php.net/manual/ro/function.base64-decode.php
In addition to Salvador Dali's answer:
on the server side don't forget that the data comes in base64 string format. It's important because in some programming languages you need to explisitely say that this string should be regarded as bytes not simple Unicode string.
Otherwise decoding won't work: the image will be saved but it will be an unreadable file.
I just made an imageCrop and Upload feature with
https://www.npmjs.com/package/react-image-crop
to get the ImagePreview ( the cropped image rendering in a canvas)
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob
canvas.toBlob(function(blob){...}, 'image/jpeg', 0.95);
I prefer sending data in blob with content type image/jpeg rather than toDataURL ( a huge base64 string`
My implementation for uploading to Azure Blob using SAS URL
axios.post(azure_sas_url, image_in_blob, {
headers: {
'x-ms-blob-type': 'BlockBlob',
'Content-Type': 'image/jpeg'
}
})