0

I'm trying to write some text on a simple jpg or png with nodejs and JIMP but i'm having issues on making it work. The picture is gotten from a telegram bot, it gets merged with another picture with canvas and then i must write some simple text on it.

Here is my code:

const Jimp = require("jimp");
      var imageCaption = 'WRITE THIS ON PICTURE';
      var loadedImage;
      const image = await Jimp.read(finalCanvas)
        .then(function (image) {
        loadedImage = image;
        return Jimp.loadFont(Jimp.FONT_SANS_16_BLACK);
        })
        .then(function (font) {
            loadedImage.print(font, 10, 10, imageCaption)
            .write(finalCanvas);
        })
        .catch(function (err) {
            console.error(err);
        });

I keep getting an error about a matching contstructor overloading not found. Also had troubles getting JIMP read my local files.

Complete error i get:

Error: No matching constructor overloading was found. Please see the docs for how to call the Jimp constructor.
    at Jimp.throwError (/home/smp0/ifsbadge/node_modules/@jimp/utils/dist/index.js:33:13)
    at new Jimp (/home/smp0/ifsbadge/node_modules/@jimp/core/dist/index.js:412:85)
    at _construct (/home/smp0/ifsbadge/node_modules/@babel/runtime/helpers/construct.js:19:21)
    at /home/smp0/ifsbadge/node_modules/@jimp/core/dist/index.js:926:32
    at new Promise (<anonymous>)
    at Function.Jimp.read (/home/smp0/ifsbadge/node_modules/@jimp/core/dist/index.js:925:10)
    at TelegramBot.<anonymous> (/home/smp0/ifsbadge/index.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:93:5) {
  methodName: 'constructor'
}

Complete context:

var needle = require('needle');
const Telegram = require('node-telegram-bot-api')
const { createCanvas, loadImage, ImageData } = require('canvas')
var Jimp = require("jimp");
var fs = require('fs');
const factions = {}


token="1234:BLABLA"
const bot = new Telegram(token, { polling: true })

bot.on('message', async (msg) => {
  if (msg.photo) {
    if (factions[msg.chat.id]) {
      console.log(`Generating badge for ${msg.from.first_name} (${msg.from.username})...`)
      bot.sendChatAction(msg.chat.id, 'upload_photo').catch(console.error)
      const pictureCanvas = createCanvas(559, 772)
      const pictureCtx = pictureCanvas.getContext('2d')
      const { file_path } = await bot.getFile(msg.photo[msg.photo.length - 1].file_id)
      const picture = await loadImage(`https://api.telegram.org/file/bot${token}/${file_path}`)
      

    // PICTURE CALCULATIONS
      pheight = picture.height
      pwidth = picture.width
      aspectratiow = (pwidth/pheight)
      aspectratioh = (pheight/pwidth)
      oheight = pheight*aspectratioh
      owidth = (pwidth) / (pwidth/559)
      newheight = 559*pheight/pwidth     
      var scale = Math.min(559/pwidth, 772/pheight);
      var posx = (559 / 2) - (559 / 2) * scale;
      var posy = (772 / 2) - (pheight / 2) * scale;
    // END OF CALCULATIONS
      
    // MERGING TWO PICTURES
      pictureCtx.drawImage(picture, 10 , posy, 559, newheight)
      const finalCanvas = createCanvas(559, 772)
      const finalCtx = finalCanvas.getContext('2d')
      const frame = await loadImage(`./frames/${factions[msg.chat.id]}.png`)
      finalCtx.drawImage(pictureCanvas, 0, 0, 559, 772)
      finalCtx.drawImage(frame, 0, 0, 559, 772)
      factions[msg.chat.id] = null
    // END OF MERGING PICTURES
      
    //APPLYING TEXT ON PICTURE
      
      const Jimp = require("jimp");
      var imageCaption = 'WRITE THIS ON PICTURE';
      var loadedImage;
      const image = await Jimp.read(finalCanvas)
        .then(function (image) {
        loadedImage = image;
        return Jimp.loadFont(Jimp.FONT_SANS_16_BLACK);
        })
        .then(function (font) {
            loadedImage.print(font, 10, 10, imageCaption)
            .write(finalCanvas);
        })
        .catch(function (err) {
            console.error(err);
        });
    //END OF APPLYING TEXT ON PICTURE
      
      
      bot.sendPhoto(msg.chat.id, finalCanvas.toBuffer('image/jpeg', { quality: 1 }))
    } else {
      bot.sendMessage(msg.chat.id, 'Write /enl1 /enl2 /enl3 o /res1 /res2 /res3 o /xf1 /xf2 !').catch(console.log)
    }
  }
})

bot.onText(/\/start/, async (msg) => {
  bot.sendMessage(msg.chat.id, "Welcome! Select your badge Write /enl1 /enl2 /enl3 o /res1 /res2 /res3 o /xf1 /xf2 !").catch(console.log)
})

bot.onText(/\/(enl1|enl2|enl3|res1|res2|res3|xf1|xf2)/, async (msg, match) => {
  factions[msg.chat.id] = match[1]
  bot.sendMessage(msg.chat.id, 'Good! Now send me your picture').catch(console.log)
})

srcs on github: https://github.com/pedrofracassi/badgemaker and https://github.com/FerdinandoLM/IngressFSBadgeMaker

  • Using a locally saved file with ```picurl=`https://api.telegram.org/file/bot${token}/${file_path}` picname = "test.jpg" var https = require('https'); var file = fs.createWriteStream(`pics/${picname}.jpg`); var request = https.get(picurl, function(response) { response.pipe(file); });``` and using ```Jimp.read(`pics/${picname}.jpg`)``` gives ```Error: Could not find MIME for Buffer ``` as error – FerdinandoLM Feb 13 '21 at 16:43
  • not entirely sure, can u post the code in the question? – seanplwong Feb 16 '21 at 04:03
  • @seanplwong sure, here it is: https://pastebin.com/BtNqz4fE i have to use pastebin due to character limit on stackoverflow – FerdinandoLM Feb 17 '21 at 10:15

1 Answers1

0

From what I can see, finalCanvas is an instance of Canvas. I don't think Jimp would take an instance of Canvas, but Canvas#toBuffer() might be the thing you want as Jimp would take a buffer: Jimp.read(finalCanvas.toBuffer())


Both http.get and response.pipe(writeStream) are asynchronous. At the time you try Jimp.read, the file isn't in the file system yet or it is not completely written onto disk.

To do it after file is written, listen to finish event.

file.on('finish', async () => {
  await Jump.read(...);
});
seanplwong
  • 1,051
  • 5
  • 14
  • Already did that but ended with a Error: path must be a string. So i used fs to actually save a file and give the path to JIMP, but got a ERRNOENT, caused by the fact that Jimp seemed to not find the file. – FerdinandoLM Feb 13 '21 at 16:34