This is an old revision of the document!
Generating Photos With Code
By: Steve Wang
// import the JIMP library var Jimp = require("jimp"); var fs = require('fs') let classPaths = [ './people/arduino.jpg', './people/ingram.jpg', './people/lee.jpg', ] let mangoPaths = [ './mango/edited-IMG_8280.jpg', './mango/edited-smoke-mengo.jpg', './mango/edited-smoke-mengo.jpg', './mango/edited-IMG_8280.jpg', ] //generated by chatgpt function getFilePaths(directoryPath) { const files = fs.readdirSync(directoryPath); const filePaths = []; files.forEach(file => { const filePath = `${directoryPath}/${file}`; const stat = fs.statSync(filePath); if (stat.isFile()) { filePaths.push(filePath); } else if (stat.isDirectory()) { const subDirectoryPath = `${directoryPath}/${file}`; const subDirectoryFilePaths = getFilePaths(subDirectoryPath); filePaths.push(...subDirectoryFilePaths); } }); return filePaths; } //getFilePaths('people') function roundOff (number,decimalPlaces){ let roundedNumber=number.toFixed(decimalPlaces); return JSON.parse(roundedNumber)} function randomRange(min, max,decimalPlaces) { if (decimalPlaces==undefined){decimalPlaces=0} } function safeSplice(inputArray, amountToRemove,indexToRemove,replaceWith) { let array1 = inputArray.slice(0, indexToRemove ) if (replaceWith!=undefined){ array1.push(replaceWith)} let array2 = inputArray.slice(indexToRemove + amountToRemove, inputArray.length) return array1.concat(array2) } // knuth shuffle from https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array function shuffle(array) { var currentIndex = array.length, randomIndex; // While there remain elements to shuffle... while (currentIndex != 0) { // Pick a remaining element... randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--; // And swap it with the current element. [array[currentIndex], array[randomIndex]] = [ array[randomIndex], array[currentIndex]]; } return array; } async function allPossibleImages (foreground, background, outputDirectory){ console.time('imageGen') let foregroundPaths = getFilePaths(foreground) let backgroundPaths = getFilePaths(background) let foregroundImgs = foregroundPaths.map(path => Jimp.read(path)); let backgroundImgs = backgroundPaths.map(path => Jimp.read(path)); makeVariationDirectories(foregroundPaths, outputDirectory) console.log('none jimp parts done') //await matchAllForegroundToAllBackgrounds(foregroundImgs, backgroundImgs, foregroundPaths, backgroundPaths, outputDirectory) await matchAllForegroundToAllBackgroundsWithRotation(foregroundImgs, backgroundImgs, foregroundPaths, backgroundPaths, outputDirectory) console.timeEnd('imageGen') } function makeVariationDirectories (foreground, outputDirectory){ fs.mkdirSync('./' + outputDirectory) foreground.forEach(x => { fs.mkdirSync('./' + outputDirectory + '/varitaions-' + getFileNameFromPath(x)) fs.copyFileSync(x, './' + outputDirectory + '/' + 'varitaions-' + getFileNameFromPath(x) + '/originalImg') }) } function getFileNameFromPath (path){ return path.slice(path.lastIndexOf('/') + 1) } function matchAllForegroundToAllBackgrounds (foregroundImgs, backgroundImgs, foregroundPaths, backgroundPaths, outputDirectory){ return Promise.all(foregroundImgs).then ((forePicture) => { return Promise.all(backgroundImgs).then ((backPicture) => { forePicture.forEach((x, n) => { backPicture.forEach((b, i) => { console.log(n, i, './' + outputDirectory + '/varitaions-' + getFileNameFromPath(foregroundPaths[n]) + '/steve' + getFileNameFromPath(backgroundPaths[i]) + '-using background' + i + '.jpg') x .composite(b,0,0, {mode:Jimp.BLEND_DIFFERENCE}) .quality(97) // set JPEG quality .write('./' + outputDirectory + '/varitaions-' + getFileNameFromPath(foregroundPaths[n]) + '/steve' + getFileNameFromPath(backgroundPaths[i]) + '-using background' + i + '.jpg'); }) }) }) resolve(true) }) } function matchAllForegroundToAllBackgroundsWithRotation (foregroundImgs, backgroundImgs, foregroundPaths, backgroundPaths, outputDirectory){ return Promise.all(foregroundImgs).then ((forePicture) => { return Promise.all(backgroundImgs).then ((backPicture) => { forePicture.forEach((x, n) => { let currentForeground = getFileNameFromPath(foregroundPaths[n]) backPicture.forEach((b, i) => { let currentBackground = getFileNameFromPath(backgroundPaths[i]) for (let r = 0; r < 4; r++) { console.log('r', r) console.log(n, i, './' + outputDirectory + '/varitaions-' + currentForeground + '/steve' + currentBackground + '-using background' + i + '-rotation' + (r * 90) + '.jpg') x .rotate(r * 90) .composite(b,0,0, {mode:Jimp.BLEND_DIFFERENCE}) .quality(97) // set JPEG quality .write('./' + outputDirectory + '/varitaions-' + currentForeground + '/steve' + currentBackground+ '-using background' + i + '-rotation'+ (r * 90) + '.jpg') } }) }) }) resolve(true) }) } allPossibleImages('multiple-blend-modes-input/more-forgrounds', 'multiple-blend-modes-input/backgrounds', 'rotated-10-testing-foreground-background') endTime = new Date () //allPossibleImages('people', 'background', 'rotation-testing-foreground-background') //only ingram and arduino uploaded to wiki: filePath = './new-testing-foreground-background/varitaions-yiler.jpg' filePath = './rotation-testing-foreground-background/varitaions-scott-and-bell.jpg' files = fs.readdirSync(filePath); files.forEach( (file,i) =>{ if (file[0]!='r'){ fs.renameSync(filePath + '/' + file, filePath + '/' + 'steve-photo-of-not-roated-yiler-JIMP-generation' + i + '.jpg') } }) wikiString = '' files = fs.readdirSync(filePath); files.forEach(x => { wikiString += '{{:students:' + x + '?400|}} \n' }) fs.writeFileSync('wikiString.txt', wikiString) let other = allFilePathsInDirectory('otherStuff') async function resizeAllImages (pathArray){ let jimpData = pathArray.map(path => Jimp.read(path)); let readData; await Promise.all(jimpData).then ((pictures) => {readData = pictures}) readData.forEach((x,i) => { if (x.bitmap.width > 400 && x.bitmap.height > 400){ x.crop(0, 0, 400, 400).quality(98).write(pathArray[i]) } else{ x.resize(400,400).quality(98).write(pathArray[i]) } }) } resizeAllImages(classPaths) function combinePhotos (pathArray, outputPath){ let jimpData = pathArray.map(path => Jimp.read(path)); Promise.all(jimpData).then ((picture) => { return picture[2] .composite(picture[0],0,0, {mode:Jimp.BLEND_LIGHTEN}) .composite(picture[1],0,0, {mode:Jimp.BLEND_DIFFERENCE}) .autocrop() .invert() .quality(97) // set JPEG quality .write(outputPath); }).catch((err) => {console.error(err)}) } let twoMangoes = [mangoPaths[0], mangoPaths[1]] combinePhotos(mangoPaths,"./output-photos/shuffled-combined.jpg") //Get all files: https://www.golinuxcloud.com/node-js-get-all-files-in-directory/ fs.readdir('classPhotos/', (err, files) => { console.log(files) files.forEach( (file,i) =>{ if (file[0]!='c' && file[1] != 'h'){ fs.renameSync('/home/steve/Documents/Code/picture-editing/classPhotos/'+file,'/home/steve/Documents/Code/picture-editing/classPhotos/'+'steve-class-photos-for-editing'+i+'.png') } }) }) console.time('counting') total = 0 for (let i = 0; i < 10000000; i++) { total += Math.random() } console.log('total', total) console.timeEnd('counting') //no multi: 113.997ms