Method of using "getImageData(...)"(or similar) on an image? - javascript

I have the following code to do so:
img = new Image();
img.src = document.getElementById("input").value;
img.onload = function(){
console.log("loaded");
c.height = img.height;
c.width = img.width;
dimensions =[img.width,img.height];
ctx.drawImage(img,0,0,img.width,img.height);
imageData = ctx.getImageData(0,0,img.width,img.height).data;
ctx.clearRect(0,0,c.width,c.height);
};
However, on google chrome it throws the error Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
Not only that, it's a very complex way of doing a simple action. Any better ways of doing this? If not, help with the error?

What are you trying to do with the data? Depending on that you could possible use the FileReader.readAsDataURL(), especially since you are trying to get the data for the whole image.
Some code:
var input = document.getElementById('file');
var ctx2 = document.getElementById('uploadcanvas').getContext('2d');
var img2 = new Image;
var canvas = document.getElementById('uploadcanvas');
var imgprop = document.createElement("img");
var reader = new FileReader();
ctx2.save();
reader.onloadend = function(e){
imgprop.src = e.target.result
imgprop.onload = function(){
ctx2.restore();
URL.revokeObjectURL(img2.src);
ctx2.clearRect(0, 0, 100,100);
var width = imgprop.width;
var height = imgprop.height;
console.log(width, height);
canvas.width = width;
canvas.height = height;
img2.src = URL.createObjectURL(input.files[0]);
img2.onload = function() {
$('#display-image').css('display', "inline");
ctx2.drawImage(img2, 0, 0);
//URL.revokeObjectURL(img2.src);
};
$("#button").removeAttr("disabled");
$("#button").html("Upload to Facebook");
}
};
reader.readAsDataURL(input.files[0]);
function dataURItoBlob(dataURI) {
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], {
type: 'image/png'
});
}

Related

how can i put base64 image file into opencv? (javascript)

I'm trying to get random image from input video file, and then put the image into opencv to get grayScale image on the webpage.
Getting random image from video is solved by below-solution.
Javascript how to extract frame from video?
but now i'm stuck to the problem, Is it impossible to give base 64 source image file into opencv(imread, imshow, cv.cvtColor)? Please help me.
'''
//const cv = require("./js/opencv");
var video = document.createElement("video");
var image = new Image();
var canvas = document.getElementById("prevImgCanvas");
var canvas_after = document.getElementById("canvas_after");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
video.addEventListener('loadeddata', function() {
reloadRandomFrame();
}, false);
video.addEventListener('seeked', function() {
var context = canvas.getContext('2d');
context.drawImage(video, 0, 0, canvas.width, canvas.height);
const dataurl = canvas.toDataURL("image/jpeg")
image.src = dataurl;
image.onload = function(){
console.log(image);
let mat = cv.imread(image);
cv.imshow('canvasOutput', mat);
mat.delete();
};
}, false);
var playSelectedFile = function(event) {
var file = this.files[0];
var fileURL = URL.createObjectURL(file);
video.src = fileURL;
}
var input = document.getElementById('fileinput');
input.addEventListener('change', playSelectedFile, false);
function reloadRandomFrame() {
if (!isNaN(video.duration)) {
var rand = Math.round(Math.random() * video.duration * 1000) + 1;
video.currentTime = rand / 1000;
}
}
'''
let image = new Image()
image.src = 'your base64'
await new Promise(r => {
image.onload = r
})
cv.imread(image)

How to merge multiple uploaded images by using Multi File Upload control?

I am trying to merge multiple images while retrieving the images from desk. It was taken from "How to create an image generator for combining multiple images?". It's working fine if single image is uploaded, but not working in case of multiple images.
This is my HTML code
<input id="file-input" type="file" name="images[]" multiple maxlength="5" ngf-select="UploadFiles($files)" accept=".png,.jpg,.jpeg,.gif" />
<canvas id="canvas"></canvas>
This is javascript code
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var lastImage;
var lastHeight = 0;
var lastWidth = 0;
var imagesLoaded = 0;
function max(a, b) {
if (a > b)
return a;
return b;
}
function addToCanvas(img) {
canvas.height = max(lastHeight, img.width);
canvas.width = lastWidth + img.height;
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (lastImage) {
ctx.drawImage(lastImage, 0, canvas.height - lastImage.height);
}
ctx.rotate(270 * Math.PI / 180); // rotate the canvas to the specified degrees
ctx.drawImage(img, -canvas.height, lastWidth);
lastImage = new Image();
lastImage.src = canvas.toDataURL();
lastWidth += img.height;
lastHeight = canvas.height;
imagesLoaded += 1;
}
$scope.UploadFiles = function (files) {
$scope.SelectedFiles = files;
cnt = files.length;
console.log($scope.SelectedFiles);
for (i = 0; i < $scope.SelectedFiles.length; i++) {
console.log(files[i]);
var reader = new FileReader();
reader.onload = function (event) {
var img = new Image();
img.onload = function () {
addToCanvas(img);
}
img.src = reader.result;
}
reader.readAsDataURL(files[i]);
}
};
When I select images from the folder, the console's debugger stops at img.onload event, where I am trying to do action in loop.
For loop iteration not working for imageload functions..
files.map((file) => {
var reader = new FileReader();
reader.onload = (event) => {
var img = new Image();
img.onload = () =>
{
addToCanvas(img);
}
img.src = reader.result;
}
reader.readAsDataURL(file);
}
)

