Saving canvas with background image to server with html2canvas - javascript

I currently have a script that successfully creates an image from canvas including its containing Div background image by using html2canvas. I also have a script that can save the canvas as an image to the server using the canvas2image plugin but the background doesn't show up.
The problem I'm having is when I try to combine the two so that I can save the Div bg and canvas as an image to the server, nothing happens which I believe is due to the canvas2image plugin not firing.
The code I have with both plugins combined is here.
function exportAndSaveCanvas() {
html2canvas($("#containingDiv"), {
background:'#fff',
onrendered: function(canvas) {
// var imgData = canvas.toDataURL('image/jpeg'); <--This would create the image needed
//but I replaced with the line below to tie in the two plugins
var screenshot = Canvas2Image.saveAsPNG(canvas, true);
canvas.parentNode.appendChild(screenshot);
screenshot.id = "canvasimage";
data = $('#canvasimage').attr('src');
canvas.parentNode.removeChild(screenshot);
// Send the screenshot to PHP to save it on the server
var url = 'upload/export.php';
$.ajax({
type: "POST",
url: url,
dataType: 'text',
data: {
base64data : data
}
});
}
});
}
The code for export.php which upload the image to the server is here
<?php
$data = $_REQUEST['base64data'];
//echo $data;
$image = explode('base64,',$data);
file_put_contents('../uploadimg/myImage.jpg', base64_decode($image[1]));
?>
I was hoping to be able to combine the two plugins to work together and get my canvas with Div background save to the server but it looks like the canvas2image plugin doesn't fire.
Thanks!

Write the background image into the canvas before you write the other image. The MDN page about writing an image to a canvas should have you covered: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images
As an aside, I'm not sure why you're using a plugin to do anything you get for free with the native canvas API.

dtanders said "As an aside, I'm not sure why you're using a plugin to do anything you get for free with the native canvas API."
This got me thinking that I was making it more difficult than it needed to be so I stripped away some code. The script below does just what I need.
function exportAndSaveCanvas() {
html2canvas($("#containingDiv"), {
background:'#fff',
onrendered: function(canvas) {
var imgData = canvas.toDataURL('image/jpeg');
var url = 'upload/export.php';
$.ajax({
type: "POST",
url: url,
dataType: 'text',
data: {
base64data : imgData
}
});
}
}); //End html2canvas
} // End exportAndSaveCanvas()

Related

Can't post larg canvas image via jquery to server side

Here my jquery code:
var image = document.getElementById("canvas").toDataURL("image/png");
$.ajax({
type: "POST",
url: "imageup.php",
data: {image:image, title:getTitle, infos:informations},
success: function (response) {
alert(response);
}
});
For small images this work perfectly, but when i use a larg image, i odn't get the full base64 code of the image itself !
I tried this solution here:
https://stackoverflow.com/a/5061163/7232957
I devided the base64 image into many part and add them into array, and then send it to server side ! but all time same thing ! not get the full image.
Any one have a trick in order to solve this annoying problem ?
Is there a way to send html5 canvas image as file to server side ?
I already configured my apache server:
post_max_size = 500 Mo
upload_max_filesize = 500 Mo

Save a canvas as an image to the server in ASP.net

I have a page with a google map in it and some data in a couple of divs, I need the user to click "Grab Screenshot" button and that should save the screenshot of the user's page and save it to the server.
I tried through Html2Canvas, but it is not allowing me to convert canvas to dataurl i.e in my javascript function, I used this:
function GenerateImage()
{
html2canvas($('#mainDiv'), {
onrendered: function(canvas) {
//this appends the canvas(screenshot) to the page, this is working fine
document.body.appendChild(canvas);
//this is not working,
//Error: SecurityError: The operation is insecure.
var image = canvas.toDataURL('image/png');
image.crossOrigin = 'anonymous';
var imgdata = image.replace(/^data:image\/(png|jpg);base64,/, '');
$.ajax({
url: '******',
data: {
imgdata:imgdata
},
type: 'post',
success: function (response) {
console.log('Success');
}
});
}
});
}
I did research, I found out it is some CORS issue, but I am unable to figure out a solution.
So, I was wondering if I can do a screenshot using ASP.net, is that possible? Thanks in advance.
I was able to successfully do it using the proxy. I had an issue with a custom marker icon from a different website on the map. That was causing the canvas to taint. I moved the image to my website and changed the path, the "tainted canvases may not be exported" error went away.

