Load file into IMAGE object using Phantom.js

2020-07-27 20:48发布

问题:

I'm trying to load image and put its data into HTML Image element but without success.

var fs = require("fs");
var content = fs.read('logo.png');

After reading content of the file I have to convert it somehow to Image or just print it to canvas. I was trying to conver binary data to Base64 Data URL with the code I've found on Stack.

function base64encode(binary) {
  return btoa(unescape(encodeURIComponent(binary)));
}
var base64Data = 'data:image/png;base64,' +base64encode(content);
console.log(base64Data);

Returned Base64 is not valid Data URL. I was trying few more approaches but without success. Do you know the best (shortest) way to achieve that?

回答1:

This is a rather ridiculous workaround, but it works. Keep in mind that PhantomJS' (1.x ?) canvas is a bit broken. So the canvas.toDataURL function returns largely inflated encodings. The smallest that I found was ironically image/bmp.

function decodeImage(imagePath, type, callback) {
    var page = require('webpage').create();
    var htmlFile = imagePath+"_temp.html";
    fs.write(htmlFile, '<html><body><img src="'+imagePath+'"></body></html>');
    var possibleCallback = type;
    type = callback ? type : "image/bmp";
    callback = callback || possibleCallback;
    page.open(htmlFile, function(){
        page.evaluate(function(imagePath, type){
            var img = document.querySelector("img");
            // the following is copied from http://stackoverflow.com/a/934925
            var canvas = document.createElement("canvas");
            canvas.width = img.width;
            canvas.height = img.height;

            // Copy the image contents to the canvas
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0);

            // Get the data-URL formatted image
            // Firefox supports PNG and JPEG. You could check img.src to
            // guess the original format, but be aware the using "image/jpg"
            // will re-encode the image.
            window.dataURL = canvas.toDataURL(type);
        }, imagePath, type);
        fs.remove(htmlFile);
        var dataUrl = page.evaluate(function(){
            return window.dataURL;
        });
        page.close();
        callback(dataUrl, type);
    });
}

You can call it like this:

decodeImage('logo.png', 'image/png', function(imgB64Data, type){
    //console.log(imgB64Data);
    console.log(imgB64Data.length);
    phantom.exit();
});

or this

decodeImage('logo.png', function(imgB64Data, type){
    //console.log(imgB64Data);
    console.log(imgB64Data.length);
    phantom.exit();
});

I tried several things. I couldn't figure out the encoding of the file as returned by fs.read. I also tried to dynamically load the file into the about:blank DOM through file://-URLs, but that didn't work. I therefore opted to write a local html file to the disk and open it immediately.