1

Is there any technique to convert images that have already been downloaded – inline JPEG/GIF/etc. images that occur in a webpage – into Base64 data using client-side JavaScript?

I am not talking about how to transform an image into Base64 using other means (server-side, online tools, etc.).

These are the constraints for my particular use case:

  • The image is on screen now, right in the page, in front of person. It has already been downloaded in a data sense.
  • The conversion from raw image data has to be done client-side.
  • The images in question are from arbitrary domains. That is, they may or may not, be of same origin domain.
  • The user, if needed (if helpful to solution), can give additional permissions (for example, a FF toolbar install to help skirt cross-domain and other issues). That is, code can be given special endorsement on the client side if that helps solve the issue.

The end goal is to transform all images on the page (in the DOM) into Base64 data inside of JavaScript. Put another way, every image the user can see on the page has been converted into a JavaScript variable of some sort that contains the Base64 data.

So far I see no posts that stay inside of all the above constraints.

Rory O'Kane
  • 29,210
  • 11
  • 96
  • 131

2 Answers2

1

I think this is close to what you are looking for but the only problem is that it only works for locally hosted images and HTML5 only.

function toURL(image) {
    var canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    var context = canvas.getContext("2d");
    context.drawImage(image, 0, 0);
    var s = canvas.toDataURL();
    return s.substring(s.indexOf(","));
}

var test = document.getElementById("myImage");

console.log(toURL(test));

You can trick javascript into thinking an image is from your domain with the following code.

image.php

<?php
    $image = getAnImagePathAndTypeFromTheDatabaseByID($_GET["id"]); 
    //returns something like
    //array("path" => "http://www.anotherwebsite.com/image.png", "type" => "png")
    header("Content-type: image/$image[type]");
    echo file_get_contents($image["path"]);
?>

Then just navigate to image.php?id=1 for example.

Logan Murphy
  • 6,120
  • 3
  • 24
  • 42
  • Logan, I saw lots of posts like that but it's non-negotiable that the images can be served from anywhere. Any domain. I wonder if the javascript can sort of 'copy' all the images that are served from other domains, then, do the encoding on the copy. Then maybe the copy could be considered a non-cross-domain item (from JS security standpoint)? Thoughts? – user2639068 Jul 31 '13 at 18:02
  • I provided code that could potentially solve the security issue. Not really sure what server you are using but this is the only way I know of. – Logan Murphy Jul 31 '13 at 18:20
  • yeah, i thought about the 'proxying' approach. I think I need to look at capabilities offered inside the context of a Firefox browser plugin. So far i am thinking the onyl way to pull of is to have user install special plugin, then that pluggin can either capture all data that comes down for the page. Or, can somewhere get around the cross-domain issue because it's an approved (user consented to install) pluggin. The overall goal here is to capture *EXACTLY* what the user is seeing on the screen right now. To do that, new requests (for images, etc) spoil that goal. – user2639068 Jul 31 '13 at 18:26
0

For it to work in cross-domain client-side you need to call the image with the attribute crossorigin = "true", or, add a line in the Logan Murphy code:

function toURL(image) {
    image.setAttribute('crossOrigin', 'anonymous');
    var canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    var context = canvas.getContext("2d");
    context.drawImage(image, 0, 0);
    var s = canvas.toDataURL();
    return s.substring(s.indexOf(","));
}

I use this code:

// image-to-uri.js v1
// converts a URL of an image into a dataURI
function imageToURI(url, callback) {
    // Create an empty canvas and image elements
    let canvas = document.createElement('canvas');
    let img = document.createElement('img');
    img.onload = function () {
        let ctx = canvas.getContext('2d');
        // match size of image
        canvas.width = img.naturalWidth || img.width;
        canvas.height = img.naturalHeight || img.height;
        // Copy the image contents to the canvas
        ctx.drawImage(img, 0, 0);
        // Get the data-URI formatted image
        callback(null, canvas.toDataURL('image/png'));
    };
    img.ononerror = function () {
        callback(new Error('FailedToLoadImage'));
    };
    // canvas is not supported
    if (!canvas.getContext) {
        setTimeout(callback, 0, new Error('CanvasIsNotSupported'));
    } else {
        img.setAttribute('crossOrigin', 'anonymous');
        img.src = url;
    };
};

which is based on this https://github.com/HenrikJoreteg/image-to-data-uri.js/blob/master/image-to-data-uri.js

Luis Lobo
  • 489
  • 4
  • 7