Skip to content
This repository has been archived by the owner on Mar 6, 2019. It is now read-only.

Replace xlink:href="file.jpg" by src="<data URI>" so raster image are embeded. #16

Open
hugolpz opened this issue Oct 30, 2014 · 3 comments

Comments

@hugolpz
Copy link
Contributor

hugolpz commented Oct 30, 2014

Currently, d3js generated SVG with linked images via :

svg.append("image")
  .attr("xlink:href", "file.jpg")
  .attr("width", width)
  .attr("height", height)
  .attr("class", "bg");

producing :

<image xlink:href="file.jpg" width="960" height="500" class="bg"></image>

, when dowloaded by v2.0, result into svg file with missing rasters.

The solution would be 1/ to convert file.jpg into a data URI string (var str) using JS. 2/ to replace

   <image xlink:href="file.jpg" ...

by

   <image href="data:image/png;base64,<dataURI>" ... 

3/ to repeat for each <image xlink:href= found.

The JS code to do 1. have been discussed here while 1 & 2 are in demo there (v/96/). The script successfully replace the href link by an href with valid and working data uri, so the image is really embedded within the svg. Then, crowbar naturally download both the SVG code and the (embedded) images :)

Note: as my stack appears to require server side base64 convertion and my d3js skills are limited, I will not push further in this way. But most of it is there, and it should be good to add to crowbar.

Note: I didn't tested if the data_uri type extension should really match the image's extension.

@hugolpz
Copy link
Contributor Author

hugolpz commented Nov 8, 2014

var converterEngine = function (input) { // fn BLOB => Binary => Base64 ?
    var uInt8Array = new Uint8Array(input),
        i = uInt8Array.length;
    var biStr = []; //new Array(i);
    while (i--) {
        biStr[i] = String.fromCharCode(uInt8Array[i]);
    }
    var base64 = window.btoa(biStr.join(''));
    console.log("2. base64 produced >>> " + base64); // print-check conversion result
    return base64;
};

var getImageBase64 = function (url, callback) {
    // 1. Loading file from url:
    var xhr = new XMLHttpRequest(url);
    xhr.open('GET', url, true); // url is the url of a PNG image.
    xhr.responseType = 'arraybuffer';
    xhr.callback = callback;
    xhr.onload = function (e) {
        if (this.status == 200) { // 2. When loaded, do:
            console.log("1:Loaded response >>> " + this.response); // print-check xhr response 
            var imgBase64 = converterEngine(this.response); // convert BLOB to base64
            this.callback(imgBase64); //execute callback function with data
        }
    };
    xhr.send();
};

//SVG DOM injection
getImageBase64('http://fiddle.jshell.net/img/logo.png', function (data) {
    d3.selectAll("image")
      .attr("href", "data:image/png;base64," + data); // replace link by data URI
})

@hugolpz
Copy link
Contributor Author

hugolpz commented Mar 6, 2015

Issue moved to d3js project.

@DDDgfx
Copy link

DDDgfx commented Jul 27, 2016

Is there any chance this will be incorporated into SVG crowbar? It could be very useful - particularly if your graphic is using some external SVG icons.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants