Accessible SVG

This page discusses the notion of translating SVG (e.g., charts, diagrams) into accessible text.


I use a lot of charts in my wiki pages. Typically, these are diagrams which show connectivity, data flow, etc. Although I'm not much of a graphic artist, I think the results are generally clear and informative. However, I'm concerned about their lack of accessibility to blind and visually impaired readers.

So, I've been speculating about ways to improve the situation. I don't tend to be very good at adding alt tags, largely because I'm not sure what can be usefully conveyed in a few words. However, I've been making an effort to provide textual descriptions, in order to provide at least a general impression of the content.

Most of the images are in Portable Network Graphics (PNG) format, taken as screenshots from tools such as OmniGraffle or SketchUp. Because PNG is a raster format, the diagram's geometry (let alone semantics) has been severely compromised. So, the images look fine, but their meaning is only available to the sighted.

Scalable Vector Graphics

Scalable Vector Graphics (SVG) is an Extensible Markup Language (XML) dialect. It has been a standard since 1999, but it has only recently started to become generally available (let alone commonplace) as an output format. However, adoption is increasing rapidly, driven in part by the use of D3.js and other JavaScript libraries.

OmniGraffle, for example, is quite willing to export diagrams in SVG format. It seems quite possible to parse and deconstruct such a diagram, generating a textual representation. Obviously, each diagram type and generating program will have its own idioms and not all of these will be possible to convert mechanically to text. However, the SVG metadata tells us who created the file, so it should be possible to employ the correct analysis logic for each translatable format.

Sample Diagram

Here is a sample diagram, representing the hardware connectivity in my (WIP) Robotic Explorer system. It contains about a dozen rectangles and a similar number of arrows, so the graphics could be rendered usefully in a tactile format. However, the textual information (e.g., "Raspberry Pi 2 Model B") is too large to fit comfortably into braille. Also, the geometry of arrows and rectangles might well be too close for legibility (let alone easy use) in a tactile format:

Textual Formats

There are a number of textual formats that might be appropriate for representing this sort of diagram, e.g.:

  • DOT - a graph description language

    DOT can be very detailed, including icon shapes,
    arrow directions and types, etc.

  • JSON - JavaScript Object Notation

    JSON is a bit verbose, because of all the quote marks.
    However, it can be read by every programming language.

  • Markdown - a simple markup language

    Markdown looks a bit like nicely formatted text.
    It can be used to generate documents, web pages, etc.

  • YAML - YAML Ain't Markup Language

    YAML is a human-readable language for data serialization.
    It uses semantic white space, which can be a problem.

Output Samples

I'm not convinced that any of these formats are going to work well in every situation.


Here is a simplified, hand-edited rendition in YAML. Note that it does not indicate anything about edge (e.g., connection) types or use (e.g., direction of control and data flow):

# Edges is a hash of lists of node names.
# Nodes is a hash of node labels.
# Both hashes are keyed by node names.

  Arduino:     [ Clock, MaxBotix, Servo ]
  MaxBotix:    [ RS_232 ]
  RX_Console:  [ RX_Server, WA_Server, Wi_Fi ]
  RX_Server:   [ WA_Server, Wi_Fi ]
  Servo:       [ Cameras, MaxBotix ]
  USB_Ports:   [ Cameras, iRobot, Raspberry, RS_232, Wi_Fi ]

  Arduino:     Arduino
  Cameras:     Cameras
  Clock:       Clock & Sensors
  iRobot:      iRobot Create 2
  MaxBotix:    MaxBotix 1360's
  Raspberry:   Raspberry Pi 2 Model B
  RS_232:      RS-232 Interfaces
  RX_Console:  RX Console
  RX_Server:   RX Server
  Servo:       Servo Motor(s)
  USB_Ports:   USB Ports and Hubs
  WA_Server:   WA Server
  Wi_Fi:       Wi-Fi Transceiver

Edges is an associative array with node names as keys and adjacency lists of node names as values. So, for example, it tells the reader that the MaxBotix node is connected to the RS_232 node.

Nodes is an associative array with node names as keys and node labels as values. So, for example, it tells the reader that the Raspberry node has the label "Raspberry Pi 2 Model B".


Here is a reasonably complete rendition, in slightly customized DOT:

// dot_1 lines denote analog, RS-232, and TTL
// dot_2 lines denote Wi-Fi
// dot_3 lines denote mechanical linkage
// solid lines denote USB (default)
// empty arrow tails denote response (default)
// solid arrow heads denote control  (default)

digraph {
  edge [ tail = empty ];

  Arduino      -> { Clock MaxBotix }            [ style = dot_1 ];
  Arduino      -> { Servo }                     [ style = dot_1  tail = none ];
  RS_232       -> { MaxBotix }                  [ style = dot_1 ];
  Raspberry    -> { USB_Ports };
  RX_Console   -> { RX_Server WA_Server Wi_Fi   [ style = dot_2 ];
  RX_Server    -> { WA_Server }                 [ style = dot_2 ];
  Servo        -> { Cameras MaxBotix }          [ style = dot_3 ];
  USB_Ports    -- { Arduino Cameras iRobot RS_232 Wi_Fi };
  Wi_Fi        -> { RX_Server }                 [ style = dot_2 ];

  Arduino      [ label = "Arduino" ];
  Cameras      [ label = "Cameras" ];
  Clock        [ label = "Clock & Sensors" ];
  iRobot       [ label = "iRobot Create 2" ];
  MaxBotix     [ label = "MaxBotix 1360's" ];
  Raspberry    [ label = "Raspberry Pi 2 Model B" ];
  RS_232       [ label = "RS-232 Interfaces" ];
  RX_Console   [ label = "RX Console" ];
  RX_Server    [ label = "RX Server" ];
  Servo        [ label = "Servo Motor(s)" ];
  USB_Ports    [ label = "USB Ports and Hubs" ];
  WA_Server    [ label = "WA Server" ];
  Wi_Fi        [ label = "Wi-Fi Transceiver" ];


Because SVG is an XML dialect, its structure is tightly constrained. Specifically, it's a serialized hierarchy with attributes at some levels. And, because the SVG tag set is pretty limited, there aren't that many variations to handle. So, we can use XSLT to extract the "interesting" data, then perform some geometric calculations and simple inferences.

The exported SVG from the example diagram mostly consists of g, line, rect, text, and tspan tags. Because we know the locations of all the items, we can (it says here :-) infer connectivity from proximity. For example, if a line starts at one icon and ends at another, we can conclude that it connects them. Arrowhead, icon, and line types can also be harvested as useful data.

So, the real questions are:

  • Would this sort of translation be worthwhile?

  • What output format(s) should be generated?

  • What chart styles (etc) can be analyzed?

This wiki page is maintained by Rich Morin, an independent consultant specializing in software design, development, and documentation. Please feel free to email comments, inquiries, suggestions, etc!

Topic revision: r91 - 10 Jan 2016, RichMorin
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding CFCL Wiki? Send feedback