How to Insert Images into Twine Without Linking

UPDATE: Twine 1.4 makes this process much easier. Go to the "Story" menu and select "Import Image". The techniques in this article are still valid too.

Twine has enjoyed some recent popularity and it is great to see the diverse and wonderful things people do. Inserting images into Twine is something that has become popular but having to transport the image as a file separate to the Twine output .html introduces some additional complications. I like the single output file nature of Twine.

Look at this Twine demo:
http://eturnerx.com/files/twinehowto/ImageDataURI.html (source .tws)
There is an image stored in the .html file itself using a Data URI (RFC 2397). That image is not a separate linked file. You can check it yourself, I'll wait.

Data URIs contains the data for the image in an encoded string that is embedded into the html <img> element. This works fine in most recent browsers (IE 8+) but is only suitable for smallish files. For IE8 the limit is not much bigger than 20 kilobytes but other browsers (including IE9) work just fine with much larger file sizes.

It is surprising how much image can fit within 20 kilobytes just by playing with filetype, compression settings and reducing pixel dimensions. Most flat line drawings in a few colours will generally compress well as PNG or GIF. Scanned line drawings should have the contrast boosted and/or posterized to flatten the colours in the image. Photographs or scanned images generally work better as JPEGs.

Once you have a small image file then it will need converting to a Data URL. I like to use:
They also have links to online tools that can further compress your image.

Here is the code that goes into your Twine passage:

<html><img width="11" height="14" src="data:image/gif;base64,R0lGOD
gcEIQA7" alt="File Icon"></html>

(data URI example from: http://dataurl.net/#about)

The <html>...</html> tells Twine to treat the code inside as raw HTML. The <img ...> is the HTML code for placing an image. The width="11" and height="14" code give the width and height of the image - you should change these to suit your image. The alt="..." code improves the accessibility of your file by giving a text alternative to your image. Most likely the code will work without a width, height or alt specified but it is considered good practise to include them if you can. The real magic happens inside src="...". That src is an abbreviation for "source" and normally that would link to an external file. Here we give it the data URI instead.

TIP: These data URIs can produce large walls of text that are annoying for you as an author to scroll past. What I suggest is to put all the image code into a different passage then use the <<display>> macro to.... ummm... yeah... display the image. This makes the image reusable anywhere in your story and keeps your text passages nice and tidy. Consider this abbreviated example... (:: Double colon is the passage title)

<<display "Image:Document Icon">>
This is my text and there is an image above.

::Image:Document Icon
<html><img ...></html>

Your Twine story can use both data URI images and normal "linked" images. And data URIs work just fine in CSS too; great for setting background patterns. (The thing in square brackets [] is a tag applied underneath the passage title).

::Stylesheet1 [stylesheet]
body {
  background-image:url(data:image/gif;base64,R0lGOD... etc );

You have the tool, go make something cool.


The Semantic Web is an Innumerable Corpus

I recently had the opportunity to present my PhD to people who are knowledgeable in related fields (particularly CYC) and have noticed that their questions usually come from me not properly explaining one property of the Semantic Web which I have called the "Innumerable Corpus".

The Innumerable Corpus is defined as: Innumerable triplets describing innumerable subjects expressed using innumerable ontologies. The word innumerable means a "practical infinity", that is, something that is not infinite but is uncountable. This means that there is no one source or one ontology that should be considered as authoritative. There is no guarantee that information of the same type (e.g. people) from the same source will use exactly the same ontologies. A general purpose semweb browser will adapt to RDF data from any source.

The inherent instability in triplets for a subject means that thinking is terms of looser "predicate patterns" is perhaps more useful than expecting conformance to ontologies.

Many Semweb projects scope the Innumerable Corpus property out. There are projects that use RDF as a data transmission language for data that is from controlled sources and in well defined ontologies. In that context a pragmatic approach is to hand produce the displays dependent on rdf:type. By ignoring the Innumerable Corpus property it is also possible to limit a project to a small subset of semweb data, place it locally for speed of access and perform computationally expensive processing over that data. Inferences can be pre-computing inferences before a user needs them.

All research projects have to scope things out for practical reasons but personally I find the Innumerable Corpus the property that most interests me about the semweb. The political argument is an important one; who controls how our knowledge is defined? Sure, authoritative information sources expressed in well known ontologies are important to our shared understanding but what about murky knowledge on the fringes? What about knowledge that is in dispute? What about knowledge that does not easily fit the orthodox ontologies? The decentralized possibilities of the semantic web really struck at the cyberpunk principles I've grown up with.

But there is also a technical reason too. Semweb browsers will eventually elaborate upon a subject by aggregating and inferring over RDF data from multiple sources. The greater the expansion then the greater probability that subjects of the same types will have less consistent predicate sets, particularly as owl:sameAs links are followed and rdf:type definitions expand. Data expansion The number of triplets per subject could be very high due to data expansion. Without filtering, grouping and ordering the displays of all those triplets will cause information overload.

The Innumerable Corpus means that each subject requires a custom produced display of data. This could be derived from how other similar (by rdf:type) subjects are displayed. These custom displays must be produced runtime.

Producing an authoritative display for an rdf:type is inherently fragile because it is difficult to account for missing predicates and additional predicates that do not conform to that display. Even the concept of an authoritative display assumes a single centrally ordained way of showing things. My preferred approach is to use personalization to let users negotiate with the semweb browser as to how they would prefer to see the data.

Plurality, instability and inconsistency are not special cases; The Innumerable Corpus is about accepting plurality, instability and inconsistency as normal and good.


Twine GameStory Recommendations I

Here are some Twine stories that demonstrate what skilled authors can do with Twine. These examples are selected to show some of the many story types or narrative structures that can be created with Twine. These are reviews that might contain minimal spoilers.

CYBERQUEEN by Porpentine
Transhuman. Surgical horror. Some good time-based visual text effects. The writing is very atmospheric and keeps shifting reality. When reality stablises I'm not sure you're happy with the result.
Minimum playtime: 15 mins

Stygia by Kitty Horrorshow
It's a grittier Monsters Inc for adults... hang on, it's a horror themed afterlife. Well written with a setting and backstory suited for a movie. Limited replayability but you won't mind.
Minimum playtime: 10mins

Cold Dead Fish by Chris Klimas
Chris is the creator of Twine. This story is rather linear with only a few choices that really matter. Much of Twine's capability is used to "chunk" the story into unfolding bites that allow for contemplation and re-reading time as the reader explores the parenthetical links. These asides are interesting to the setting, but would have choked the narrative if the story was strictly serial. The subject of the story is a gentleman and an enigmatic lady.
Minimum playtime: 15mins

Fake Nerd Girl Detector by Zoe Quinn
Twine used instead of a flow-chart. This technique allows more space to make an argument and allows the author to keep the ending a surprise.
Minimum playtime: 5mins - some replayability in exploring the various endings

Choose Your Own Anna Anthropy Interview by Cara Ellison
This one is a hypertext arrangement of an interview with Anna Anthropy. If you're familiar with Anna's work you can skip most of the "asides". If you're interested in Anna's take on something in particular then you can read that. The format enables more indepth and richly annotated interviews than an equivalent serial article could.
Minimum playtime: 5mins - though you could easily spend more time if the subject matter interests you

Time Quest by Dungeon Smash
This choose your own adventure is sophomoronically funny. You get to trip around time and even postulate on the nature of time itself. Twine is very easily suited to make these kinds of stories.
Minimum playtime: 10mins

That's it for this round-up. Until next time (undetermined), maybe you can check out my Twine conversions of some old text games.