I'm looking for a clean way to convert a SVG to PNG and download, in Vue 2. What is the best approach ?
I finally managed to come up with this solution:
save() {
const a = document.querySelector("a");
const triggerDownload = (imgURI: string) => {
const evt = new MouseEvent("click", {
view: window,
bubbles: false,
cancelable: true,
});
a?.setAttribute("download", "FileName.png");
a?.setAttribute("href", imgURI);
a?.setAttribute("target", "_blank");
a?.dispatchEvent(evt);
};
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
const ctx = canvas.getContext("2d");
data = new XMLSerializer().serializeToString(
document.getElementById("svgId") as Node
);
const DOMURL = window.URL || window.webkitURL || window;
const img = new Image();
const svgBlob = new Blob([data], { type: "image/svg+xml;charset=utf-8" });
const url = DOMURL.createObjectURL(svgBlob);
img.onload = function () {
ctx?.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
const imgURI = canvas
.toDataURL("image/png")
.replace("image/png", "image/octet-stream");
triggerDownload(imgURI);
ctx?.clearRect(0, 0, canvas.width, canvas.height);
};
img.src = url;
},
Related
I keep getting this error when importing an image and using canvas with discord.js:
C:\Users\Travi\OneDrive\Documents\GitHub\re\src\img\licenseTemp.png:1
�PNG
SyntaxError: Invalid or unexpected token
Here's my code:
I'm also using module Alias so that's why it's const licenseTemp = require('#img')
const BaseCommand = require('../../utils/structures/BaseCommand');
const Canvas = require('canvas');
const { MessageAttachment } = require('discord.js');
const licenseTemp = require('#img');
module.exports = class RankCommand extends BaseCommand {
constructor() {
super('rank', 'Information', []);
}
async run(client, message, args) {
const canvas = Canvas.createCanvas(449, 292);
const ctx = canvas.getContext('2d');
const background = await Canvas.loadImage(licenseTemp);
ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
const attachment = new MessageAttachment(canvas.toBuffer(), 'license.png');
message.channel.send(attachment);
}
}
Do not require('#img'), this will try to make your image's content read as text be part of the script.
Instead let node-canvas's loadImage handle the fetching of that resource: make licenseTemp be the URL to that image directly.
I want to change the style when the feature is modifying, but once the feature's style has been setting, its modify would be stopped, how can I change the style and it still can modify?
here is the code:
this.modify.on(['modifystart', 'modifyend'], function (evt) {
target.style.cursor = evt.type === 'modifystart' ? 'grabbing' : 'pointer'
const currentFeature = evt.features.array_[0]
const oldStyle = currentFeature.getStyle()
console.log(oldStyle)
console.log(evt.type)
if (evt.type === 'modifystart') {
const moveImage = new Image()
const pinInfo = evt.features.array_[0].get('pinInfo')
moveImage.src = that.moveIcon
moveImage.width = 50
moveImage.height = 70
moveImage.onload = function () {
const iconCanvas = document.createElement('canvas')
iconCanvas.width = moveImage.width
iconCanvas.height = moveImage.height
const iconCanvasCtx = iconCanvas.getContext('2d')
// 背景アイコンを描画
iconCanvasCtx.drawImage(moveImage, 0, -25, 50, 70)
const style = new Style({
image: new Icon({
anchor: [0.5, 0.5],
img: iconCanvas,
imgSize: [moveImage.width, moveImage.height],
scale: that.imgSize / 30
})
})
// const arrayStyle = [style, oldStyle]
currentFeature.setStyle(style)
}
} else if (evt.type === 'modifyend') {
// currentFeature.setStyle(oldStyle)
}
})
Thanks a lot!
I am developing an face detection application,for that I need to collect the users image for reference to detect them later.i have successfully uploaded the image in MySQL databse.now I need upload the image in public folder in react to detect the image in camera.i stuck in uploading image in react public folder.help me out get rid of this problem..
This is the React code where image to be detected in the imgUrl variable
detect = async () => {
const videoTag = document.getElementById("videoTag");
const canvas = document.getElementById("myCanvas");
const displaySize = { width: videoTag.width, height: videoTag.height };
faceapi.matchDimensions(canvas, displaySize);
//setInterval starts here for continuous detection
time = setInterval(async () => {
let fullFaceDescriptions = await faceapi
.detectAllFaces(videoTag)
.withFaceLandmarks()
.withFaceExpressions()
.withFaceDescriptors();
const value = fullFaceDescriptions.length;
this.setState({ detection: value });
fullFaceDescriptions = faceapi.resizeResults(
fullFaceDescriptions,
displaySize
);
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
//Label Images
var dummy = ["praveen", "vikranth", "Gokul", "Rahul"];
const labels = nameArray1;
// const labels = ["praveen", "vikranth", "Gokul", "Rahul"];
if (no_of_times <= 0) {
if (no_of_times === 0) {
labeledFaceDescriptors = await Promise.all(
labels.map(async (label) => {
// fetch image data from urls and convert blob to HTMLImage element
const imgUrl = `/img/${label}.png`; // for testing purpose
// const imgUrl = testImage;
const img = await faceapi.fetchImage(imgUrl);
const fullFaceDescription = await faceapi
.detectSingleFace(img)
.withFaceLandmarks()
.withFaceExpressions()
.withFaceDescriptor();
if (!fullFaceDescription) {
throw new Error(`no faces detected for ${label}`);
}
const faceDescriptors = [fullFaceDescription.descriptor];
return new faceapi.LabeledFaceDescriptors(label, faceDescriptors);
})
);
// console.log(no_of_times);
}
}
const maxDescriptorDistance = 0.7;
no_of_times++;
const faceMatcher = new faceapi.FaceMatcher(
labeledFaceDescriptors,
maxDescriptorDistance
);
const results = fullFaceDescriptions.map((fd) =>
faceMatcher.findBestMatch(fd.descriptor)
);
result = [];
results.forEach((bestMatch, i) => {
const box = fullFaceDescriptions[i].detection.box;
// console.log(box)
const text = bestMatch.toString(); //this for basMatch name detection
var str = "";
//This is for removing names confidence to map value without duplicate
var val = text.replace(/[0-9]/g, "");
for (let i of val) {
if (i !== " ") {
str += i;
} else {
break;
}
}
if (result.includes(str) === false) result.push(str);
const drawBox = new faceapi.draw.DrawBox(box, { label: text });
drawBox.draw(canvas);
faceapi.draw.drawFaceExpressions(canvas, fullFaceDescriptions, 0.85);
});
for (let i = 0; i < fullFaceDescriptions.length; i++) {
const result1 = fullFaceDescriptions[i].expressions.asSortedArray()[i];
// console.log(result[i]);
// console.log(result1.expression);
this.test(result[i], result1.expression);
}
}, 100);
In the above code i am manually putting image in public folder,this need to be done dynamically when the user uploads image.
this is place i get the images in base64 from nodejs
axios.get("/image").then((res) => {
testImage = res.data;
// console.log("from image" + res.data);
imgback = <img src={`data:image/jpeg;base64,${res.data}`} />;
});
This is nodejs code for the get request from reactjs
app.get("/image", (req, res) => {
connection.query("SELECT * FROM images", (error, row, fields) => {
if (!!error) {
console.log("Error in the query");
} else {
console.log("successful query");
var buffer = new Buffer(row[0].image, "binary");
var bufferBase64 = buffer.toString("base64");
res.send(bufferBase64);
}
});
});
my goal is, in the imgUrl variable in react code i need to specify the image folder for that i need to dynamically add image in folder.
Or is there is any other way to directly give image array in the imgUrl variable.please help me to sort out this problem.
I am trying to write on image with hindi language. I am using node-canvas library. There is some problem with my output. Can someone help me ?
const { createCanvas, loadImage, registerFont} = require('canvas')
const canvas = createCanvas(400, 400)
const ctx = canvas.getContext('2d')
var str= "यह. मिसिसिपी है";
console.log(str);
loadImage('missisippi.jpg').then((image) => {
console.log(image);
ctx.drawImage(image, 0 , 0, 400, 400);
ctx.fillText(str,100,40);
var body = canvas.toDataURL(),
base64Data = body.replace(/^data:image\/png;base64,/,""),
binaryData = new Buffer(base64Data, 'base64').toString('binary');
require("fs").writeFile("out.png", binaryData, "binary", function(err) {
console.log(err); // writes out file without error, but it's not a valid image
})
// console.log('<img src="' + canvas.toDataURL() + '" />')
})
This is the output image . You can see that मिसिसिपी is grammatically wrong. (In case u are familiar with Hindi.
I have also tried the very same thing with npm-gm. in that too I faced same issue. Can someone help me out in this issue ?
How can I write text on image with custom font ?
The following is working fine for me -
var fs = require('fs')
var path = require('path')
var Canvas = require('canvas')
function fontFile (name) {
return path.join(__dirname, '/fonts/', name)
}
Canvas.registerFont(fontFile('ARBLI___0.ttf'), {family: 'ARBLI___0'})
var canvas = Canvas.createCanvas(7100, 3500)
var ctx = canvas.getContext('2d')
var Image = Canvas.Image;
var img = new Image();
img.src = 'input/DOIT_Art_Size.jpg';
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.font = '150pt ARBLI___0'
ctx.fillText('यह मिसिसिपी है',3900, 1700)
canvas.createPNGStream().pipe(fs.createWriteStream(path.join(__dirname, 'output/font.png')))
canvas.createJPEGStream().pipe(fs.createWriteStream(path.join(__dirname, 'output/font.jpg')))
My node version is 6.11.2.
Canvas module is 2.0.0-alpha.16.
My input image dimension is 7100*3500 pixels.
I'm trying to create and image on the Google Firebase server with node-canvas and store it in Firebase Storage.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const gcs = require('#google-cloud/storage')();
const path = require('path');
const Canvas = require('canvas-prebuilt');
const env = require('dotenv').config();
try {admin.initializeApp(functions.config().firebase);} catch(e) {}
//Trigger on creation of a new post
exports.default = functions.database.ref('/posts/{postId}').onCreate(event => {
//Get the postID
const postId = event.params.postId;
console.log('We have a new post ' + postId);
//Get data from the postid
return admin.database().ref('/posts/' + postId).once('value').then(function(snapshot) {
const text = snapshot.val().text;
const canvas = new Canvas(1024, 512);
const ctx = canvas.getContext('2d');
//Draw Background
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, 1024 , 512);
//Draw Text
ctx.font = 'bold 66px Arial';
ctx.textAlign = 'center';
ctx.fillStyle = '#fff';
ctx.fillText(text, 120, 256, 784);
// Use the postID to name the file Ex : -L1rVJUAtSbc_FampT0D.png
var filename = postId + '.png';
// Create the file metadata
var metadata = {
contentType: 'image/png'
};
const bucket = gcs.bucket('images');
const filePath = 'images/' + filename;
return canvas.toDataURL('image/png', function(err, png){
//Save on Firebase Storage
return bucket.upload(png, {
destination: filePath,
metadata: metadata
}).then(() => {
console.log('Image uploaded to Storage at ', filePath);
});
});
});
});
But, when I try to save it with toDataURL I get this error :
ENAMETOOLONG: name too long, stat 'data:image/png;base64,iVBORw0 ...'
And when I try with toBuffer I get this one :
TypeError: Path must be a string. Received
at assertPath (path.js:7:11)
at Object.basename (path.js:1362:5)
at Bucket.upload (/user_code/node_modules/#google-cloud/storage/src/bucket.js:2259:43)
at /user_code/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:777:22
at Bucket.wrapper [as upload] (/user_code/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:761:12)
at /user_code/sendTweet.js:107:21
I also try toBlob but the function doesn't exist server side with node-canvas.
Anyone know how I should save the image server side before transfer it to Firebase Storage?
Thanks!