Sampling an image's pixels? - javascript

I have an <img> loading from a URL and I want to see what colors the pixels have.
var img = document.getElementById('image');
img.src = "https://someimage.url/image.jpg";
img.onload = function () {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
};
At this point, due to .getImageData, the console says operation is insecure.
I try to fix this by adding img.crossOrigin = "anonymous";.
This gets rid of the error message, but leaves me with an empty, unloaded image.
Other posts have suggested moving components out of img.onload, but it's the same result.
Some have suggested that this path is not possible due to security reasons. If so, what is another way of approaching this? How else does one determine the color of a certain pixel displayed on screen?
The documentation for getImageData seems to show exactly what I want to do. It looks like the only difference is that their image is on their own server instead of someone else's. Is this the only way around this problem? And if that's the case, would a more straightforward concept be:
download image to your own server
process it locally
delete image after processing
This might be more straightforward, but probably won't scale very well?

Related

slow down time take by domtoimage js

I am using domtoimage library to convert html (with lots of CSS) to image.
Actually I need high clarity image for printing purpose (600 DPI). So for this I scale (zoom) the html to 6.25(600/96) times, then I use domtoimage to capture it. I am successful as per my plans. My image is of high resolution and the printing clarity is also satisfactory.
But the issue is with optimization. It takes too long time for domtomimage. I know this issue is because of html scaling, but I need high resolution image.
Any idea for making this capture fast? My main focus is to reduce time taken by library to capture and create image.
Note:
I have also tried with phantom JS, but some css properties are not supported in it.
I have also tried html2canvas which has also limitation with some CSS property
Just for information I have added scale property to draw function
function draw(domNode, options) {
return toSvg(domNode, options)
.then(util.makeImage)
.then(util.delay(100))
.then(function (image) {
var canvas = newCanvas(domNode);
// canvas.getContext('2d').drawImage(image, 0, 0);
var ctx = canvas.getContext('2d');
if(options.scale){
ctx.scale(6.25,6.25);
}
ctx.drawImage(image, 0, 0);
return canvas;
});
function newCanvas(domNode) {
var canvas = document.createElement('canvas');
if(options.scale){
canvas.width = options.width || 6.25 * util.width(domNode);
canvas.height = options.height || 6.25 * util.height(domNode);
}
else{
canvas.width = options.width || util.width(domNode);
canvas.height = options.height || util.height(domNode);
}
if (options.bgcolor) {
var ctx = canvas.getContext('2d');
ctx.fillStyle = options.bgcolor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
return canvas;
}
}
I could speed up the image generation process by several times by skipping the font re-rendering process. I'm not sure what content you're trying to capture but if it is not font-specific, I forked and edited the library based on suggestions from several other users and it works for me. It also helped me get rid of many failed XHR requests due to CORS and is currently working on all browsers.
Check out: https://github.com/venkat4541/dom-to-image
This may or may not work for you based on your font usage. Hope it helps.

How to select file, fix orientation, and add to canvas

My site allows users to upload their own photos. I've learned that this is trickier than first expected and although I can get each of the components working individually I'm not successfully getting them to produce the outcome I need when combining them. I believe the issue is my lack of understanding around the outputs of the functions i'm using.
I think what I need to do is:
Let the user choose the file to upload
Check / fix the orientation
Display the image in a canvas
Convert the canvas to base64 (to upload to Firebase)
Upload the item
Let the user choose the file to upload
$(document).on('change','#fileUpload',function(e) {
correctImageOrientation(e);
});
Check / fix the image orientation
I'm using image-load (link) for my orientation changes.
function correctImageOrientation(e) {
loadImage(
e.target.files[0],
function (img) {
// document.body.appendChild(img); // Note: this successfully appends the image in the correct orientation to the body - but I need to do this to a canvas to I call:
addImageToCanvas(img);
},
{
orientation: true
}
);
Display the image in a canvas
This part fails. If I pass in the selected file using e.target.files[0] and create an objectURL then it works. This is why I think the img i'm passing in needs to be read / displayed on the canvas differently.
function addImageToCanvas(img) {
img.onload = function() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, 300, 300);
console.log("Ending img.onload"); // This is never reached
}
}
I can then successfully convert the file to base64 and upload to Firebase.
I think there must be an easier way to achieve what I want which is for people to upload an image, for the orientation to be correct, and for this to be stored online.
EDIT: To store the image in firebase I am using this to convert the image back to a blob.
I have replaced addImageToCanvas with the function below which was taken then modified from David Walsh's site. Because I'm passing in an image I needed to convert this to a canvas.
function convertImageToCanvas(image) {
var canvas = document.getElementById("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
}

Getting blank image with canvas draw about half the time

I am converting a base64 string into an image, and then passing it to a canvas draw to make it smaller. This is based off a script I found on SO.
function imageToDataUri(img, width, height) {
// create an off-screen canvas
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
// set its dimension to target size
canvas.width = width;
canvas.height = height;
// draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, width, height);
// encode image to data-uri with base64 version of compressed image
return canvas.toDataURL();
}
I pass in the image element (which is correct before, I've checked), and some of the time this script works correctly and changes the image to the correct size, and other times it generates what I think is a blank image, like this:
iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAEJJREFUaAXt0IEAAAAAw6D5Ux/khVBhwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYeBwYnQgABzCacsQAAAABJRU5ErkJggg==
I can't find any reproducability - it happens or it doesn't, on the same or different images.
What could be going on? The script seems to work, but only half the time? Everything else is being kept exactly the same.
Edit - this is how the image for the above function is being generated:
function resizeURI(base64) {
var img = new Image;
// turns base64 into dataURI
var uri = base64ToDataUri(base64);
img.src = uri;
var resizedURI = resizeImage(img);
// turns dataURI into base64 again
resizedURI = resizedURI.substring(resizedURI.indexOf(",") + 1);
return resizedURI;
}
function resizeImage(img) {
var newDataUri = imageToDataUri(img, 50, 50);
return newDataUri;
}
The reason is because the image is not always loaded when the imageToDataUri is called. you should wait for it to be fully loaded, by adding event listener, and wait for "loaded" event before you call imageToDataUri().
see HTML5 canvas - drawImage not always drawing the image

Create canvas/bitmap in pure Javascript (No html)

I'm developing a server for a iPhone game in Javascript with socket.io. The servers purpose is to draw a offscreen bitmap with the players path in order to check if that path is already draw. Simply put, all of the drawing will only be shown on the client screen. Here is the code I've found for creating a canvas and then finding pixel colors in it. However I've no html code since it's only made using Javascript. So will this code work in a Javascript only program? If not, how can i do something like this but with the same result?
Edit: I'm using socket.io with node.js
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
// Make sure to set the size, otherwise its zero
canvas.width = 100;
canvas.height = 100;
// Draw to the offscreen canvas
context.fillStyle = "#0000ff";
context.fillRect(0,0,50,50);
context.fillStyle = "#ff9900";
context.arc(50,50,25,50,0,Math.PI*2);
context.fill();
// document.body.appendChild(canvas)
// To preview the canvas
var imgData = context.getImageData(0, 0, canvas.height, canvas.width);
var offset = 90*canvas.width+50*4
console.log(imgData.data[offset]);
console.log(imgData.data[offset+1]);
console.log(imgData.data[offset+2]);
console.log(imgData.data[offset+3]);
Node.JS + Node-Canvas will accept javascript-only input and will output an image:
https://github.com/Automattic/node-canvas

Resize base64 image in firefox

I'm still new in coding and HTML5.
I have a HTML5 stage with multiple canvas. I need to get the base64 image from that stage and resize it, then get the base64 image of the resized canvas.
This is the code I use:
stage.toDataURL({
callback: function(dataUrl) {
var tmp_img = new Image();
tmp_img.src = dataUrl;
//resize image to 45x75
var canvas = document.getElementById('hidden_canvas');
canvas.width = 45;
canvas.height = 75;
var ctx = canvas.getContext("2d");
ctx.drawImage(tmp_img, 0, 0, canvas.width, canvas.height);
dataUrl = canvas.toDataURL();
)};
The dataUrl is correct in Chrome but when I run the code in Firefox, it seems that the Firefox didn't generate the correct base64 code.
I would really appreciate any help
You've stumbled upon a common problem.
tmp_img.src loads the dataUrl into your new image--but that takes time. So javascript continues with your code below that even before the image is loaded. The result is that you are sometimes trying to ctx.drawImage before tmp_img has been fully loaded and is ready to use.
The fix is to refactor your code to use tmp_img.onload. The .onload triggers a callback function when tmp_img is finally ready to use. The refactoring might look like this:
var tmp_img = new Image();
tmp_img.onload=function(){
//resize image to 45x75
var canvas = document.getElementById('hidden_canvas');
canvas.width = 45;
canvas.height = 75;
var ctx = canvas.getContext("2d");
ctx.drawImage(tmp_img, 0, 0, canvas.width, canvas.height);
dataUrl = canvas.toDataURL();
}
tmp_img.src = dataUrl;
// more javascript
JavaScript will execute the above code in this order:
Create a new Image object
See tmp_img.onload and make a not that it should do that code when the image is fully loaded
Set tmp_img.src and start loading the image.
Continue with "more javascript"
When the image is fully loaded, execute everything in the .onload callback function.
It looks like you're using KineticJS--are you?
If so, then instead of stage.toDataURL you could use stage.toImage. That way you already have the image loaded when the stage.toImage callback is executed (you don't have to worry about waiting for the image to load). Then just .drawImage the image that KineticJS provides in the callback.

Categories

Resources