Monday, 1 July 2013

Export an image from a d3.js page as a SVG or bitmap

The following post is a portion of the D3 Tips and Tricks book which is free to download. To use this post in context, consider it with the others in the blog or just download the the book as a pdf / epub or mobi .
---------------------------------------------------------- 

At some point you will want to take your lovingly crafted D3 graphical masterpiece and put it in a
(close your eyes if you're squeamish) Power Point presentation or Word document or export it for sharing in some other way.

There could be many reasons for wanting to do this and some may be more complicated than I will be willing to explore, but for the occasional conversion of images I have found what I regard as a fairly easy process.

Before we begin our exporting odyssey, let's cover a little bit of housekeeping and describe the difference between a vector graphic (in this case specifically Scalable Vector Graphics) and a bitmap. Please skip ahead if you're comfortable with the terms.


Bitmaps

 A bitmap (or raster) image is one that is composed of lots of discrete individual dots (let's call them pixels) which, when joined together (and zoomed out a bit) give the impression of an image.

If we use the example of the force layout example we developed, and look at a screen shot (and it's important to remember that this is a screen shot) of the image we see a picture that looks fairly benign.

 However, as we enlarge the image by doubling it's size (x 2) we begin to see some rough edges appear.


 And if we enlarge it by doubling again (x 4) , it starts to look decidedly rough.


 Doubling again (x 8), starts to show the pixels pretty clearly.


 Doubling again for the last time (x 16) and the pixels are plainly evident.


 Bitmaps can be saved in a wide range of formats depending on users requirements including compression, colour depth, transparency and a host of other attributes. Typically they can be identified by the file suffix .jpg, .png or .bmp (and there are an equally large number of other suffixes).

This will be the type of format that most people will be familiar with for images and their ubiquity with the advent of digital cameras almost makes it redundant to describe them.

However, there is another type of image and it is even more important to d3.js users.

Vector Graphics (Specifically SVG)

Scalable Vector Graphics (SVG) use a technique of drawing an image that relies more on a description of an image than the final representation that a user sees. Instead of arranging individual pixels on an image is created by describing the way the image is created.

For instance, drawing a line would be accomplished by defining two sets of coordinates and specifying a line of a particular width and colour be drawn between the points.

This might sound a little long winded, and it does create a sense of abstraction, but it is a far more powerful mechanism for drawing as there is no loss of detail with increasing scale. Changes to the image can be simply carried out by adjusting the coordinates, colour description, line width or curve diameter. If this all sounds a little familiar, you have *definitely* been paying attention, because this is the heart of the way that d3.js draws images in a browser. It uses a combination of coordinates, shapes and attributes to create vector images in a web page.

As a demonstration of the difference, here is the same original picture which I have saved as a SVG image.

 Enlarged by doubling it's size (x 2) everything looks smooth.


 If we enlarge it by doubling again (x 4) , it still looks good.


 Doubling again (x 8) and we can see that the text 'James' is actually composed of a fill colour and a border.


 Doubling again for the last time (x 16) everything still retains it's clear sharp edges.


Let's get exporting!

We'll use a three stage process for exporting our image (assuming the desired end result is a bitmap) and usefully, the first stage will result in us having a vector image as well!

The sequence will go as follows:

1. Copy the image from the web page and save it as a SVG file
2. Open the SVG image in a program designed to use vector images and edit it if required.
3. Export that image as a bitmap

Copying the image off the web page

Getting the image out of a web page is made easy by using 'SVG Crowbar'. This is a "*A Chrome-specific bookmarklet that extracts SVG nodes and accompanying styles from an HTML document and downloads them as an SVG file*". What that means is that once you drag the bookmarklet from the web page to your bookmarks (You need to be using Google Chrome, and I'm told that about 60% of the people who visit d3noob.org do) you're ready to go.

Now when you have a web page open that's displaying a D3 creation, all you need to do is click on the SVG Crowbar bookmark and you will be prompted for a location to save a svg image.

Really. It's that simple.

Open the SVG Image and Edit

Obviously now that you have a SVG image, you need to be able to do something with it. My preferred software for this is Inkscape.

 Inkscape is "*An Open Source vector graphics editor, with capabilities similar to Illustrator, CorelDraw, or Xara X, using the W3C standard Scalable Vector Graphics (SVG) file format*".

It really is an extremely capable drawing program and it is capable of a lot more than the job we're going to use it for, so you may find it has other uses that may be valuable.

Once installed, you can open the saved file directly into Inkscape.


While here you can edit the drawing to your hearts delight. I particularly recommend ungrouping the diagram and removing or adjusting individual elements if required.

Once you have finished editing, you are ready for the final step.

Saving as a bitmap

While still in Inkscape, go to the 'File', 'Export Bitmap...' menu.


This will open a dialog box where you can select an appropriate resolution and location for your bitmap and then press the export button.


There you go.

It is worth knowing that the default settings here will export the diagram with a transparent background (using *.png) which will fit in nicely with a wide range of graphical end uses.

The description above (and heaps of other stuff) is in the D3 Tips and Tricks book that can be downloaded for free (or donate if you really want to :-)).

9 comments:

  1. Thanks for this tutorial. The pictures made it easier to follow.

    I don't really like doing conversions. Changing images from one file type to another irritates me when it involves a long and arduous process. When it is fairly simple, it's not so bad.

    I wish that things were advanced enough for us to just create our work and wherever we wanted to use it or display it, the file would just convert to the required format automatically upon uploading.

    ReplyDelete
    Replies
    1. No problem. Like most things, they start our difficult and troublesome, but overtime there is a convergence in need and capability that allows a better product. We just have to wait :-)

      Delete
  2. Thanks for the nice tutorial it really helped. However, I wonder why you'd want to convert to bitmap in the end? In most situations keeping the vector format would be preferrable (wmf, emf or eps for use in Office applications for example). This way you can create very high quality graphics that are also suitable for print.

    ReplyDelete
    Replies
    1. Very true! From memory (so long ago now) I think I was focusing on the ubiquity of a bitmap rather than the superior quality of the vector original. You are quite right though. Whenever possible the vector version of the image will be the best to use.

      Delete
  3. Thanks for your nice tutorial! But if you look at the exported svg the markers aren't drawn correctly. I have the same problem and I guess it depends on the curved edges. Do you have a solution for this?

    ReplyDelete
    Replies
    1. Wow! well spotted. Initially I thought it might be something that I had done with the d3.js code, but I just tested it with the original graphic done by Mike Bostock and it has the same problem (and a couple of others). http://bl.ocks.org/mbostock/1153292.
      I am unaware of the reason for this but would be interested to know. Cheers.

      Delete
    2. I played a little bit with the parameters for the c curve tag. There is a parameter called "sweep" which is set to 1 in the examples. If you change it to 0 the marker will be drawn correctly. Actually I have no idea why this works but it does!

      Delete
  4. My svg is intercative and shows a specific view on mouseover.
    Any chance to start SVG Crowbar without moving the mouse e.g. key-shortcut
    AND receiving the specific view including the mouseover-effect?

    ReplyDelete
    Replies
    1. That's a good question and sorry for the delay in replying. I know exactly what you're wanting to do and it makes perfect sense. You would probably have to try to edit the crowbar code itself That's where I'd start) or have something inside your code that detected a keypress as a command to run the crowbar code (as you can see when you hover over the crowbar bookmark (`javascript:javascript: (function () { var e = document.createElement('script'); e.setAttribute('src', 'https://nytimes.github.io/svg-crowbar/svg-crowbar-2.js'); e.setAttribute('class', 'svg-crowbar'); document.body.appendChild(e); })();`))

      Delete