getImageData returns white image - javascript

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
}

Related

how to insert Image() into docx in JavaScript?

I use "dom-to-image" to convert html table to png:
var wrapper = document.getElementById('exportContent');
domtoimage.toSvg(wrapper).then(function (svgDataUrl) {
downloadPNGFromAnyImageSrc(svgDataUrl);
});
function downloadPNGFromAnyImageSrc(src)
{
var img = new Image;
img.onload = function(){
var canvas = convertImageToCanvas(img);
var pngImage = convertCanvasToImage(canvas);
var anchor = document.createElement('a');
anchor.setAttribute('href', pngImage.src);
anchor.setAttribute('download', 'image.png');
anchor.click();
};
img.src = src;
// Converts image to canvas; returns new canvas element
function convertImageToCanvas(image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
return canvas;
}
// Converts canvas to an image
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png", 1.0);
return image;
}
}
It converts the element to png. However I need to put it into doc file.
Now I need to generate/save a docx file with this png without saving png.
How can I do it?
I followed this post: dom to img

pdfmake base64 image callback

I have to work with pdfmake to build a pdf preview within my laravel application. I am a javascript noob and going nuts to generate the dataURI for an image in b. Hope you can help me out.
How can I get that generated base64 into my docdefinition?
function convertImageToDataURL(src, callback, outputFormat) {
// Create an Image object
var img = new Image();
// Add CORS approval to prevent a tainted canvas
img.crossOrigin = 'Anonymous';
img.onload = function() {
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var dataURL;
canvas.height = this.naturalHeight;
canvas.width = this.naturalWidth;
ctx.drawImage(this, 0, 0);
dataURL = canvas.toDataURL(outputFormat);
callback(dataURL);
// Mark the canvas to be ready for garbage
// collection
canvas = null;
};
img.src = src;
// make sure the load event fires for cached images too
if (img.complete || img.complete === undefined) {
// Flush cache
img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
// Try again
img.src = src;
}
}
convertImageToDataURL(
'{{asset('storage/'.$report->author->enterprises->first()->logo_image)}}',
function(dataUrl) {
// console.log('RESULT:', dataUrl);
// Put dataUrl into DocDefinition here!?!?
// return dataUrl is undefined
}
);`
Okay. As I said: I am a javascript noob. So I changed the script to this one:
function convertImageToDataURL(imgSrc) {
img = new Image();
img.src = imgSrc;
img.crossOrigin = "Anonymous";
var canvas = document.createElement("canvas");
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL("image/jpg");
canvas = null;
return dataURL;
}
It might not be beautyful nor elegant, but it works for me.

Draw Image to Canvas and encode it via base64

I'm trying to draw an existing image onto a canvas and encode it via base64. Here is my code:
var canvas = document.createElement("canvas");
canvas.id = "MyCanvas";
document.getElementById("Table1").appendChild(canvas);
var myCanvas = document.getElementById("MyCanvas");
var myCanvasContext = myCanvas.getContext("2d");
myCanvas.width = 135;
myCanvas.height = 170;
var img = new Image();
img.onload = function(){
myCanvasContext.drawImage(img,0,0);
}
img.src = "https://example.com/asd.png";
var toURL = myCanvas.toDataURL();
console.log(toURL);
It draws the image to the canvas, but the toURL is an empty image base64 code with 135x170 size. I've tried to decode it, but it always shows a blank image.
I can't find what is the problem with it.
The problem is that myCanvas.toDataURL(); is called before the image is actually loaded. For this you'd need to move it inside the onload-callback, like:
var img = new Image();
img.onload = function(){
myCanvasContext.drawImage(img,0,0);
// ...moved here
var toURL = myCanvas.toDataURL();
console.log(toURL);
}
img.src = "https://example.com/asd.png";
The following is a simplified example:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = "";
img.src = 'https://www.gravatar.com/avatar/8939f42cb6c31e31e570ea8f07fe9757?s=32&d=identicon&r=PG';
img.onload = () => {
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0);
console.log(canvas.toDataURL());
};
document.body.appendChild(canvas); // append the canvas ...
document.body.appendChild(img); // ... and img for demo purposes only
var canvas = document.createElement("canvas");
canvas.id = "MyCanvas";
document.getElementById("Table1").appendChild(canvas);
var myCanvas = document.getElementById("MyCanvas");
var myCanvasContext = myCanvas.getContext("2d");
myCanvas.width = 500;
myCanvas.height = 500;
var img = new Image();
img.onload = function(){
myCanvasContext.drawImage(img,0,0);
}
img.src = "http://underthebridge.co.uk/wp-content/uploads/2014/03/Example-main-image1.jpg";
var toURL = myCanvas.toDataURL();
console.log(toURL);
var img2 = document.createElement("img");
img2.id = "MyImg";
img2.src = toURL;
document.getElementById("Table1").appendChild(img2);
<div id='Table1'> </div>
You can't put an base64 inside a canvas but only in a tag img.

Modifying source of file FileReader

So i have an image that is read via the FileReader with the following code:
var reader = new FileReader();
reader.onload = function (e) {
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.src = e.target.result;
imageObj.onload = function(){
//
canvas.width = this.width;
canvas.height = this.height;
// Move them before drawing anything.
context.drawImage(imageObj, 0,0);
context.font = "40pt Calibri";
context.fillText("My TEXT!", 20, 20);
console.log(e.target.result);
console.log(canvas.toDataURL("image/jpeg"));
BuildingService.addFile({file: file, filename: guid});
category.Pictures.push({offlineFoto: canvas.toDataURL(), FileNameOnDevice: guid});
};
leftToProcess--;
if (leftToProcess == 0) {
$scope.loadingCat = false;
$scope.loadingSubCat = false;
}
$scope.$apply();
};
reader.readAsDataURL(file);
Then on the line where I do BuildingService.addFile() I add the file, but now it still contains the original data of that file.
But I have no clue on how to modify the file object, that the new base64 image data is in the file.
So how would you do this?

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