Get img from DOM and upload it via ajax

How can I get an image from DOM and then upload it via ajax?
my_img_ele = document.getElementById("my_img");
This is the ajax call
var xmlHttp=new XMLHttpRequest();
xmlHttp.open("POST", "site", true);
var formData = new FormData();
formData.append(IMG_HERE);
xmlHttp.send(formData);
What I have been doing is just sending the url and then looking up the image server side. But I figure this will be quicker.
EDIT: Note that the user is not uploading an image via a form. It's an img element.
If you were asking "upload images via AJAX", using the FormData the answer can be simpler and easily searchable on the internet.
Kindly see if this link addresses your question.
To get an image from the DOM, you would use the same above. But instead of submitting the form, you would be reading the DOM img element as a dataURI.
Check the FIDDLE for the following code's HTML:
var originalImage = document.getElementById("image"),
canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
formdata = false,
dummy = document.getElementById('dummy'),
newImage = new Image();
if (window.FormData) {
formdata = new FormData();
}
newImage.onload = function(){
// width and height here should be the same as original image
// detect before-hand, using jQuery(el).width() /.height() on the DOM element
context.drawImage(newImage, 0, 0, 400, 300);
}
newImage.src = originalImage.src;
// traditional ajax and jQuery, no HTML5
if (formdata) {
var canvasToDURI = canvas.toDataURL();
formdata.append("image-data", canvasToDURI);
// yay!, jQuery
$.ajax({
url: "upload.php",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success: function (res) {
// do some thing !
dummy.innerText = 'Image data sent !';
},
error: function(a, b, c) {
dummy.innerText = 'The following data was not sent due to : ' + b + ' -- '+ c + ' \n\n' + canvasToDURI;
}
});
}
If FormData is also not supported, you can create a form element and change the enctype of the form to "multipart/form-data" and send the data using JavaScript in an AJAX call, without submitting the form.
Your figure is obviously wrong. Here's the thing, an image element is nothing else than a DOM node, containing the URL of the image, the image itself get downloaded by the browser, so on a client machine it's only available in the browser memory. And even is somehow you gain acces to the browser memory (cache), consider that based on the clients connection it is highly probable that uploading it from there is way slower than dowloading it server side from the original source. The other solution is that you download the image based on the URL (img.src) via ajax get simply detour it with an other ajax in the first ones callback, but it's of course means that the image travels averagely two times more.

javascript resize image [reduce size] and upload

