I am trying to load an image with loadImage function of canvas with a path, but it doesn't find it and i don't know why because it is supposed to loadImage only if the path exists.
Err : `Error: ENOENT, No such file or directory 'C:/Users/elpepito11/OneDrive/Bureau/Topaz/base de données/serveurs/1066636825604657183/welcome/welcomeimage/welcomeimage.jpg'
Code :
if(fs.existsSync(imagepath)){
const { createCanvas, loadImage } = require('canvas');
const canvas = createCanvas(1920, 1080);
const ctx = canvas.getContext('2d');
const background = await loadImage(imagepath);
}
imagepath :
const serverpath = path.join(__dirname, '..','..','..', "base de données",'serveurs',interaction.guild.id)
const dossierimage = path.join(serverpath, 'welcome', 'welcomeimage')
const imagepath = path.join(dossierimage, 'welcomeimage.jpg')
I was excepting it to find the file.
Related
On a server I am running node.js with matter.js, jsDom and Canvas. I need to capture the rendered scene into a file. There is a simple scene with a number of rectangles. The code is;
const frameRate = 1000 / 30;
const intervalRate = 1000 / 15;
const dom = new JSDOM('<!DOCTYPE html><body><canvas id="output"></canvas></body>');
global.document = dom.window.document;
const canvas = document.getElementById("output");
const renderer = Render.create({
element: canvas,
engine: engine,
options: {}
});
setInterval(() => {
Engine.update(engine, frameRate);
Render.world(renderer);
let img = canvas.toDataURL("image/png");
let base64Data = img.replace(/^data:image\/png;base64,/, "");
let fname = ""+(new Date()).getMilliseconds();
fs.writeFile(`./images/${fname}.png`, base64Data, 'base64', function(err) {
if (err){
console.log(err);
}
});
}, intervalRate);
I have traced through Render.world(renderer) and it seems to draw the lines into the canvas, but the images are rendered blank. What am I doing wrong that I don't see any content?
EDIT:
The correct use is
const renderer = Render.create({
canvas,
engine: engine,
options: {}
});
I'm attempting to put a watermark image on an input image before saving it to a database. I'm using a canvas to do this then convert the canvas back to a blob but when I reference the watermark image in the projects local file directory to draw onto the canvas, I get a "Tainted canvases may not be exported." error in the console.
// Read input file
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
// Create canvas & calculate Stamp size and position
const canvas = document.createElement("canvas");
canvas.width = canvasSize.width;
canvas.height = canvasSize.height;
var calcW = canvasSize.width/2;
var calcH = calcW/2.16;
var calcX = (canvasSize.width - calcW)/2;
var calcY = (canvasSize.height - calcH)/2;
// Load input image into canvas
const img = document.createElement("img");
img.src = reader.result;
img.onload = () => {
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
//Load & draw the Stamp image
const mark = new Image();
mark.src = 'assets/img/compliant.png'; // <<TAINTED ASSET?
mark.onload = () => {
ctx.drawImage(mark, calcX,calcY,calcW,calcH);
// Convert to blob and get URL
canvas.toBlob((canvasBlob) => {
const newImg = document.createElement("img"),
url = URL.createObjectURL(canvasBlob);
newImg.onload = function () {
//Destroy objecturl after image loading
URL.revokeObjectURL(url);
};
// Show stamped image
newImg.src = url;
window.open(url);
});
};
};
};
});
You have to use
img.crossOrigin='anonymous';
On every image you want to manipulate (draw in a canvas, transform to an array buffer… this is to prevent you from manipulating potentially private user data)
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attr-crossorigin
Over the past few months, I have been working on this code that deals with ellipsoidal earth and just recently I have finished it. My professor now wants me to send him pictures of the diagrams I made as an SVG file. I know in Python you can put a few lines of code into your project to have it download the image, but I am unsure how it works in JavaScript. How can I do this in JavaScript, or is there another easier way?
Check out this demo: https://codepen.io/Alexander9111/pen/VwLaaPe?editors=1010
Code (modified from https://stackoverflow.com/a/19885344/9792594):
function downloadSVGasTextFile() {
const base64doc = btoa(unescape(encodeURIComponent(document.querySelector('svg').outerHTML)));
const a = document.createElement('a');
const e = new MouseEvent('click');
a.download = 'download.svg';
a.href = 'data:text/html;base64,' + base64doc;
a.dispatchEvent(e);
}
downloadSVGasTextFile();
You encode your svg as a 64bit string and then use that as the href of an anchor tag and then dispatch a click event to download the svg text file as download.svg
If you want to save an image, such as .png then you can first draw svg image into a cnavas then download that as .png,
UPDATE
I modified the answer and the demo to now include both download as text file .svg or download as image file .png https://codepen.io/Alexander9111/pen/VwLaaPe:
HTML:
<svg>
...
</svg>
<br/>
<button id="downloadPNG">Download .png</button>
<button id="downloadSVG">Download .svg</button>
JS:
function downloadSVGAsText() {
const svg = document.querySelector('svg');
const base64doc = btoa(unescape(encodeURIComponent(svg.outerHTML)));
const a = document.createElement('a');
const e = new MouseEvent('click');
a.download = 'download.svg';
a.href = 'data:image/svg+xml;base64,' + base64doc;
a.dispatchEvent(e);
}
function downloadSVGAsPNG(e){
const canvas = document.createElement("canvas");
const svg = document.querySelector('svg');
const base64doc = btoa(unescape(encodeURIComponent(svg.outerHTML)));
const w = parseInt(svg.getAttribute('width'));
const h = parseInt(svg.getAttribute('height'));
const img_to_download = document.createElement('img');
img_to_download.src = 'data:image/svg+xml;base64,' + base64doc;
console.log(w, h);
img_to_download.onload = function () {
canvas.setAttribute('width', w);
canvas.setAttribute('height', h);
const context = canvas.getContext("2d");
//context.clearRect(0, 0, w, h);
context.drawImage(img_to_download,0,0,w,h);
const dataURL = canvas.toDataURL('image/png');
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(canvas.msToBlob(), "download.png");
e.preventDefault();
} else {
const a = document.createElement('a');
const my_evt = new MouseEvent('click');
a.download = 'download.png';
a.href = dataURL;
a.dispatchEvent(my_evt);
}
//canvas.parentNode.removeChild(canvas);
}
}
const downloadSVG = document.querySelector('#downloadSVG');
downloadSVG.addEventListener('click', downloadSVGAsText);
const downloadPNG = document.querySelector('#downloadPNG');
downloadPNG.addEventListener('click', downloadSVGAsPNG);
I am developing angular application and trying to decode image with QR code on client side only and facing with next errors.
I have next flow:
User uploads image.
I decode qr code from image.
<input type="file" name="file" id="file" accept="image/*"(change)="qrCodeUploaded($event.target.files)"/>
I have tried next libraries:
https://github.com/zxing-js/library
qrCodeUploaded(files: FileList): void {
const fileReader = new FileReader();
const codeReader = new BrowserQRCodeReader();
fileReader.readAsDataURL(files[0]);
fileReader.onload = (e: any) => {
var image = document.createElement("img");
image.src = e.target.result;
setTimeout(() => codeReader.decodeFromImage(image, e.target.result).then(res => console.log(res)), 100);
};
}
Works for some of qr codes, but issues on mobile. If you will take a photo of QR code with your phone, it will be not decoded. So for mobile you will need to implement video.
https://github.com/cozmo/jsQR
qrCodeUploaded(files: FileList): void {
const fileReader = new FileReader();
fileReader.readAsArrayBuffer(files[0]);
fileReader.onload = (e: any) => {
console.log(new Uint8ClampedArray(e.target.result));
console.log(jsQR(new Uint8ClampedArray(e.target.result), 256, 256));
};
}
I get next error for any QR images I upload:
core.js:15714 ERROR Error: Malformed data passed to binarizer.
at Object.binarize (jsQR.js:408)
at jsQR (jsQR.js:368)
gist link:
https://gist.github.com/er-ant/b5c75c822eb085e70035cf333bb0fb55
Please, tell me what I am doing wrong and propose some solution for QR codes decoding. Open for any thoughts :)
For second library I missed that it expects ImageData and I pass Binary Data.
Thus, we have 3 solutions how to convert Binary Data to ImageData:
Use createImageBitmap Kaiido solution with some updates, as proposed in comments doesn't work.
qrCodeUploadedHandler(files: FileList): void {
const file: File = files[0];
createImageBitmap(files[0])
.then(bmp => {
const canvas = document.createElement('canvas');
const width: number = bmp.width;
const height: number = bmp.height;
canvas.width = bmp.width;
canvas.height = bmp.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(bmp, 0, 0);
const qrCodeImageFormat = ctx.getImageData(0,0,bmp.width,bmp.height);
const qrDecoded = jsQR(qrCodeImageFormat.data, qrCodeImageFormat.width, qrCodeImageFormat.height);
});
}
Get ImageData from canvas.
qrCodeUploadedHandler(files: FileList): void {
const file: File = files[0];
const fileReader: FileReader = new FileReader();
fileReader.readAsDataURL(files[0]);
fileReader.onload = (event: ProgressEvent) => {
const img: HTMLImageElement = new Image();
img.onload = () => {
const canvas: HTMLCanvasElement = document.createElement('canvas');
const width: number = img.width;
const height: number = img.height;
canvas.width = width;
canvas.height = height;
const canvasRenderingContext: CanvasRenderingContext2D = canvas.getContext('2d');
console.log(canvasRenderingContext);
canvasRenderingContext.drawImage(img, 0, 0);
const qrCodeImageFormat: ImageData = canvasRenderingContext.getImageData(0, 0, width, height);
const qrDecoded = jsQR(qrCodeImageFormat.data, qrCodeImageFormat.width, qrCodeImageFormat.height);
canvas.remove();
};
img.onerror = () => console.error('Upload file of image format please.');
img.src = (<any>event.target).result;
}
You can parse images with png.js and jpeg-js libraries for ImageData.
step:
Create a new image object from image file
Create a canvas
Draw the image to the canvas
Get ImageData through the context of canvas
Scan QR code with jsQR.
install:
npm install jsqr --save
code:
// utils/qrcode.js
import jsQR from "jsqr"
export const scanQrCode = (file, callback) => {
const image = new Image()
image.src = file.content
image.addEventListener("load", (e) => {
console.log(
"image on load, image.naturalWidth, image.naturalHeight",
image.naturalWidth,
image.naturalHeight
)
const canvas = document.createElement("canvas") // Creates a canvas object
canvas.width = image.naturalWidth // Assigns image's width to canvas
canvas.height = image.naturalHeight // Assigns image's height to canvas
const context = canvas.getContext("2d") // Creates a contect object
context.imageSmoothingEnabled = false
context.drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight) // Draws the image on canvas
const imageData = context.getImageData(0, 0, image.naturalWidth, image.naturalHeight) // Assigns image base64 string in jpeg format to a variable
const code = jsQR(imageData.data, image.naturalWidth, image.naturalHeight)
if (code) {
console.log("Found QR code", code)
callback(code)
}
})
}
use:
scanQrCode(file, (code) => {
console.log(code.data);
});
I'm using createImageBitmap() which creates an ImageBitmap file.
How do I convert this file to a blob or ideally PNG so I can upload?
The only way currently is to draw it on a canvas.
For more efficiency, you can try to use an ImageBitmapRenderingContext, which will not copy the pixels buffer again.
(async () => {
const resp = await fetch('https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png');
// yes.. from a Blob to a Blob...
const blob1 = await resp.blob();
const bmp = await createImageBitmap(blob1);
console.log(bmp); // ImageBitmap
// create a canvas
const canvas = document.createElement('canvas');
// resize it to the size of our ImageBitmap
canvas.width = bmp.width;
canvas.height = bmp.height;
// get a bitmaprenderer context
const ctx = canvas.getContext('bitmaprenderer');
ctx.transferFromImageBitmap(bmp);
// get it back as a Blob
const blob2 = await new Promise((res) => canvas.toBlob(res));
console.log(blob2); // Blob
const img = document.body.appendChild(new Image());
img.src = URL.createObjectURL(blob2);
})().catch(console.error);
Check HTMLCanvasElement#toBlob() for the options you can pass in (file format and quality when applicable).