Javascript: Pass created image through ajax. - javascript

So I created an image using canvas. And I want to pass the image using ajax. I know how to do it using form but this time I'm not using one. This is my code for creating image.
var video = document.querySelector('video')
, canvas;
var img = document.querySelector('img') || document.createElement('img');
var context;
var width = video.offsetWidth
, height = video.offsetHeight;
canvas = canvas || document.createElement('canvas');
canvas.width = width;
canvas.height = height;
context = canvas.getContext('2d');
context.drawImage(video, 0, 0, width, height);
img.src = canvas.toDataURL('image/png');
document.body.appendChild(img);
the "img" variable is my created image. This is my code of passing image using ajax
var form = $('#fileUploadForm')[0];
var data = new FormData(form);
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/api/file/upload",
data: data,
processData: false, //prevent jQuery from automatically transforming the data into a query string
contentType: false,
cache: false,
success: (data) => {
$("#listFiles").text(data);
},
error: (e) => {
$("#listFiles").text(e.responseText);
}
});
I tried other tutorials by creating a new FormData but it doesn't seem to work. I also tried assigning value to input file type.But it doesn't work and others doesn't recommend it due to future security problems. Hoping you could help me.

Related

Execute Function After Canvas toDataURL() Function is Complete

I'm converting images to base64 using canvas. What i need to do is convert those images and then show the result to the user (original image and base64 version). Everything works as expected with small images, but when i try to convert large images (>3MB) and the conversion time increases, the base64 version is empty.
This might be is caused because the result is shown before the toDataURL() function is completed.
I need to show the result after all the needed processing has ended, for testing purposes.
Here's my code:
var convertToBase64 = function(url, callback)
{
var image = new Image();
image.onload = function ()
{
//create canvas and draw image...
var imageData = canvas.toDataURL('image/png');
callback(imageData);
};
image.src = url;
};
convertToBase64('img/circle.png', function(imageData)
{
window.open(imageData);
});
Even though i'm using image.onload() with a callback, i'm unable to show the result after the toDataURL() has been processed.
What am i doing wrong?
UPDATE: I tried both the solutions below and they didn't work. I'm using AngularJS and Electron in this project. Any way i can force the code to be synchronous? Or maybe some solution using Promises?
UPDATE #2: #Kaiido pointed out that toDataURL() is in fact synchronous and this issue is more likely due to maximum URI length. Since i'm using Electron and the image preview was for testing purposes only, i'm going to save the file in a folder and analise it from there.
Your code seems absolutely fine. Not sure why isn't working you. Maybe, there are some issues with your browser. Perhaps try using a different one. Also you could use a custom event, which gets triggered when the image conversion is competed.
// using jQuery for custom event
function convertToBase64(url) {
var image = new Image();
image.src = url;
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var imageData = canvas.toDataURL();
$(document).trigger('conversionCompleted', imageData);
};
};
convertToBase64('4mb.jpg');
$(document).on('conversionCompleted', function(e, d) {
window.open(d);
});
This approach might work for you. It shows the image onscreen using the native html element, then draws it to a canvas, then converts the canvas to Base64, then clears the canvas and draws the converted image onto the canvas. You can then scroll between the top image (original) and the bottom image (converted). I tried it on large images and it takes a second or two for the second image to draw but it seems to work...
Html is here:
<img id="imageID">
<canvas id="myCanvas" style="width:400;height:400;">
</canvas>
Script is here:
var ctx;
function convertToBase64(url, callback)
{
var image = document.getElementById("imageID");
image.onload = function() {
var canvas = document.getElementById("myCanvas");
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
ctx = canvas.getContext("2d");
ctx.drawImage(image,0,0);
var imageData = canvas.toDataURL('image/png');
ctx.fillStyle ="#FFFFFF";
ctx.fillRect(0,0,canvas.width,canvas.height);
callback(imageData);
};
image.src = url;
};
var imagename = 'images/bigfiletest.jpg';
window.onload = function () {
convertToBase64(imagename, function(imageData) {
var myImage = new Image();
myImage.src = imageData;
ctx.drawImage(myImage,0,0);
});
}
Note that I also tried it without the callback and it worked fine as well...

javascript- unable to convert canvas to image data

