0

I want to identify a directory, 'inbox_screenshots', which contains a list of up to 100 png files from 1-100. I want to loop through each image and write its filename onto the actual image (i.e 1.png written onto 1.png etc)

I have tried

for (i = 1; i < 100; i++) {
  let fname = path + i + ".png"
  fs.access(fname, (err) => {
    if (err) {
      console.log("The file does not exist.");
    } else {
      console.log("The file exists.");
      Jimp.read(fname)
        .then(function (image) {
          loadedImage = image;
          return Jimp.loadFont(Jimp.FONT_SANS_128_BLACK);
        })
        .then(function (font) {
          loadedImage.print(font, 900, 100, i)
            .write(fname);
        })
        .catch(function (err) {
          console.error(err);
        });
    }
  });
}

After running this all the images have 100 typed onto them, rather than 1,2,3,4,5etc (filenames are 1.png->100.png)

I also tried

fs.readdirSync(path).forEach(file => {
    console.log(file);
    Jimp.read(path + file)
        .then(function (image) {
            loadedImage = image;
            return Jimp.loadFont(Jimp.FONT_SANS_128_BLACK);
        })
        .then(function (font) {
            loadedImage.print(font, 900, 100, file)
                .write(path + file);
        })
        .catch(function (err) {
            console.error(err);
        });
});

This works for writing the filenames onto the images but it writes ALL the filenames onto each image, overlapping, so there will be 1,2,3,4,5,6,7,8,9 etc all on each image, overlapped.

Would appreciate a point in the right direction.

EDIT i was missing a let in the first example

Now when i add the let it puts the filename on the image but it keeps stacking the last filename onto it, for example the 6th iteration will have 1,2,3,4,5,6 on it, rather than just 6. Here's an example: https://i.gyazo.com/1c29db37dc564c75f78a696ca46cfc80.png (i can't add images yet)

Dave
  • 23
  • 1
  • 5
  • 1
    In your first version, it should be `for (let i = 1; i < 100; i++)` — the `let` is the key. – Pointy Dec 07 '20 at 14:31

2 Answers2

0

try this

for (let i = 1; i < 100; i++) {
  let fname = path + i + ".png"
  fs.access(fname, (err) => {
    if (err) {
      console.log("The file does not exist.");
    } else {
      console.log("The file exists.");
      Jimp.read(fname)
        .then(function (image) {
          loadedImage = image;
          return Jimp.loadFont(Jimp.FONT_SANS_128_BLACK);
        })
        .then(function (font) {
          console.log("writing to file: ", i);
          loadedImage.print(font, 900, 100, i)
            .write(fname);
        })
        .catch(function (err) {
          console.error(err);
        });
    }
  });
}

let i statement might be critical here.

canbax
  • 3,432
  • 1
  • 27
  • 44
  • Appreciated - but now when i writes onto the images each filename before the current iteration is added onto the image i.e for the 6th iteration it adds 1,2,3,4,5 and 6 onto the image. Do you have any ideas how to stop that? I've added an image link on the bottom of my post – Dave Dec 07 '20 at 14:41
  • instead of *try this* explain what is wrong and why. This way people can learn and understand the problem which will prevent them from making the same mistake over and over again. – Reyno Dec 07 '20 at 14:41
  • @Reyno you are right but since I can't reproduce the problem by myself, I don't know if this really solves the problem. – canbax Dec 07 '20 at 14:43
  • @Dave I added a `console.log("writing to file: ", i);` Is the code block is inside another loop? I think the logic in these blocks is fine. – canbax Dec 07 '20 at 14:56
0

NICE, I found a solution on a separate site for singular images. i was going to ask the same question on a single image basis, If i were to do so, then someone would likely consider this a duplicate, so i'll post here.

When looking at images i had in a folder for my daughters science project, i needed the filename to be a part of the image (to show the timestamp)

I ended up with this solution (my timestamp was only a portion of my filename)

const fileInput = document.getElementById('file-input');
const canvas = document.getElementById('canvas');
const downloadBtn = document.getElementById('download-btn');
const ctx = canvas.getContext('2d');

fileInput.addEventListener('change', () => {
  const file = fileInput.files[0];
  const reader = new FileReader();

  reader.addEventListener('load', () => {
    const image = new Image();
    image.addEventListener('load', () => {
      canvas.width = image.width;
      canvas.height = image.height;
      ctx.drawImage(image, 0, 0);
      const filename = file.name.slice(9,17);
      const fontSize = Math.min(canvas.width, canvas.height) / 15;
      const lineWidth = fontSize / 10;
      const textWidth = ctx.measureText(filename).width * lineWidth;
      const margin = Math.min(canvas.width, canvas.height) / 20;
      let textX = canvas.width - textWidth - margin;
      let textY = canvas.height - fontSize - margin;
      if (textX < margin) {
        textX = margin;
      }
      if (textY < margin) {
        textY = canvas.height - margin;
      }
      ctx.font = `${fontSize}px sans-serif`;
      ctx.strokeStyle = 'white';
      ctx.lineWidth = lineWidth;
      ctx.strokeText(filename, textX, textY+200);
    });
    image.src = reader.result;
  });

  reader.readAsDataURL(file);
});

downloadBtn.addEventListener('click', () => {
  const link = document.createElement('a');
  link.download = 'image.png';
  link.href = canvas.toDataURL();
  link.click();
});
canvas {
  border: 1px solid black;
}
<html>
<div>
  <input type="file" id="file-input">
  <button id="download-btn">Download</button>
</div>
<div>
  <canvas id="canvas"></canvas>
</div>
</body>
</html>

it works fantastically.. and doesn't require node.js (but won't do batches of images)

Ryan Harger
  • 47
  • 1
  • 9