Mosaic pictures

My old interest in picture mosaics got revived by a image I saw in a gallery recently. I don’t like the idea to upload so many (potential private) photos on a server, so I didn’t look at any online services for that. I reactivated an old license of AndreaMosaic. I soon realized not having enough suitable pictures since I put the following constraints:

  • The individual pictures should still be visible
  • The pictures should not be manipulated by the software (except for a horizontal mirroring), I wanted the original pictures to be almost preserved.

Unsplash offers millions of nice copyright-free pictures. In order to download those pictures effectively I modified the Bulksplash script in order to circumvent the picture amount restriction by looping. The script is malfunctioning as unsplash only gives you about the same random pictures. Solution: I used the script several times throughout the day and cleaned duplicates with another program (I used the free “photos duplicate cleaner” from the app store). Code below.

Using AndreaMosaic with these settings (I had to go with a considerable color change): Screenshot of the settings used in AndreaMosaic

The result has a size of 19220x12803 pixel that sum up to a file of 90 MB. I like how the nostrils turned out.

face_closup.png nostrils_closeup.png overview.png

All images are copyright-free from unsplash, including the chimpanzee.

I printed to complete this test: Chimpanzee mosaic on the wall

Installing ImageMagix with homebrew, I used this command: convert -delay 50 chimp*.png -loop 0 chimp_mosaic.gif to convert pictures to a looping gif for the front page.

Summary: Using AndreaMosaic you get a decent mosaic in a very short time. However, I would have liked more ways to manipulate (e.g. use different sizes of mosaics depending on the level of details of the underlying picutre). I found another program called studio artist which claims to be able to do all this but the review of that program will have to wait for another time.

My bulksplash mod looks something like this (you have to complement your own directory and API key). Should be on github/-lab soon...

//node node tower-git/Bulksplash/index --folder=color --collections=023267
//neu cg und https://stackoverflow.com/questions/48339532/how-to-make-multiple-paginated-get-requests-to-an-api-in-while-loop-with-node-js
const async = require("async");
let page = 1;
let json;


program
  .version('1.0.0')
  .option('--amount [limit]', 'Amount of pictures to download (Default is 10)')
  .option('--folder [name]', 'Name of the folder you want to save the images to (Default is "images")')
  .option('--width [w]', 'Width of images (Default is 1200)')
  .option('--height [h]', 'Height of images (Default is 800)')
  .option('--featured [f]', 'Download featured images only')
  .option('--search [s]', 'Download images with a specific term')
  .option('--orientation [o]', 'Image orientation (landscape, portrait, and squarish)')
  .option('--collections [c]', 'collection id')
  .parse(process.argv);

//if(!program.amount){
//    program.amount = 10
let last_page = program.amount;
//}

if(!program.folder){
    program.folder = "images"
    //program.folder = program.search;
}

if(!program.orientation){
    program.orientation= "landscape"
}

var ProgressBar = require('progress');
var bar = new ProgressBar(':bar', { total: parseInt(program.amount) });

function download(url, dest, dirname) {
    var dir = '/Volumes/SSD1T/unsplash/' + dirname; 
    if (!fs.existsSync(dir)){
        fs.mkdirSync(dir)
    }
    var file = fs.createWriteStream(dest);
    var request = https.get(url, function(response) {
        response.pipe(file);
}).on("error", function (e) {
        console.log("Error while downloading", url, e.code);
    });
};

var url = "https://api.unsplash.com/photos/random?count=30&client_id=yourapiIDhere";

if(program.width){
    var url = url + "&w=" + program.width;
}

if(program.height){
    var url = url + "&h=" + program.height;
}

if(program.search){
    var url = url + "&query=" + program.search;
}

if(program.collections){
    var url = url + "&collections=" + program.collections;
}

//console.log("\nDownloading images from:\n")

//to slow down
const sleep = require('util').promisify(setTimeout)

async.whilst(function () {
  return page <= last_page;
},
function (next) {
//  console.log(url+"&page="+ page)
request(url+"&page="+ page, (error, response, body) => {
    if (!error && response.statusCode === 200) {
        var body = JSON.parse(body);


        for (i in body){
            if(program.width || program.height){
                var img = body[i]["urls"].custom
            } else{
                var img = body[i]["urls"].raw
            }   
            console.log(body[i]["user"].name + " (" + body[i]["user"].links["html"] + ")")
download(img, path.join(__dirname,  "../yourfolder/unsplash/" +program.folder+ "/image_"+ page + i + Math.floor(Math.random()*(1000)) +".jpg"), program.folder)
        }

    } else {
        console.log("Got an error: ", error)
    }

// slow down
async function main() {
    console.time("Slept for")
    await sleep(Math.floor(Math.random()*(100000-10000)+10000))
    // wait between 10 and 100 s
       page++;
   next();
    console.timeEnd("Slept for")
}

main()

});
},
function (err) {
  // All things are done!
});