guys!
I'm trying to make a demo using which a user will be able to capture an image from the web camera enabled through his browser and this image will be saved in the backend by passing it to a PHP service using AJAX call.
I'm able to capture as canvas but not being to convert it into image data.
I'm getting canvas is undefined error
Setup is pretty simple.
HTML
<video id="videoElement" autoplay></video>
<button id="snap">Snap Photo</button>
<canvas id="canvas" style="display:none" ></canvas>
JAVASCRIPT
// Grab elements, create settings, etc.
var video = document.getElementById('videoElement');
// Get access to the camera!
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// Not adding `{ audio: true }` since we only want video now
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
video.src = window.URL.createObjectURL(stream);
video.play();
});
}
// Elements for taking the snapshot
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var video = document.getElementById('videoElement');
// Trigger photo take
document.getElementById("snap").addEventListener("click", function() {
var cann= context.drawImage(video, 0, 0, 640, 480); //draw canvas
//then convert canvas to image so i can obtain dataurl
//and pass it to another function using AJAX
var img= convertCanvasToImage(cann);
console.log(img);
});
// Converts canvas to an image
function convertCanvasToImage(canvas)
{
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
}
I'm pretty new to this field. I have one more question. Will this work on latest browsers?
Can anyone help me figure out the mistake I made?
FIDDLE
Reference:
https://davidwalsh.name/browser-camera
https://davidwalsh.name/convert-canvas-image
Just call this
var img= convertCanvasToImage();
function convertCanvasToImage()
{
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
}
No need to pass canvas as you defined canvas above. But if you have convertCanvasToImage function in another file then you can use
var img= convertCanvasToImage(canvas);
This may help.
function demoFromHTML() {
html2canvas(document.getElementById("talltweets"), {
onrendered: function(canvas) {
var imageData = canvas.toDataURL('image/png',1.0);
}
});
}
Pass canvas object instead of cann
var img= convertCanvasToImage(canvas);
If you can try to avoid dataURL and use blob instead - it will save you more memory and load images faster
$canvas.toBlob(function(blob){
var url = URL.createObjectURL(blob)
var img = new Image
img.onload = function() {
URL.revokeObjecURL(this.src)
}
img.src = url
console.log(blob)
console.log(url)
})
<canvas id="$canvas">
there is polyfills you can use to support canvas#toBlob

html2canvas doesn't get image full height

For some reason that I can't understand, the html2canvas is not capturing the whole height of the div.
html2canvas($container, {
height: $container.height(),
onrendered: function(canvas) {
var data = canvas.toDataURL('image/png');
var file = dataURLtoBlob(data);
var formObjects = new FormData();
formObjects.append('file', file);
$.ajax({
url: 'ajax_preview',
type: 'POST',
data: formObjects,
processData: false,
contentType: false,
}).done(function(response){
console.log(response);
//window.open(response, '_blank');
});
}
});
I have also tried to set up the Height manually height: $container.height() but unfortunately the image keeps getting cut off. I also tried to set the height 1124, but the result is the same.
It's hard to see, but in the image below you see a white portion of the image without any border. Everything I have in that portion is not shown.
Any ideas of what could cause this behavior?
Solved.
My code is actually right, the problem was on a CSS file that I use.
To avoid this I've deleted and call again the file while converting the div into an image.
// $= means that ends with
("link[href$='my.css']").remove();
html2canvas($container, {
onrendered: function(canvas) {
var data = canvas.toDataURL('image/png');
var file = dataURLtoBlob(data);
// etc
$('head').append("<link href='" + base_url + "public/css/my.css' rel='stylesheet'/>");
}
});

Draggable issue when loading Multiple Images in Kinetic JS

$.ajax({
type: 'get',
url: myUrl,
success: function(data) {
//alert("ajax");
$.each(data, function(idx, obj) {
createImage(obj.id, obj.mPosX, obj.mPosY);
});
},
contentType: "application/json",
dataType: 'json'
});
function createImage(mId, curX, curY) {
var layer2 = new Kinetic.Layer();
var imageObj = new Image();
imageObj.src = 'img/pawn.png';
imageObj.onload = function() {
pImage[mId] = new Kinetic.Image({
x: curX,
y: curY,
image: imageObj,
draggable:true,
id: pImage[mId]
});
layer2.add(pImage[mId]);
layer2.setScale(cur_scale);
stage.add(layer2);
};
}
I am trying to add multiple images with different position from a JSON file, I am successful in placing the images in exact location, But the problem is if i try to drag the image it position itself at top of the canvas.
Any idea why it is behaving like this.?
right now you are creating a new layer for every single image. That is not how KJS works.
You first create a stage, then create a layer and then add all the images to this one layer.
Maybe this will solve the problem.

Convert Svg to Png on Client Side

I am working on a Web based application where user can create designs in Svg. i want to convert the svg design into png image file on client side. i found a solution of using canvas, this works well in firefox, but in chrome it generate security error.
check the code below thanks:-
var mainsvg=document.getElementById('svgforImg');
var canvas=document.getElementById('canvas');
var ctx = canvas.getContext("2d");
var data=mainsvg.innerHTML;
var DOMURL = self.URL || self.webkitURL || self;
var svg = new Blob([data], {
type: "image/svg+xml;charset=utf-8"
});
var url = DOMURL.createObjectURL(svg);
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
var imageurl = canvas.toDataURL("image/png");
}
Now my variable imageurl contains 'base64 png' image. this works in Firefox. But in chrome line
var imageurl = canvas.toDataURL("image/png");
generate security error.
Any help would be highly appreciated.
I think this is related to this question. From which server does the SVG originate? If it is a different one than the one your application is coming from (remember: sub-domains matter!), you could add the desired http-headers in the originating server.

Categories