getImageData returns white image

I need to read the image data from an image object in javascript.
But my code returns always a blank array (set to 255)
<html>
<header>
</header>
<body>
<input type="file" id="imgfile" onchange="testImageData(event);" />
<canvas id="canvas1" width="640" height="480"></canvas>
<script src="./../scripts/cam.js" ></script>
</body>
</html>
Here is the script
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d');
function getImageData(image){
/*
returns Uint8ClampedArray object
takes an image obj
*/
var canvas = document.createElement("canvas");
canvas.height = image.height;
canvas.width = image.width;
var ctx = canvas.getContext("2d");
ctx.width = image.width;
ctx.height = image.height;
ctx.drawImage(image,0,0);
return ctx.getImageData(0, 0, ctx.width, ctx.height);
}
function testImageData(event){
var selectedFile = event.target.files[0];
var reader = new FileReader();
var img = new Image();
reader.onload = function(event) {
console.log('onload');
img.src = event.target.result;
img.onload = function(){
context1.drawImage(img, 0,0, img.width, img.height);
var imgData = getImageData(img);
// console.log(imgData);
var data = imgData.data;
for(var i = 0; i<data.length;i+=4){
console.log(data[i],data[i+1],data[i+2],data[i+3]);
}
}
};
In my understanding, the console.log should return me the data in RGBA.
But I'm just getting 255.
console.log output
EDIT:
Okay I found a work around but I don't understand why this is working.
Instead using getImageData, I get the data directly from the drawn context1.
function testImageData(event){
var selectedFile = event.target.files[0];
var reader = new FileReader();
var img = new Image();
reader.onload = function(event) {
console.log('onload');
img.src = event.target.result;
img.onload = function(){
context1.drawImage(img, 0,0, img.width, img.height);
var imgData = context1.getImageData(0,0,img.width,img.height);
var data = imgData.data;
for(var i = 0; i<data.length;i+=4){
console.log(data[i],data[i+1],data[i+2],data[i+3]);
}
}
};
So the problem must lie in creating a new canvas.
You should wait for the image to load img.onload you are waiting for the readers onload event...
you also forget to read the file... missed reader.readAsDataURL
but you don't need the filereader.
window.URL = window.URL || webkitURL
var img = new Image();
img.src = URL.createObjectURL(file)
img.onload = function(){
// put your image on the canvas
}

Convert piece of canvas to blob type

I am trying to optimize some code that uses the canvas.drawImage() call.
This is a pretty expensive call when called several hundreds or thousands of times.
Found out about the canvas.toBlob(callback) method but I want to know if there is a way to get only a section of the canvas.
drawimage() gives much more fine grain control over which sections should be draw.
canvas.drawImage(canvas, sx, sy, sw, sh, dx, dy, dw, dh);
Any suggestions / thoughts are welcomed!
The canvas.toBlob method is currently only supported by Firefox browser.
For it to work on other browsers, you can use this code to convert a base64 dataURI to a blob object.
Now, to get only a portion of the canvas through these methods, you'll have to create a new canvas, set its dimensions to the cropped ones and draw the part you want on it :
var img = new Image();
img.crossOrigin = 'anonymous';
img.src = "http://i.imgur.com/fHyEMsl.jpg";
var resultImg = new Image();
var resultSize = document.createElement('span');
document.body.appendChild(resultImg);
document.body.appendChild(resultSize);
var cropped = {x: 0, y: 0, width: 130, height: 130};
var canvas = document.createElement('canvas');
document.body.appendChild(canvas);
img.onload = function() {
canvas.width = this.width;
canvas.height = this.height;
canvas.getContext('2d').drawImage(this, 0, 0);
setInterval(cropCanvas, 1000);
}
function cropCanvas() {
URL.revokeObjectURL(resultImg.src);
var newCanvas = document.createElement('canvas');
newCanvas.width = cropped.width;
newCanvas.height = cropped.height;
newCanvas.getContext('2d').drawImage(canvas, -cropped.x, -cropped.y);
if (newCanvas.toBlob) { // Firefox
newCanvas.toBlob(function(blob) {
resultImg.src = URL.createObjectURL(blob);
resultSize.innerHTML = blob.size + ' bytes';
}, 'image/jpeg');
} else { // all other browsers
var blob = dataURItoBlob(newCanvas.toDataURL('image/jpeg'));
resultImg.src = URL.createObjectURL(blob);
resultSize.innerHTML = blob.size + ' bytes';
}
//move our crop
if (cropped.x < img.width - 130)
cropped.x += 130;
else {
if (cropped.y < img.height - 130) {
cropped.y += 130;
cropped.x = 0;
} else {
cropped.x = 0;
cropped.y = 0;
}
}
}
// taken from https://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata/5100158#5100158
function dataURItoBlob(dataURI) {
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {
type: mimeString
});
}

A canvas into which I would like to load a Base64 string that represents a png image but just displays a blank white box

I have a canvas into which I would like to load a Base64 string that represents a png image. However, the following code just displays a blank white box and I am baffled as to why. When I look at the data in the canvas, it looks identical to a canvas that gets its data from a FileReader object (also below). Any help deducing this issue is greatly appreciated!
This code shows a white canvas:
html
<canvas id="canvas" width="114" height="114" style="z-index: 999999; display: none; padding-left: 50px"></canvas>
javascript
var websiteIconData = $('#ctl00_ContentPlaceHolder1_websiteIcon');
if (websiteIconData.val() != '') {
var canvas = document.getElementById('canvas');
var ctx = document.getElementById('canvas').getContext('2d');
var loadedImg = new Image();
loadedImg.onload = function () {
ctx.drawImage(this, 0, 0);
Debugger.log(ctx);
};
loadedImg.src = websiteIconData.val();
canvas.style.display = 'block';
}
This code shows the image:
$('#loadWebsiteIcon').on({
change: function (ev) {
var reader = new FileReader();
reader.onload = function (e) {
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function () {
var MAX_WIDTH = 114;
var MAX_HEIGHT = 114;
var width = img.width;
var height = img.height;
if (width > MAX_WIDTH) {
width = MAX_WIDTH;
}
if (height > MAX_HEIGHT) {
height = MAX_HEIGHT;
}
ctx.drawImage(img, 0, 0, width, height);
for (var i = 0; i <= document.images.length; i++) {
}
Debugger.log(ctx);
};
img.src = e.target.result;
}
draw();
};
reader.readAsDataURL(ev.target.files[0]);
var canvas = document.getElementById('canvas');
canvas.style.display = 'block';
var imgData = canvas.toDataURL();
$('#ctl00_ContentPlaceHolder1_websiteIcon').val(imgData);
Debugger.log(imgData);
}
});
Be careful how Base64 is parsed. If it is parsed for email, it will insert a character ever 76 lines by default. Most Base64 encoders have an option to turn this off. I am looking at MIME::Base64
From that document :
The returned encoded string is broken into lines of no more than 76 characters each and it >will end with $eol unless it is empty.
where $eol was one of the arguments. In the case of this module, setting it to an empty string would prevent the base64 from being broken up.
It turns out the issue had little to do with the canvas API or the Base64 encoding. It was more an issue of the canvas.toDataURL(); function getting called before the image had been loaded in the canvas. Moving this line to within the img.onload function seemed to do the trick. Below is the correct code:
function initImageChange() {
//this is will be a string in Base64, in this case it is an <input type="text">... tag
var imageData = $('#imageData');
//this is a canvas tag in on the page
var canvas = document.getElementById('canvas');
//load the image from the imageData var if it exists
if (imageData.val() != '') {
var ctx2=canvas.getContext('2d');
var loadedImg = new Image();
loadedImg.onload = function() {
ctx2.drawImage(this, 0, 0);
};
loadedImg.src = imageData.val();
canvas.style.display = 'block';
}
//this is a function that loads an image from a file onto the canvas and
//sends the Base64 representation of this image to the text input tag. This
//could fairly easily be send directly to a post request or saved some other way
$('#loadImage').on({
change: function (ev) {
var ctx = document.getElementById('canvas').getContext('2d');
var dataURL = '';
var reader = new FileReader();
reader.onload = function (e) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
function draw() {
var img = new Image();
img.onload = function () {
var MAX_WIDTH = 130;
var MAX_HEIGHT = 110;
var width = img.width;
var height = img.height;
if (width > MAX_WIDTH) {
width = MAX_WIDTH;
}
if (height > MAX_HEIGHT) {
height = MAX_HEIGHT;
}
ctx.drawImage(img, 0, 0, width, height);
dataURL = canvas.toDataURL();
$('#ctl00_ContentPlaceHolder1_websiteIcon').val(dataURL);
ctx.restore();
};
img.src = e.target.result;
}
draw();
};
reader.readAsDataURL(ev.target.files[0]);
canvas.style.display = 'block';
}
});
}

Categories

Resources