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.
Related
I am using canvas npm for create images, and trying to convert to readable stream and put it in a variable seems to corrupt.
This is how I save it:
let fullStream;
let stream = canvas.createPNGStream(null, { quality: 1 })
stream.on('data', (d) => {
d = d.toString()
if (!fullStream) fullStream = d
else fullStream = fullStream + d
})
The question is, what am I doing wrong for corrupt, how to fix and how to save it in a variable.
The result of fullStream seems fine, but it is not.
createPNGStream is readable stream you just need to pipe the output to writable stream without handling the chunks
const fs = require('fs')
const { createCanvas, loadImage } = require('canvas')
// create canvas
const canvas = createCanvas(200, 200)
const ctx = canvas.getContext('2d')
ctx.font = '30px Impact'
ctx.rotate(0.1)
ctx.fillText('Awesome!', 50, 100)
const text = ctx.measureText('Awesome!')
ctx.strokeStyle = 'rgba(0,0,0,0.5)'
ctx.beginPath()
ctx.lineTo(50, 102)
ctx.lineTo(50 + text.width, 102)
ctx.stroke()
//save to png
const out = fs.createWriteStream(__dirname + '/test.png')
const stream = canvas.createPNGStream()
stream.pipe(out)
out.on('finish', () => console.log('The PNG file was created.'))
my code runs first perfectly but now not anymore.
its a welcome card for a discord server.
here's how it should have looked:
https://imgur.com/GEcULY5.png
and here's how it looks now:
https://imgur.com/cHLr2Bi.png
here is the code:
client.on("guildMemberAdd",async member => {
var name = member.displayName
var id = member.id
var membercount = member.guild.memberCount
var displayAvatarURL = member.user.displayAvatarURL({format:"jpg"})
var joinimage = Canvas.createCanvas(2000,1000)
var ctx = joinimage.getContext("2d")
var background = await Canvas.loadImage("./background.png")
ctx.drawImage(background,0,0,2000,1000)
ctx.textAlign = "center"
ctx.font = '120px Arial';
ctx.fillStyle = '#ffffff';
ctx.fillText("welkom",1400,400)
ctx.fillText(name,1400,550)
ctx.font = '60px Arial';
ctx.fillText(("Maak veel plezier in PixelKingdoms!"),1400,750)
const avatar = await Canvas.loadImage(displayAvatarURL)
ctx.beginPath();
ctx.arc(500, 500, 300, 0, 2 * Math.PI);
ctx.clip();
ctx.drawImage(avatar, 200, 200, 600, 600);
ctx.lineWidth = 20;
ctx.strokeStyle = "white";
ctx.stroke();
ctx.closePath()
const attachment = new discord.MessageAttachment(joinimage.toBuffer(), 'welcome-image.png');
member.guild.channels.cache.get("873169519881900033").send("Hey <#"+id+">Welkom in **"+member.guild.name+"**!",attachment)
var fanrole = member.guild.roles.cache.get("873163741276033084")
member.roles.add(fanrole)
})```
(sorry for bad english)
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;
},
Is there a way to convert multiple base64 PNG files to PDF?
Thanks
I was able to solve the problem using node-canvas
const fs = require('fs');
const {createCanvas, loadImage}= require('canvas');
// get the base64 string
const base64String = require("./base64");
loadImage(Buffer.from(base64String, "base64")).then(async (img) => {
const canvas = createCanvas(img.width, img.height, 'pdf');
const ctx = canvas.getContext('2d');
console.log(`w: ${img.width}, h: ${img.height}`);
ctx.drawImage(img, 0, 0, img.width, img.height);
const base64image = canvas.toBuffer();
// write the file to a pdf file
fs.writeFile('simple.pdf', base64image, function(err) {
console.log('File created');
});
});
for more info: https://www.npmjs.com/package/canvas
Note: solution works not only for png but any image type.
Then use any pdf library to merge the pdfs like hummus
I think you are looking for this.
import fs from 'fs';
let base64String = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA';
// Remove header
let base64image = base64String.split(';base64,').pop();
fs.writeFile('filename.pdf', base64image, {encoding: 'base64'}, function(err) {
console.log('File created');
});
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!