0

I wrote a node.js script to use jimp to get all image files from a directory, (which I take as input), run some manipulations on that and then save them in the target directory (another input) as filename.suffix.extension. I take suffix also as input.

But I only see the last file from the list that I collect as to be present in the target directory.

// imports
var Jimp = require('jimp');
const fs = require('fs')

// inputs
dir = process.argv[2]
target = process.argv[3]
suffix = process.argv[4]

// collect files
let dirCont = fs.readdirSync( dir );
const files = dirCont.filter( ( elm ) => /.*\.(png|jpg)/gi.test(elm) );

// run jimp on each file and write to target directory
for (file in files)
{  
    target_file = target+files[file].replace(/\.[^/.]+$/, "")+'.'+suffix+files[file].match(/\.[^/.]+$/)
    Jimp.read(dir+'/'+files[file]).then(function (file) {
        return file.resize(256, 256)     // resize
             .quality(60)                 // set JPEG quality
             .greyscale()                 // set greyscale
             .write(target_file); // save
    })

}

I run the entire thing using grunt.

following up from this question, things that I tried:

but still pretty much not working

Immediately-Invoked Function Expression

var Jimp = require('jimp');
const fs = require('fs')

dir = process.argv[2]
target = process.argv[3]
suffix = process.argv[4]
let dirCont = fs.readdirSync( dir );
const files = dirCont.filter( ( elm ) => /.*\.(png|jpg)/gi.test(elm) );

for (file in files)
{
    (function(index) {
    console.log("index: "+index)
    target_file = target+files[index].replace(/\.[^/.]+$/, "")+'.'+suffix+files[index].match(/\.[^/.]+$/)
    Jimp.read(dir+'/'+files[index]), function (err, filee) {
             if (err) throw err;
             filee.resize(256, 256)     // resize
             .quality(60)                 // set JPEG quality
             .greyscale()                 // set greyscale
             .write(target_file); // save
    }
    })(file);

}

Result:

Still only the last file is written

Function.prototype.bind

var Jimp = require('jimp');
const fs = require('fs')

dir = process.argv[2]
target = process.argv[3]
suffix = process.argv[4]
let dirCont = fs.readdirSync( dir );
const files = dirCont.filter( ( elm ) => /.*\.(png|jpg)/gi.test(elm) );
var funcs = {}
for (file in files)
{
    console.log(file)
    console.log(files[file])

    target_file = target+files[file].replace(/\.[^/.]+$/, "")+'.'+suffix+files[file].match(/\.[^/.]+$/)
    funcs[file] = Jimp.read(dir+'/'+files[file]), function (err, filee) {
        return filee.resize(256, 256)     // resize
             .quality(60)                 // set JPEG quality
             .greyscale()                 // set greyscale
             .write(target_file); // save
    }.bind(this, file)

}

for (var j = 0; j < 3; j++) {
  funcs[j]();
}

Result:

Error message:

  funcs[j]();
          ^
TypeError: funcs[j] is not a function

I discovered it is a promise object

forEach implementation

still only the last iteration was printed

Can anyone help me on this?

J. Doe
  • 33
  • 3

1 Answers1

2

The issue is that target_file, in each of these, is a shared variable (each iteration is modifying the same one). Just change:

target_file = 

to

let target_file = 

or

const target_file = 

and you should be fine.

dave
  • 62,300
  • 5
  • 72
  • 93
  • I am new to js, thanks for the quick reply. I thought that `target_file` was a local variable and constructing and destroying with each function call – J. Doe Jul 06 '18 at 20:59
  • would you answer that even if the `target_file` is a shared variable, I am writing the files inside each iteration. It seems like the writing part happened after the iterations were finished – J. Doe Jul 06 '18 at 21:04
  • when you do `Jimp.read(dir+'/'+files[file]), function (err, filee) { /* do stuff */ })`, the `/* do stuff */` part is a callback, which implies it's going to happen asynchronously. By the time that function runs, most likely, every iteration of the loop has completed (and then the callback gets called once for each file, but they all write to the same target_file so it seems as if only one of them was called). – dave Jul 06 '18 at 21:30