Collaborative Imaging (Whiteboarding via Streaming XPM)

Ryan Eatmon

The Jabber.org Project

reatmon@jabber.org

Thomas Muldowney

The Jabber.org Project

temas@jabber.org

Jeremie Miller

The Jabber.org Project

jeremie@jabber.org

01/25/2001


Introduction

Jabber is a dynamic platform, connecting people and applications through conversations. There is often a need to express information that is not well suited to simple text, but can be seen visually. This is the first step in adding an exciting new aspect to a real-time textual conversation.

This extension is not the end-all of imaging/whiteboarding and Jabber, but designed to suite the needs of most people when drawing simple graphics to get an idea across in addition to a normal chat. It is also designed to be a companion with the Jabber architecture, able to be deployed instantly and have very low implementation requirements for support in any client.

The format is based on a variation of XPM (http://www-sop.inria.fr/koala/lehors/xpm.html). The variations are all made so that XPM is better for streaming dynamically in XML, and placed in the jabber:x:sxpm namespace (Streaming XPM). It can be an extension to any message, groupchat, attachment to a message, or built dynamically in a one-on-one chat.


Drawing and Displaying


    <x xmlns='jabber:x:sxpm'>
      <board height='400' width='400/>
      <map char='#"/>
      <map char=' ' c='None'/>
      <map char='a' c='#ffffff'/>
      <map char='b' c='#000000'/>
      <map char='c' c='#ff0000'/>
      ...
      <data> compressed sxpm stream </data>
    </x>

The above jabber:x:sxpm block defines everything that is variable in an xpm,
with the number of colors begin fixed at 17 (transparent and 16 colors).
The compression on an sxpm is very very simple.  If you know anything about
XPM then you know that it basically defines the size - <board/>,
colors - <map/>, and the image as a big grid where it defines every pixel
and the color that it has based on the color to character mapping.  A <map/>
entry can be sent at anytime and should be updated in both the image and
the GUI color selection tool.

We don't want to have to send a 600x600 image everytime.  Using the fact that
when you draw something on the board you will not be using more than three of
the colors (transparent, the draw color, and possibly a fill color) then we
can easily compress the grid.  Consider the following 10x10 xpm:

. = None
a = yellow
b = black

"....aa....",
"..aaaaaa..",  Standard smiley face.
".aaaaaaaa.",
".aabaabaa.",
"aaabaabaaa",
"aaaaaaaaaa",
".aabaabaa.",
".aaabbaaa.",
"..aaaaaa..",
"....aa...."

in stream mode (w is the width, break every w characters for a new row):

<data width='10'>....aa......aaaaaa...aaaaaaaa..aabaabaa.aaabaabaaaaaaaaaaaaa.aabaabaa..aaabbaaa...aaaaaa......aa....</data>

And now compressed, replacing the characters with the number of times they repeated followed by that single character:

<data width='10'>4.2a6.6a3.8a2.2ab2ab2a.3ab2ab13a.2ab2ab2a2.3a2b3a3.6a6.2a4.</data>

An easy uncompression, and nothing is lost.  But I doubt that anyone will be 
able to send as complicated image as a smiley face.  Either most of the time it
will be lines, or boxes, or some free hand drawing.

Here's a box (newlines inserted for illustration only!):

<data width='10'>
aaaaaaaaaa
a........a
a........a
a........a
a........a
a........a
a........a
a........a
a........a
aaaaaaaaaa
</data>

and the same compressed:

<data width='10'>11a8.2a8.2a8.2a8.2a8.2a8.2a8.2a8.11a</data>


To send new data to the whiteboard, just send the <data/> tag with the xpm
data you want to add, and the x,y offset and width of the block as attributes, if needed.
It's that simple.  In almost every case, it is desireable to not send the update data until
the user action has been completed, when the line has been drawn or shape tool has been placed/sized
and the entire data section can be compressed and sent.

Erasing Pixels


  Part of the colormap includes an erase character.

  <map char='#'/>

When you send this inside the <data/> tag the result will be to remove the pixels at those points and 
make it transparent in the future.

Note:  This entry in the colormap is not to be used when writing out to a
file by the client.  Erase is not a valid XPM color map entry, but we had
to define something for SXPM to show that you wanted to erase a pixel
so that the background image/color would appear.  You cannot simply send a 
transparent character, as it would not affect the underlying existing drawn images.

Cursor Updates

  One of the nice things about the whiteboard is that you can tell when people
are drawing something on the board through the message system.  When you start
drawing something on the whiteboard, you should send out a message including this:

    <x xmlns='jabber:x:sxpm'>
      <cursor x='20' y='20'/>
    </x>

Then the recipient(s) would display a little cursor with your nick next to it on the
board to show that you are drawing something.  When you send the drawn item,
that message signals that you are done drawing.