Is it possible to resize the image with javascript or Flash ?
My requirement:
A user uploading a image with 10MB in size,i want to re size the image on client side using Javascript or flash,after resizing the image,it need to be uploaded to the server.
If it is possible i can save the bandwidth.
I am using uploadify for upload images and Codeigniter on the Server Side.
is there any other methods to do this ?
Note : Reference to some Libraries are really helpful.
Thank you.
Yes, it is possible in Flash Player 10 and later.
This is an old blog post, from when Flash Player 10 and the FileReference.load() function was new, back in 2008, and it doesn't cover all steps needed, but it's a start:
http://www.mikechambers.com/blog/2008/08/20/reading-and-writing-local-files-in-flash-player-10/
You would probably also need to look into how to resize a bitmap in ActionScript, how to encode the bitmap as JPEG or PNG (using as3corelib) and how to upload the result to the server.
Edit: http://www.plupload.com seems to have support for resizing. There's also http://resize-before-upload.com/
Yes it's possible to resize an image in javascript using the HTML5 canvas API. You, however, will need to save it somewhere after being resized.
The first API you will need to check is drawImage.
The second one is toDataURL.
Depending on what you want to do, you can either:
Make the user save the smaller image using this client side script.
Store it yourself using a server-side language, to convert a Base64 Encoded Image to an actual image file, and save it on your server. Check out Example 1.
Example 1: PHP5 based solution:
<?php
define('UPLOAD_DIR', 'images/');
$img = $_POST['img'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.png';
$success = file_put_contents($file, $data);
print $success ? $file : 'Unable to save the file.';
?>
UPDATE #2:
As stated in the comments below, this method requires a modern browser that supports File APIs to work. Use the flash method instead to support both modern and non-html5 browsers.
If you using JSON to upload use the following code
function UploadPhoto(img) {
var uri = "http://domain/App/AppService.svc/GetImg/New";
var imgElem = document.getElementById(img);
var imgData = JSON.stringify(getBase64Image(imgElem));
alert(imgData);
$.ajax({
url: uri,
contentType: 'application/json',
dataType: 'json',
type: 'POST',
data: imgData,
error: function () {
alert('failed');
},
success: function () {
alert('Sucess');
}
});
}
function getBase64Image(imgElem) {
var width = 100;
var height = 150;
// imgElem must be on the same server otherwise a cross-origin error will be thrown "SECURITY_ERR: DOM Exception 18"
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(imgElem, 0, 0, width, height);
ctx.scale(width, height)
var dataURL = canvas.toDataURL("image/png");
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

Image resizing client-side with JavaScript before upload to the server

I am looking for a way to resize an image client-side with JavaScript (really resize, not just change width and height).
I know it's possible to do it in Flash but I would like to avoid it if possible.
Is there any open source algorithm somewhere on the web?
Here's a gist which does this:
https://gist.github.com/dcollien/312bce1270a5f511bf4a
(an es6 version, and a .js version which can be included in a script tag)
You can use it as follows:
<input type="file" id="select">
<img id="preview">
<script>
document.getElementById('select').onchange = function(evt) {
ImageTools.resize(this.files[0], {
width: 320, // maximum width
height: 240 // maximum height
}, function(blob, didItResize) {
// didItResize will be true if it managed to resize it, otherwise false (and will return the original file as 'blob')
document.getElementById('preview').src = window.URL.createObjectURL(blob);
// you can also now upload this blob using an XHR.
});
};
</script>
It includes a bunch of support detection and polyfills to make sure it works on as many browsers as I could manage.
(it also ignores gif images - in case they're animated)
The answer to this is yes - in HTML 5 you can resize images client-side using the canvas element. You can also take the new data and send it to a server. See this tutorial:
http://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/
If you were resizing before uploading I just found out this http://www.plupload.com/
It does all the magic for you in any imaginable method.
Unfortunately HTML5 resize only is supported with Mozilla browser, but you can redirect other browsers to Flash and Silverlight.
I just tried it and it worked with my android!
I was using http://swfupload.org/ in flash, it does the job very well, but the resize size is very small. (cannot remember the limit) and does not go back to html4 when flash is not available.
http://nodeca.github.io/pica/demo/
In modern browser you can use canvas to load/save image data. But you should keep in mind several things if you resize image on the client:
You will have only 8bits per channel (jpeg can have better dynamic range, about 12 bits). If you don't upload professional photos, that should not be a problem.
Be careful about resize algorithm. The most of client side resizers use trivial math, and result is worse than it could be.
You may need to sharpen downscaled image.
If you wish do reuse metadata (exif and other) from original - don't forget to strip color profile info. Because it's applied when you load image to canvas.
Perhaps with the canvas tag (though it's not portable). There's a blog about how to rotate an image with canvas here, I suppose if you can rotate it, you can resize it. Maybe it can be a starting point.
See this library also.
You can use a javascript image processing framework for client-side image processing before uploading the image to the server.
Below I used MarvinJ to create a runnable code based on the example in the following page:
"Processing images in client-side before uploading it to a server"
Basically I use the method Marvin.scale(...) to resize the image. Then, I upload the image as a blob (using the method image.toBlob()). The server answers back providing a URL of the received image.
/***********************************************
* GLOBAL VARS
**********************************************/
var image = new MarvinImage();
/***********************************************
* FILE CHOOSER AND UPLOAD
**********************************************/
$('#fileUpload').change(function (event) {
form = new FormData();
form.append('name', event.target.files[0].name);
reader = new FileReader();
reader.readAsDataURL(event.target.files[0]);
reader.onload = function(){
image.load(reader.result, imageLoaded);
};
});
function resizeAndSendToServer(){
$("#divServerResponse").html("uploading...");
$.ajax({
method: 'POST',
url: 'https://www.marvinj.org/backoffice/imageUpload.php',
data: form,
enctype: 'multipart/form-data',
contentType: false,
processData: false,
success: function (resp) {
$("#divServerResponse").html("SERVER RESPONSE (NEW IMAGE):<br/><img src='"+resp+"' style='max-width:400px'></img>");
},
error: function (data) {
console.log("error:"+error);
console.log(data);
},
});
};
/***********************************************
* IMAGE MANIPULATION
**********************************************/
function imageLoaded(){
Marvin.scale(image.clone(), image, 120);
form.append("blob", image.toBlob());
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.marvinj.org/releases/marvinj-0.8.js"></script>
<form id="form" action='/backoffice/imageUpload.php' style='margin:auto;' method='post' enctype='multipart/form-data'>
<input type='file' id='fileUpload' class='upload' name='userfile'/>
</form><br/>
<button type="button" onclick="resizeAndSendToServer()">Resize and Send to Server</button><br/><br/>
<div id="divServerResponse">
</div>
In my experience, this example has been the best solution for uploading a resized picture: https://zocada.com/compress-resize-images-javascript-browser/
It uses the HTML5 Canvas feature.
The code is as 'simple' as this:
compress(e) {
const fileName = e.target.files[0].name;
const reader = new FileReader();
reader.readAsDataURL(e.target.files[0]);
reader.onload = event => {
const img = new Image();
img.src = event.target.result;
img.onload = () => {
const elem = document.createElement('canvas');
const width = Math.min(800, img.width);
const scaleFactor = width / img.width;
elem.width = width;
elem.height = img.height * scaleFactor;
const ctx = elem.getContext('2d');
// img.width and img.height will contain the original dimensions
ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);
ctx.canvas.toBlob((blob) => {
const file = new File([blob], fileName, {
type: 'image/jpeg',
lastModified: Date.now()
});
}, 'image/jpeg', 1);
},
reader.onerror = error => console.log(error);
};
}
There are two downsides with this solution.
The first one is related with the image rotation, due to ignoring EXIF data. I couldn't tackle this issue, and wasn't so important in my use case, but will be glad to hear any feedback.
The second downside is the lack of support foe IE/Edge (not the Chrome based version though), and I won't put any time on that.
Yes, with modern browsers this is totally doable. Even doable to the point of uploading the file specifically as a binary file having done any number of canvas alterations.
http://jsfiddle.net/bo40drmv/
(this answer is a improvement of the accepted answer here)
Keeping in mind to catch process the result submission in the PHP with something akin to:
//File destination
$destination = "/folder/cropped_image.png";
//Get uploaded image file it's temporary name
$image_tmp_name = $_FILES["cropped_image"]["tmp_name"][0];
//Move temporary file to final destination
move_uploaded_file($image_tmp_name, $destination);
If one worries about Vitaly's point, you can try some of the cropping and resizing on the working jfiddle.

Categories