Turning an eInk screen into a monochrome art gallery

Previously on Terence Eden's Blog: I turned an old eReader into an Information Screen.

This time, I'm taking a different Nook, and turning it into a magic gallery. Here's what it looks like in action:


With the front light off:

With the front light on:

How it works

Every few minutes, it finds a black and white artistic image from Flickr and displays it. Simple!


Ambient home cinema by Tom Whitwell


I've previously replaced the battery on an eInk Nook, so I know how easy they are to disassemble. But for this I wanted to keep the plastic frame on, so that I'd be able to attach a more æsthetically pleasing wooden picture frame.

Finding a picture frame of the right size was a little tricky. The physical dimension of the unit are ~170mm x ~140mm. But the screen is only ~125mm x ~93mm .

I used eFrame - they have a really handy website for custom sized frames and inserts. I ordered a mount for an 135mm x 103mm picture (they cut them slightly smaller but I didn't want any overhang) with 20mm top and bottom borders, and 35mm left and right borders. That gave me enough space to fit the Nook. But, as long as the aperture lets you see the eInk, and masks off the plastic frame, you should be OK.

I was also able to buy a frame without a glass front. As this is my first attempt, I went for simple and cheap wood - rather than something more ornate and artistic. Total cost including shipping was £25.

Attaching the frame

It is useful to be able to get to the main "N" button - and there needs to be a gap for the charging cable. I thought about cutting out a little bit of the frame but, in the end, it was easier to attach the Nook to the frame using velcro and blu-tak. Because of the weight of the Nook, I used some sturdy hooks for the wall mount.


There wasn't enough room in the frame for a normal USB cable, so I used a right-angled micro-USB cable. With the page refreshing every 5 minutes between 0600-2300, it got about 3 days of battery life - less if it used the Glow-Light. So a permanent wired connection seemed sensible.


On the surface this seems quite simple - get a bunch of images and display them. But there are some limitations.

The original Nook Simple Touch is, bless it, an old and slow device. I want to do the minimum amount of processing on it as possible. The screen resolution is only 600x800. I don't want to convert colour artwork to black and white - that will just look messy. I also want the image size to roughly match the screen - so things aren't shrunk down.

So, I want a list of art which meets the following criteria:

  • Intended for monochrome display1
  • Roughly 4:3 aspect ratio
  • Proper art2 by real artists3

I started by looking at the Open Data produced by various museums and art galleries. Unfortunately, none of them indicated whether an artwork was greyscale. So, I turned to Flickr!

Using the Flickr API

Sadly, the Flickr API has been neglected for the best part of a decade. So the documentation is grossly out of date.

Two of the undocumented Search API calls are styles and orientation. I use them to search for black and white images in landscape orientation.
You can discover more by using the Flickr search website and opening the "Advanced" panel.

The rest of the API call is quite standard. A keyword to search for ("art") - or whatever you want. Sorted by "interestingness" - although popularity is also a good metric. With safe_search turned off - no prudes in our house. And an image size no wider that 800px - because serving a correctly scaled image means less work for the eReader.

The Code

It is almost embarrassing in its simplicity. It uses Sam Wilson's PHP library for Flickr. It grabs 100 images, and then picks a random one to serve. It is resized to fit in a bounding box of 800x600 and repaginated to centre the image. The image is rotated it 90 degrees and served over HTTP with an appropriate caching policy. Nothing else. Here it is4.

require_once 'vendor/autoload.php';
$flickr = new \Samwilson\PhpFlickr\PhpFlickr("123465789");

$search_terms = ["art", "artistic", "painting", "drawing"];
$search_rand = array_rand($search_terms, 1);

$sort_terms = ["date-posted-asc", "date-posted-desc", "date-taken-asc", "date-taken-desc", "interestingness-desc", "interestingness-asc", "relevance"];
$sort_rand = array_rand($sort_terms, 1);

$s = $flickr->photos()->search(["text"        => $search_terms[$search_rand],
                                "per_page"    => "100",
                                "styles"      => "blackandwhite",
                                "orientation" => "landscape",
                                "sort"        => $sort_terms[$sort_rand],
                                "safe_search" =>"3"

$number_of_photos = count($s["photo"]);

$random_photo = random_int(0, $number_of_photos - 1);

$p = $s["photo"][$random_photo];

$farm   = $p["farm"];
$server = $p["server"];
$id     = $p["id"];
$secret = $p["secret"];
$title  = $p["title"];

$image_url = "https://live.staticflickr.com/{$server}/{$id}_{$secret}_c.jpg";

$image = imagecreatefromjpeg( $image_url );

$cropped = imagecropauto( $image, IMG_CROP_DEFAULT );
if ( $cropped !== false ) {
   $image = $cropped;

$x = imagesx( $image );
$y = imagesy( $image );

$width_ratio  = $x / 800;
$height_ratio = $y / 600;

// Scale
if ( $height_ratio >= $width_ratio ) {
   $new_height = ( 600 / $y ) * $x;
   $scaled = imagescale( $image, $new_height, 600 );
} else {
   $scaled = imagescale( $image, 800, -1 );

$x = imagesx( $scaled );
$y = imagesy( $scaled );

// Make a background canvas
$canvas = imagecreatetruecolor( 800, 600 );
$black  = imagecolorallocate( $canvas, 0, 0, 0 );
imagefilledrectangle( $canvas, 0, 0, 800, 600, $black );

$dst_x = ( ( 800 - $x ) / 2 );
$dst_y = ( ( 600 - $y ) / 2 );

imagecopy( $canvas, $scaled, $dst_x, $dst_y, 0, 0, $x, $y );

$rotated = imagerotate( $canvas, 90, 0 );

header('Content-type: image/jpeg');
header("Expires: on, 01 Jan 1970 00:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

imagejpeg( $rotated );

// Tidy Up
imagedestroy( $image );
imagedestroy( $scaled );
imagedestroy( $rotated );


As I mentioned in my previous post about displaying web pages on the Nook - the browser is slow, old, and can't handle https connections.

So I used ElectricSign which is an old Android app. Give it a URL and it will display the contents on screen. It can be set to periodically refresh.

I've had it running for months on a different screen and it hasn't crashed.

That's it!


  • Buy more cheap, 2nd hand eInk screens on eBay. Preferably larger and with higher DPI.
  • Get some fancy frames.
  • Start a pirate art museum.
  • Monetise it by tracking how long people stare at a particular artwork.
  • BitCoin?5

Thanks for reading

If you've enjoyed this blog post, you can buy me something from my wishlist or sponsor my GitHub. Find out more way to support this blog.

  1. OK, bit more complicated than that. eInk Pearl can display 16 shades of grey
  2. Whatever that is... 
  3. Whoever they are... 
  4. Licenced as MIT - but it is so basic that I won't be annoyed if you do something else with it. 
  5. LOL! Nope! 

Share this post on…

7 thoughts on “Turning an eInk screen into a monochrome art gallery”

  1. mike says:

    I like it. But I've read the post several times and still don't understand, where is the PHP running?

    1. @edent says:

      Ah, sorry. I have a publicly accessible web sever which is running the PHP code. Electric Sign (the Android app) points to that.

      1. mike says:

        Thanks. I have a Pi that runs 24/7 and could handle also some image processing and being a very low traffic web server. I wonder how many Nooks there are on eBay… 😀


What are your reckons?

All comments are moderated and may not be published immediately. Your email address will not be published.Allowed HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <p> <pre> <br> <img src="" alt="" title="" srcset="">