Truextacy
Truextacy

Reputation: 562

PhantomJS to create overlayed thumbnail images

I am taking a screenshot of a web page using the zoomFactor, and clipRect, I have it rendering at the correct size. I am stuck on how to put a local image on top of it so that it prints as a single image.

page.open(link, function(status) {
    page.viewportSize = { width: 188, height: 195 };
        var clipRect = page.evaluate(function() {
            return document.querySelector("body").getBoundingClientRect();
        });
        page.clipRect = {
            top: 0,
            left: clipRect.left,
            width: 188,
            height: 195
        };
        page.zoomFactor = 0.20;
        page.render(sku + '_Thumb.jpg', { format: 'jpg', quality: '100' });
        console.log("Thumb Complete");
});

I tried injecting the local image into the DOM but had no luck, I thought I could maybe use ImageMagick CLI, but could not get it to run.

Upvotes: 4

Views: 411

Answers (1)

Vaviloff
Vaviloff

Reputation: 16836

I tried injecting the local image into the DOM but had no luck

Imagine you could edit remote site html content - how could you possibly link an image to a file that's on another server and is not served? Of course that won't work because if you inject an image into a remote page's DOM, the image has to be accessible via http.

So let's try that first.

page.viewportSize = { width: 188, height: 195 };
page.open(link, function(status) {

    page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', function() {

        // Inject remote image        
        page.evaluate(function(){

            $("body").append("<div style='position: absolute; top:0; left: 0;z-index:9999'><img src='https://images.unsplash.com/photo-1461409971633-aa0e46732112?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=640&fit=max&s=bb401d13a08d6459b80bc63a0905a091'></div>");

        });

    });

    // Let's make sure the remote image has time to load
    setTimeout(function(){

        var clipRect = page.evaluate(function() {
            return document.querySelector("body").getBoundingClientRect();
        });
        page.clipRect = {
            top: 0,
            left: clipRect.left,
            width: 188,
            height: 195
        };
        page.zoomFactor = 0.20;
        page.render('thumb.jpg', { format: 'jpg', quality: '100' });
        console.log("Thumb Complete");
        phantom.exit();

    }, 3000);
});

The original thumb produced by your script looks this (I operated on cnn.com):

original image

A thumb with injected remote image from Unsplash looks like this:

remote image injected

But having to make a local image available externally is not too convenient - what if you don't have an http server on the working machine or what if you work on a local computer behind a NAT?

Luckily there's a simple solution in the form a PhantomJS built-in server:

var server = require('webserver').create();
var fs = require("fs");
var image = fs.open("img.jpg", "rb");
var data = image.read();

var listening = server.listen(3000, function (request, response) {
    console.log("GOT HTTP REQUEST");

    response.statusCode = 200;
    response.headers = {"Cache": "no-cache", "Content-Type": "image/jpeg"};
    response.setEncoding("binary");
    response.write(data);
    response.close();
});
if (!listening) {
    console.log("could not create web server listening on port " + port);
    phantom.exit();
}

Hats off to this answer for tip on setting the correct binary encoding.

With this code in the script we're starting a local server on port 3000 just to serve a given image (for watermarking purposes or some such, I suppose). After that we just have to inject an image from the local address:

page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', function() {

    page.evaluate(function(){

        $("body").append("<div style='position: absolute; top:0; left: 0;z-index:9999'><img src='http://127.0.0.1:3000/'></div>");
    });

});

Now that is a local image succesfully embedded in a thumbnail of a remote web page:

local image injected

Upvotes: 2

Related Questions