Authors: Wout Dillen and Joshua Schäuble
First published: 26 June 2019
Last update: 6 August 2019
(first published version) DOI: http://dx.doi.org/10.17613/6n9b-2n48
This tutorial was developed by Wout Dillen and Joshua Schäuble at the Centre for Manuscript Genetics (CMG), as part of the IIIF courses of the University of Antwerp‘s Summer School on Digital Humanities. This is a one-week summer school organized by the Antwerp Centre for Digital humanities and literary Criticism (ACDC).
The course was first taught in Antwerp in 2018 (3-7 September), and an adapted version was taught again in 2019 (1-5 July). In the course, students learn how to set up a IIIF-compatible image server (iipimage) on a local network of Raspberry Pi computers, to ultimately re-use and manipulate each other’s images using the IIIF protocol.
1. Double-Checking Your Raspberry Pi’s Setup
Developed as a classroom instrument, this tutorial assumes that you are a student, and that you have access to a Raspberry Pi (RPi) with the Raspbian Operating System pre-installed on it. While they were preparing your RPi for this course, your tutors will also have checked that they are set up correctly for the course. Still, it is important that we double-check some of their settings, because they are crucial for the rest of this course.
1.1 Make sure that SSH is enabled on your RPi
On your RPi, select the raspberry icon in the top left corner, and navigate to: Preferences > Raspberry Pi Configuration
. Here, select the tab Interfaces
and ensure, that SSH is Enabled
.
1.2 Ensure that the keyboard layout is set correctly
Up until the moment when we are able to SSH into our RPis, we will need to use the keyboard to control them. Go to Preferences/Mouse and Keyboard Settings
, select the tab Keyboard
and there the button Keyboard Layout
. Select the layout of the keyboard you are using, in our case (at the University of Antwerp) this would be Belgium/Belgian
.
1.3 Ensure that the system language is set to English
We want all RPis to be operated in English. Go to Preferences > Raspberry Pi Configuration
again, this time select the tab Localisation
. Click on Set Locale
and make sure the Language
is set to English
and the Character Set
is UTF-8
.
1.4 Set the System Password
Although we are in a closed network for this course and do not expect any hacking attempts, it is always good practice to change your RPi’s password. Especially when SSH is enabled, changing the default password (raspberry
) will prevent others from accessing and controlling your computer without your knowledge. Go to Preferences > Raspberry Pi Configuration
again, this time select the tab System
and set the password to your own (unless your tutor provides you with one).
1.5 Reboot your RPi
Go to your terminal, and enter the following command:
sudo reboot now
2. Connect your RPi to the Internet
In the original setup for this tutorial, all RPis are connected to one another (and together to a local router, called IIIFarm
) via ethernet
. But we need them to be connected to the actual Internet too – to download packages etc. For this connection we will use the WiFi. The problem here is, that your RPi will prioritise Ethernet over WiFi for its internet connection. This is not surprising, because ethernet connections are typically much faster and more reliable than WiFi connections. But so in our case, we’ll need to turn this around, so the RPi will always use WiFi for internet connections first, rather than trying to connect through our (local, unconnected) ethernet network.
2.1 Connect your RPi to the WiFi
WiFi network names and passwords will differ depending on where you are following this course, so listen to your tutors, and use the login information they provide.
2.2 Prioritise WiFi for web requests using nano
So now we want to make sure our RPi uses the WiFi to connect to the internet, rather than its ethernet connection. To change this, we will need to make changes in a configuration file. Open a terminal, and enter:
sudo nano /etc/dhcpcd.conf
This will tell the RPi to use the programme nano
, a shell text editor, to open a file located in the path /etc/dhcpcd.conf
.
2.3 Assign metric values to your ports
Use the arrow-down
key to move to the end of the configuration file. There, add the following lines:
interface wlan0 metric 202 interface eth0 metric 303
Hit Ctrl+o
to save the file and confirm with enter
. These lines assign metric values to your WiFi and your ethernet ports. The lower the value, the higher its priority. So, since 202
is lower than 303
, wlan0
(your WiFi port) will be rated higher than eth0
(your ethernet port) and our system will send web requests via wlan0
instead. Finally, hit Ctrl+x
to leave nano
.
2.4. Reboot your RPi
To allow these changes to take effect, you will now have to reboot your RPi again. We will do this using the terminal:
sudo reboot now
2.5 Connect the RPi to the WiFi network again
Open the browser. You should be directed to the university’s login page now. This means that assigning the metric values has worked! Each group has received credentials for an account on the guest network. Log in using these access data. Once you are logged in, visit any website to make sure your internet is connected.
2.6. Double-check the metric values
Open a terminal and enter the following command:
route
This command will show you your routing table: a list of all the system’s routing destinations (in the form of IP addresses), that tell the system where to send which data packages. Here you can double-check that the metric value of the wlan0
interface is now lower than that of the eth0
interface.
2.7 Note down your IP Address
As mentioned, we will need the IP address that our router has assigned to our RPi to SSH into the RPi via our laptops. We can find the IP address we need by running the following command:
ifconfig
This lists all your network settings. In the list, find the entry that starts with eth0
(typically the first one), and note down the first IP address that you see, the one that directly follows the word inet
.
2.8. No more peeking!
Now that we have the IP addresses of our RPis, we can finally access them via SSH, using our laptops. That means we will no longer need to look at its desktop. Turn off the monitor that is connected to your RPi.
3. SSH into your RPi
We will now start to control our RPi from a different system (your laptop) using the command line. Since the rest of this tutorial assumes that you know some basic command line commands (and will even ask to write your own commands here and there), this is the point where your tutors will offer you a brief introduction to working in a Linux terminal. At a later point in time, a similar tutorial for training command line basics will be provided and linked here on this website.
3.1 SSH Connect
On your laptop (the one that is connected to the IIIFarm
WiFi) open a Command Line Interface. Here, enter:
ssh pi@your.ip.address
and confirm with enter
.
On your first login to a new resource you will get a security warning. Confirm by typing yes
. You will be prompted for your RPi’s password. Type in the password that you’ve set up for your RPi, and confirm with enter
.
3.2 Creating Files and Directories
At this point, your tutors should have either already put a folder on your RPi’s Desktop
, or prepared a USB-stick that passes around while you complete this exercise. In the second case, when you get the USB, you can turn your RPi’s monitor on, plug the USB into the RPi, and copy the directory with your RPi’s name onto your Desktop
. (The whole directory, not just the files that are inside). When this is done, turn the monitor off again, and continue with the following exercise.
3.3 Command Line Exercise
- Navigate to the
Desktop
- Create a new directory called
html
- Navigate into that directory
- Create a new document in that folder, called
index.html
- Also create a new directory in that folder, called
images
- Verify that your
html
directory now containes anindex.html
file and animages
subdirectory
To continue beyond this point, you will need the folder provided by your tutors to be copied to your Desktop
. So wait for the USB if necessary.
- Check your Present Working Directory
- Navigate back to the
Desktop
- Verify that the Desktop has two directories:
html
and one withyour_RPi_name
- Navigate into the directory with
your_RPi_name
- List the contents of this directory
As this list will show, the directory contains 2 .png
images, and one .jpg
image. The .png
images are high-resolution facsimile images of random pages of the first draft of Mary Shelley’s Frankenstein. For this tutorial, they are your institution’s pieces of the Monster we are creating.
- Copy these contents into the following directory:
/home/pi/Desktop/html/images
- Navigate into that directory, and verify that it indeed contains these three images
- Rename the
.png
images usingmv
. Their new names should beimage1.png
and.image2.png
3.4 Create a HTML document in nano
First, navigate back to the html
directory on your Desktop
. Now open the index.html
file with nano
:
nano index.html
Now you can use the command line text editor nano
to write the following code into the file:
<html> <head> <meta charset="utf-8" /> <title>My Institution's Page</title> </head> <body> <h1>Welcome to [your_RPi_name]</h1> <p>See our beautiful pieces of the Monster:</p> <img src="images/frankenstein.jpg" style="width:300px;" /> </body> </html>
3.5 Creating a HTML Document in nano
The code we just wrote in nano
is written in a language that your browser can read: html
. This means that if you open it in your browser, it will display the document as if it were an online web-page.
In the code, the following line will load an image from your html/images
directory, and resize it to a width
of 300px
in your browser:
<img src="images/frankenstein.jpg" style="width:300px;" />
When you’re satisfied that the file is copied correctly into your command line through nano
, save the file with Ctrl+o
, and quit nano
with Ctrl+x
.
4. Set up a Web Server on Your RPi
Now that everything’s set up and we can connect to the internet, we’ll start with setting up a web server on your RPi. This will allow you to serve your content (the offline web page you’ve just built) with other users on your network (here, the IIIFarm) on an actual website.
4.1 Update APT Package List
Before we start downloading and installing packages on our RPi, it’s good practice to first update apt-get
‘s package list – the list of links to the public repositories that our operating system’s app store uses to know where the most up-to-date versions its software packages are hosted. To do that, enter:
sudo apt-get update
4.2 Install Apache 2 (with fcgid
)
Now it’s time to download our software! The web server that we’re going to use is the commonly used Apache2
webserver. In addition, we also need to install one of Apache2
‘s modules (a kind of sub-software-package) called fcgid
.
With apt-get install
, you can line up a series of software packages to install them all with a single command. So go ahead and run:
sudo apt-get install apache2 libapache2-mod-fcgid
On running this command, apt-get
will inform you if the software has any dependencies (other software that needs to be downloaded), and tells you how much disk space these downloads will take up on your RPi. You’ll have to confirm with y
, and wait until your packages are downloaded and installed. As we’re all on the same network and the RPi’s aren’t very fast, this may take a while.
4.3 Start Web Server
Once the software is downloaded, we can start it up on the RPi. Run:
systemctl start apache2
Here, you will be asked which user you want to use to run the Apache2 service. Choose 1
(pi) and confirm with enter
. The command line will then prompt you for a password, so type in your RPi’s password and confirm by hitting enter
again.
The command we’ve just run – systemctl
– is a utility to manage (start, stop, restart) services on your RPi (like the Apache2
service we’ve just installed). We’ll be using it a lot in this tutorial, so make sure you remember your RPi password!
4.4. Test Apache
Before we do anything else, we’d like to make sure that our Apache webserver is actually running. On your computer, open a browser, enter your RPi’s IP Address into the browser’s address bar, and confirm with enter
. You should now see the Apache2 Debian Default Page. On the top of that page, in a red banner, you’ll read “It works!”
4.5. Viewing Your Website
By default only contents that are in the folder /var/www/html/
are accessible. Although this folder could be changed (e.g. to your Desktop
, or a folder in your Documents
) doing so is not considered good practice. Instead of relocating the folder Apache points to, we move our content (those files we want to access via the browser) to the default folder.
Copy the html
folder from the Desktop
to /var/www
:
sudo cp -r /home/pi/Desktop/html/ /var/www/
Now you can enter your IP address into the browser of your laptop. If everything went well, you can load the website from your RPi (which now functions as your server) on your laptop (which funtions as the client).
5. Install the IIPImage Server on Your RPi
In the previous step, we installed Apache – a web server that allows each of us to host web pages such as our own page in html
) and share them within our network. As we’ve seen, we can easily hard-code images into such html
web pages (by providing a link to the image in the @src
attribute of an <img>
tag) – but that is not enough for our purposes. Instead, we need to install a dedicated image server alongside our web server, to process the images on the fly. For that, we will install a IIIF-compliant image server called IIPImage.
5.1 Install the IIPImage-Server
Install the package iipimage-server
by entering the following command:
sudo apt-get install iipimage-server
You will have to download some dependencies (between 50-100MB), confirm with y
and wait until the image server is installed.
5.2 Change the image server’s data directory
By default, the data directory of the image server is under /usr/lib/iipimage-server/
. We want to change this to /var/www/iipimage-server/
. To do so, we have to copy the folder over to /var/www/
and tell the image server where the data directory has moved. Copy the iipimage-server
directory from /usr/lib/
to /var/www
:
sudo cp -r /usr/lib/iipimage-server/ /var/www/iipimage-server/
To use the image server in our website, we need to run it as an Apache module. Such modules are configured in the directory /etc/apache2/mods-available/
. Change to this directory. Once you are there, we need to open the image server’s config file with nano
so we can make some changes (don’t forget the sudo
!). the config file is called iipsrv.conf
.
sudo nano /etc/apache2/mods-available/iipsrv.conf
In this file change the following line:
ScriptAlias /iipsrv/ "/usr/lib/iipimage-server/"
to:
ScriptAlias /iipsrv/ "/var/www/iipimage-server/"
Save the file with Ctrl+o
, and hit enter
to confirm) and close nano (Ctrl+x
). Now once we enable the module, apache knows where we put the image server’s data directory, and the two servers can work together.
5.3 Enable the necessary Apache modules for the image server
First, we want to double check that the fcgid
module is enabled. Since we installed it earlier, this should already have happened by default. Enter:
sudo a2enmod fcgid
You should now see a message that confirms that fcgid
was already enabled. Next, we need enable the headers
module. Enter:
sudo a2enmod headers
If one of these two modules was not enabled before, you will have to restart apache now. In that case, enter:
systemctl restart apache2
Finally, we’ll want to check if our image server’s module (iipsrv
) is enabled too. Enter:
sudo a2enmod iipsrv
Now that all three modules are definitely enabled, we need to restart Apache again. Enter:
systemctl restart apache2
5.4. Enable CORS
In the image servers configuration file we have to enable “cross origin resource sharing” (CORS). It is important to enable this setting to make sure the image server is IIIF-compliant, because it allows others to embed your images into their website. To enable CORS, open the apache configuration file with nano
.
sudo nano /etc/apache2/apache2.conf
Move down (arrow-down key ↓
) to the end of the file and add the following line:
Header set Access-Control-Allow-Origin *
Make sure there are no spelling mistakes in this line! Save the file (Ctrl+o
, enter
) and leave nano (Ctrl+x
).
And, again, Apache needs to be restarted:
systemctl restart apache2
5.5 Check if your IIPImage Server is running
Finally, we’ll want to make sure that everything is working correctly, and that the image server we just configured is actually running. In your laptop’s browser go to:
your.ip.address/iipsrv/iipsrv.fcgi
If the IIPImage Server start screen appears, your server should run correctly. Well done!
6. Making Pyramid TIFFs for IIPImage
IIPImage needs a specific type of files to work its image serving magic. These are pyramid TIFFs – which are basically layered documents that contain multiple, mapped versions of the same image in different resolutions. This allows the image server to optimise its zoom function, as it switches to higher resolution images as the user zooms deeper and deeper into the document.
6.1. Install Image Processor: VIPS
To convert our high-resolution images into Pyramid TIFFs, we will first need to install another package on our RPi – this time we need an image processor. There are a couple of different options available for this, but we’ll use the software package VIPS. Use apt-get
to install the package libvips-tools
:
sudo apt-get install libvips-tools
6.2. Find Your Images
Change to the folder /var/www/html/images/
. At an earlier stage, we stored two Frankenstein facsimile images in this folder: image1.png
and image2.png
. Make sure they are still there using ls
.
6.3. Transform Your Images
To transform these .png
images into (tiled pyramid) .tif
images, run the following command:
sudo vips im_vips2tiff image1.png image1.tif:deflate,tile:256x256,pyramid
Once you’ve hit enter
, wait until the processing is done. This can take several minutes, because Pyramid TIFFs are huge files.
Once the first image is processed, move on to the second image. Afterwards make sure, both .tif
files (image1.tif
and image2.tif
) are in the folder, alongside to the .png
files – which should still be there too.
6.4. Copy the Pyramid TIFFs to the Image Server’s Data Directory
Just like Apache stores the accessible documents in a specific data directory (/var/www/html
), our IIPImage server also has a directory where our images need to be stored. Earlier, we’ve set this directory to /var/www/iipimage-server/
. In order to make our images accessible via the image server module (and not only via apache) we have to copy (cp
) them into this folder.
sudo cp image*.tif ../../iipimage-server/.
Note: ../../
only works as long as you are in the /var/www/html/images/
folder. It would not lead to the correct target from any other pwd
. An alternative would be to use an absolute path.
7. IIIF Parameters
Now that we have set up IIPImage, you can access all of the images in your var/www/iipimage-server
directory in any browser or IIIF-compliant image viewer – such as Mirador, Universal Viewer, OpenSeadragon, or Leaflet-IIIF.
7.1. Accessing Images in the Browser
When you call an image via an IIPImage server URL
, the image server will show you this image according to some parameters that you have set in the URL
. Let’s have a look at how this works.
Open your browser (on the laptop!) and go to:
your.ip.address/iipsrv/iipsrv.fcgi?IIIF=image1.tif/full/400,/0/default.jpg
Now, open another tab in your browser and go to:
your.ip.address/iipsrv/iipsrv.fcgi?IIIF=image1.tif/full/800,/90/grey.jpg
Both URL
s show you the same image, but not in the same way. Compare the URL
s above and try to find out how it influenced the server’s presentation of that image in your browser.
7.2 Experiment with the IIIF Image API
The IIIF consortium provides a detailed documentation of the IIIF Image API’s parameters here. Have a look at this documentation, and play with different settings for your images by manipulating the URL
in the following exercise:
Reading up on the IIIF parameters, find out how to:
- Rotate your image by `180` degrees
- Retrieve **only a section** of an image
- Retrieve an image with a width of `5000px` and a proportionally scaled height
- Retrieve an image with a `width` of `100px` and a `height` of `300px`
- Display your image in `greyscale`
7.3. Get the `info.json` from your image server
All the information you need to build tools that show your images work on the basis of a info.json
file, which is generated by the server for every image. To view this file for your own collection, enter the following URL
into your browser:
your.ip.address/iipsrv/iipsrv.fcgi?IIIF=image1.tif
When no further IIIF URL
variables are specified, the IIPImage server will forward you to the info.json
file.
7.4 Accessing Each Other’s Images
So, each of us now has a fully functioning RPi with a web server and an image server that provide access to a couple of tiled pyramid TIFF images that we have learned to access and manipulate] with the IIIF URL parameters. And since all of our RPis are connected on the same network, we can use the same technology that allows us to view and manipulate the images on our own RPi in the browser of our own laptops allow us to do the same with each other’s images too.
Ask your neigbour to give you the information you need to build IIIF compliant URLs for their images. Then try to view and manipulate their images using the IIIF parameters
We will need URL
s like these going forward. So save some of these URLS on your laptop somewhere (like a .txt
or .doc
file), so you will be able to copy and paste them.
8. Reusing IIIF Images
Now that we have a series of links to images (our own as well as our neighbours’), we can embed their URL
s into our html
page to incorporate them in our websites.
8.1. Include Images in your html
Web Page.
Open the index.html
file we created earlier with nano
:
sudo nano /var/www/html/index.html
In this file, add the following two lines after the frankenstein.jpg
image:
<br/><img src="your.ip.address/iipsrv/iipsrv.fcgi?IIIF=image1.tif/full/400,/0/default.jpg" /> <br/><img src="your.neighbours.ip.address/iipsrv/iipsrv.fcgi?IIIF=image1.tif/full/400,/0/default.jpg" />
Copy these links carefully – although you will of course have to to change the IP addresses in these URL
s with the ones you came up with earlier.
Save the index.html
file (hit Ctrl+o
, then enter
) and exit nano
(hit Ctrl+x
). Then enter your RPi’s IP address in your browser (on the laptop!) again, and look at the effect your changes had on your website.
8.2 IIIF Manifests
So wouldn’t it be nice if we could also embed additional metadata about each image (or even an entire collection of images) directly from the server of the image provider? In a computer readable, standardized format? This would allow us to give credit where credit is due. And if the original hosts have enriched their images in any way (with dates, transcriptions, annotations, etc.), we might want to reference those, or reuse them in our website in some way too. IIIF provides a solution for this: IIIF Manifests. This is a container file (in the JSON
format), that contains metadata about an image collection as well as the IIIF compliant URL
s to the contained images. For now, we will only look at a simple example, in detail we will learn about manifests and IIIF compliant image annotation later.
8.3 Download A Sample Manifest
Here again, you will need to follow your tutors’ instructions to download a sample manifest for your collection – or download the one we used in class here.
8.4. Adapt the Manifest to Your Needs
At this point, you don’t have to understand the file you’re reading in nano
. Instead, just replace all instances of the string MY_IP_ADDRESS
with your actual IP Address.
Warning: If you make a mistake here, your manifest will not work later. There should be 10 instances for you to replace. Go through slowly line by line.
When you are done double-checking, go through the file again, looking for the line "label": "Team [PI Name]",
(line 9). Now, replace the string [PI NAME]
by the name of your Raspberry Pi.]
Once you are done, save (hitting Ctrl+o
, then enter
) and exit nano (Ctrl+x
).
8.5 Double Check that the File Loads
Check in the browser if your manifest is publically accessible. Open the laptop browser and enter:
your.ip.address/frankenstein.json
The manifest JSON
file should load in your browser.
9. Frankenstein
This is the point where we’ll really start taking advantage of the interoperability features IIIF has to offer, as we’ll aggregate, mix and match each other’s images. You’ll effectively be assembling your own “Monster” out of the Frankenstein manuscript images you and your peers are hosting. To do so, we’ll be working more with IIIF Manifests, so depending on your (and your peers’) technical background, this would be a good point for your tutors to introduce the basics of the JSON
data format.
9.1 Loading Manifests in Mirador
On their laptop, that is also connected to our IIIFarm, your tutors will also has a version of Apache running, that should make data from his laptop accessible to you. In his web-shared folder he installed a version of Mirador, a IIIF compliant image viewer with a couple of nice features such as deep zooming. But one of this viewers coolest features is, that you can load IIIF manifests dynamically if you have the URL
of the manifest. Luckily, each team knows the URL
of their manifest, you have just entered it in your browser. Lets load them all – one by one – in Mirador.
Follow your tutor’s instructions to load their Mirador instance on your own IIIFarm-connected laptop and add your own manifest. Play with the viewer. Make yourself familiar with the functionality it provides. Then load some of the manifests of other teams into the viewer too.
9.2 Adding Metdata to the Manifest
At this point, your IIIF manifests do not yet provide a lot of metadata. Let’s first experiment by improving what is there already. Open your manifest (frankenstein.json
) with nano
and edit the existing JSON
data.
Warning: Try not to change the file’s structure and don’t change the id
s.
What you enter here does not have to make sense for now, but whenever you change something, save the file (hit CTRL+o
, then enter
– but don’t exit nano!) and reload your manifest in the Mirador viewer.
Try to see how mirador views the JSON
data you changed. Which change is visualized where?
On the initial image folder we gave to you (/home/pi/Desktop/yourPisName/images/
), your .png
imagess still had individual names. Their name (a number) was the position of the image in the sequence of the entire notebook. Try to get this information into your canvas information. For example: if your files were called 023.png
and 024.png
, make sure that your canvas for image1.tif
reads “Page 23”
, and image2.tif
would correspond to “Page 24”
, etc.]
9.3. Including Other Teams’ Manifests
- Study the canvas area of your manifest. Open another team’s manifest and look at their
JSON
. Find their canvases. - Figure out if their two images should come before or after your own images.
- Try to copy their canvases from their manifest into your manifest: find the right position to add their canvases (either before or after your own canvases) copy them there.
- Load your manifest again in mirador. Did it work? If not… debug!
- Add the canvases of at least two other teams at the correct position in the sequence.
9.4 Finding the Missing Information Online
Maybe you would be happy to have more real metadata in your manifest. Luckily, the Shelley Godwin Archive recently published the entire notebook in IIIF. Here is the corresponding blog post:
https://blogs.bodleian.ox.ac.uk/digital/2017/08/16/iiifrankenstein/
Can you find the manifest? You cannot load it in our instance of Mirador (because we don’t have internet) but you can load the JSON
manifest on your internet-connected laptop and use the given information to improve your own manifest to your heart’s content.
That’s it! You’ve now successfully installed a IIIF compliant image server on a RPi, shared images, and mixed, matched, and manipulated those of your peers. At this point, you should also be able to set up a similar environment for your own project on a Raspbian or Debian (Linux) system.
The summer school’s first edition was generously sponsored by the University of Antwerp’s Literature Department, the Antwerp Summer University, the Flemish Government’s Department of Economy, Science, and Innovation, Digital Humanities Flanders (DHu.F), and DARIAH-BE – the last of which provided us with the course’s hardware and the opportunity to develop these tutorials further. The development, teaching, and dissemination of this tutorial falls under the purview of the CLARIAH-VL project’s WP2 on Community Engagement, User Involvement and Training.
These tutorials are published under a Creative Commons Share Alike licence (CC-BY-SA 4.0). This means that you can re-use (share and adapt) these slides provided you provide sufficient attribution and publish and distribute the result under the same license.