Coloured Sugar

Once I’d finished writing a range of BBC Micro Python-Fu image filters for The GIMP, the Amstrad CPC series seemed the obvious next computer to tackle.

The graphics capabilities of the CPC were very similar to those of the BBC Micro, but the CPCs benefitted greatly from having many more colours available. Everything you could ever want to know about the video capabilities of the Amstrad CPC range is explained here.

The graphics capabilities are so similar, in fact, that to create a graphics filter for Amstrad CPC in Mode 0 all I had to do was change the palette data in my BBC Micro Mode 5 filter. Instead of picking 4 colours from a range of 8 the filter simply needs to pick 16 colours from a range of 27.

So, here is a picture of Baron Sugar‘s beloved Hackney Empire (formerly the ATV Television Theatre):

ATV, Rediffusion and ABC all made programmes here

And here it is put through my Amstrad CPC Mode 0 image filter for The GIMP with no dithering:

Amstrad CPC, Mode 0, No Dither

Oh dear. Even the BBC Micro Mode 2 filter seemed to be able to do better:

BBC Micro, Mode 2, No Dither

Here’s the Amstrad CPC Mode 0 filter with 2×2 threshold matrix:

Amstrad CPC, Mode 0, Ordered Dither 2×2 threshold matrix

The BBC Micro Mode 2 version with a 2×2 threshold matix seems much flatter and less detailed:

BBC Micro, Mode 2, Ordered Dither 2×2 threshold matrix

So what went wrong with no dithering? Well, the method I’m using to choose a palette is very crude – it picks the sixteen most used colours from the Amstrad CPC palette to go into the final image. If my method is applied an image with lots of dark areas and a few highlights the highlights will be completely missing as the light colours will not be used enough to feature in the final table of 16 colours. I obviously need to find a method that takes into account the range of luminance used on an image.

The situation gets even worse when dealing with the Amstrad CPC Mode 1. Amstrad CPC Mode 1 is very similar to the BBC Micro’s Mode 1. But whereas Mode 1 on the BBC Micro can pick 4 colours from a selection of 8, Mode 1 on the Amstrad CPC can pick 4 colours from a selection of 27.

Here’s a picture of Polly parrot:

Pining for the fjords

Here’s the same picture put through the Amstrad CPC Mode 1 filter with no dithering:

Amstrad CPC, Mode 1, No Dither

Here’s the same picture of a parrot put through the BBC Micro Mode 1 filter with no dithering.

BBC Micro, Mode 1, No Dither

Even Sierra3 error diffusion won’t help the Amstrad CPC Mode 1 image:

Amstrad CPC, Mode 1, Sierra 3 Error Diffusion

Whereas the BBC Micro filter produces excellent results:

BBC Micro, Mode 1, Sierra 3 Error Diffusion

Needless to say, the Amstrad CPC filters should be producing better results than the BBC Micro filters!

So, I’m going off to find a better way to pick an Amstrad palette! In the meantime, if you want to play with the Amstrad CPC filters they can be downloaded from here. Microsoft Windows users can find out how to install and use the filters with The GIMP by following the very nice set of instructions with pictures I’ve found here.

A la Mode

Time for another chapter in the continuing story of producing Python-Fu retro computing image filters for The GIMP from some original programs in sdlBasic by nitrofurano.

In my last post I talked about ordered dithering, and how it compared to the error diffusion technique I had implemented previously. After successfully implementing ordered dithering the natural next step was to incorporate the ordered dithering into my BBC Micro Mode 2 image filter so that all the image processing techniques were available in one filter.

Finished filter interface

Whilst doing this, I also made the Strength slider in my BBC Micro filter act upon Ordered Dithering as well as Error Diffusion. This allows for some quite interesting effects.

Here is John Liven’s Somerset cottage picture. I’ve applied Ordered Dithering with a 2×2 threshold matrix set to 100% strength:

Mode 2, 2×2 Ordered Dither, 100% Strength

And here is the same picture with the same dithering applied at just 50% strength:

Mode 2, 2×2 Ordered Dither, 50% Strength

Once this was done the BBC Micro Mode 2 filter was finally finished off. I then turned my attention to writing a BBC Micro Mode 5 filter. Mode 5 is very similar to Mode 2, but you can only use 4 colours from a selection of 8.

This means the image filter needs an additional step in which the palette to use for the image is selected. The way I approached this was to scan the entire image pixel by pixel tallying which of the 8 possible BBC Micro colours each pixel was closest to. Then, I simply used the four most commonly found colours.

Incidentally, the way you work out how close one colour is to another is quite simple once it’s explained to you: I found the answer here.

After a coding a bit of Python I loaded an image of some parrots into The GIMP:

Norwegian Blue is on the left

And tried out the filter with no dithering. It worked first time:

Mode 5, No Dithering

And when some Sierra3 error diffusion was added too, the results were incredibly good:

Mode 5, Sierra 3 Error Diffusion 100% Serpentine

I still can’t get over the fact that there are just four colours (black, white, red and green) in this image.

With a Mode 5 filter under my belt it was very easy to produce a Mode 1 filter. Mode 1 is the same as Mode 5, but has square pixels:

Mode 1, Sierra 3 Error Diffusion 100% Serpentine

And a Mode 4 filter. Mode 4 is like Mode 1, but is restricted to just two colours:

Mode 4, Sierra 3 Error Diffusion 100% Serpentine

So, I have got a pretty nice suite of BBC Micro image filters, with only Mode 0 to add. As always, you can download them from here. Microsoft Windows users can find out how to install and use the filters with The GIMP by following the very nice set of instructions with pictures I’ve found here.

What A Ditherer

I’ve spent a lot of time recently converting nitrofurano‘s sdlBasic retro computing picture converter programs into Python-Fu image filters for The GIMP. I’ve also been adding a few ideas of my own – particularly in the area of half-toning techniques.

After successfully getting Error Diffusion working, I decided to see if I could get Ordered Dithering working. Ordered Dithering is a technique akin to the half-toning you see on images in newspapers. From an image made up of many colours you can create an image made up of only a handful of colours stippled such a way as to give the illusion of many colours.

There are several excellent explanations of Ordered Dither on the web for the curious written by people who actually know what they are talking about – I would recommend this one and this one.

Ordered Dithering is much simpler than Error Diffusion (which is probably why it took me longer to get it working!). As it’s a much simpler process it’s lightning fast in comparison, even when coded in Python.

As a test, I took John Liven’s picture of a Somerset cottage. 

Photo: John Livens

Then I converted the image to the BBC Micro‘s MODE 2 (which has just eight colours) using an ordered dither with a 2 x 2 threshold matrix.

BBC MODE2, Ordered Dither, 2×2 matrix

As you can see above, it produces a very pleasing regular patterning on the colours – to allow you to compare, here is the same image with Floyd-Steinberg Error Diffusion:

BBC MODE2, Floyd-Steinberg Error Diffusion

On a small image such as this, larger grids don’t really add much. Here is an ordered dither using a 4 x 4 threshold matrix:

BBC Micro MODE2, Ordered dither, 4×4 matrix

But, the proof of the pudding is in the eating. If you have The GIMP installed on your computer you might like to try the ordered dither filter for yourself – it’s available from here.

BBC on the BBC

Over the past few days I’ve been converting nitrofurano‘s image filters from stand-alone sdlBasic programs to Python-Fu image filters for The GIMP. But, so far, there has been a particularly noticeable absence – the BBC Micro.

Partly that was because the BBC Micro world has already been utterly spoilt in the image conversion department by Francis G. Loch‘s incredible BBC Micro Image Converter. It’s a highly professional piece of software and does it all. I’ve posted about it many times here and the work I’ve done for Retro Software would have been utterly impossible without it.

BBC Micro Image Converter by Francis G. Loch

But partly it was because Francis’ program had inspired me to try and find out more about the mind-boggling array of dither options he had included in his program. It boasted a host of exotic sounding names like “Floyd-Steinberg”, “Sierra”, “Jarvis, Judice and Ninke” and “Stucki”.

Paulo had used a technique called Bayer ordered dither in his filters, which is similar to the traditional half-toning used in print. It’s very powerful, very fast and gives you a lovely regular patterned effect on the images, which is sometimes just what you’re after.

Naturally, Francis’ BBC Micro Image Converter does this as well. But these exotic sounding names were the inventors of various flavours of another technique: error diffusion.

Error diffusion works by trying to compensate for the colour information lost by turning a pixel into a value from a restricted palette by sharing it out amongst the surrounding pixels.

After looking at the Wikipedia entry for Floyd-Steinberg, it looked like even I could understand how to program it and then after finding an excellent article here I realised that all the other filters did exactly the same thing. They just shared out the lost information (or quantisation error) to different pixels in different proportions.

And, after a couple of hours messing about in Python, I managed to get out a servicable MODE 2 image (click on the images to enlarge):

Floyd-Steinberg error diffusion, 100% strength

You can see just how effective error diffusion is when you compare the results to the same image processed with no error diffusion:

The same image with no error diffusion

Here’s the original image for comparison:

I’m the one on the right

I excitedly added a range of different filters into my BBC Micro image filter:

Take your pick!

There was a problem though. Sierra3 was taking well over 70 seconds. This sluggishness was caused by the inefficient way in which I was checking that a pixel was within a certain range in Python.

Sierra3, 100% Strength – and very slow!

An error message I had been getting during development rather ironically proved to be the key to solving the speed problem. Instead of using time consuming range() functions to see if pixels were inside a particular range, I could use exception handling and check for an IndexError instead. This was very fast – it sped the filter up by a factor of at least four. Mind you, it still crawls along compared to Francis’ version!

The next thing I needed to add to the filter was something called “Serpentine parsing“. This means that instead of processing the image from left to right as it moves down, the computer processes the image backwards and forwards. This helps to stop all the error diffusion going in just one direction – smearing all the errors to the right.

Finally, pinching another one of Francis’ excellent ideas, I added a strength control to the filter to allow you to control how strongly the error diffusion works.

Finished interface

Here is Test Card F with 50% Floyd-Steinberg error diffusion strength:

Floyd-Steinberg error diffusion, 50% strength

And here it is with 25% Floyd-Steinberg error diffusion strength:

Floyd-Steinberg error diffusion, 25% strength

So, a BBC Micro Mode 2 image filter for The GIMP, that can be downloaded from here. However there are numerous refinements that need to be added to it. But they will have to wait for another day.

Test Card F Copyright © 1967 BBC, ITA and BREMA.

If you see SID, tell him…

I’ve converted nitrofurano‘s sdlBasic Commodore 64 Low Resolution mode picture converter into a Python-Fu image filter for The GIMP.

In Commodore 64 Low Resolution mode, each block of 4 x 8 2:1 aspect ratio pixels can contain four colours from a choice of 16.  Only, it’s a bit more complicated than that! Fortunately, this article explains how it is supposed to behave very nicely. Paulo’s algorithm has to go through eight separate stages to create the finished image.

The main novelty for me in this filter was that in order to avoid having to use a three dimensional list (which would have entailed syntax to boggle the mind) I used a Python new-style class. That meant I could use a one dimensional list and let the class take care of getting and setting the right bit of it when required through method calls.

Here’s an example image before:

Original scan

And after conversion in The GIMP using the filter:

Commodore 64 Low Res Filter

As usual this plug-in, along with ones for the ZX Spectrum, Apple II and MSX1 can be downloaded from here.

Appley Within

As I had enjoyed converting nitrofurano‘s sdlBasic MSX and ZX Spectrum picture converters to The GIMP, I thought I’d tackle the Apple II colour picture filter next.

Mind you, saying that the Apple II had a colour mode is a bit like saying that Steve Wozniak was a professional ballroom dancer. Whilst technically correct, it really is wide of the mark.

Apple II colour is a strange world in which “red or yellow” becomes orange and “blue or cyan” becomes blue. Because of this Paulo’s filter was rather more complicated than the ones I’ve tackled previously. In all, it took me about three days to understand what was going on and finally iron out all the bugs (mine, not Paulo’s!).

Because of the complexity of the filter, I decided to implement some functions to emulate the ink(), dot(), point() and line() commands of sdlBasic. This made the Python much more readable (and eaiser to debug), even if it did mean I lost a bit of speed.

In order to make up some of the lost speed, I used tuples instead of lists for the look-up tables. I should have done this in my other filters too.

Once I finished the filter I dug out my usual cottage picture as a test:

Photo: John Livens

The resulting image had me crying into my coffee:

Soundtrack from the film More?

It looked like something out of “The Lost World of Friese-Greene“! Having picked out some bugs I got something a bit closer, but the white stripes were a real pain to get rid of:

It took ages to fix…

Finally, after I had remembered how to count to six, I got a successful image:

…but the result was worth it.

The filter runs in two modes, a halftone mode or a posterised mode. The posterise mode doesn’t stipple the colours. Here is the posterised output:

Posterised, it’s very striking

I added a little dialogue box to the filter to allow users to pick which mode they want:

The filter’s complex user interface

My overall impression is that the Apple II produced orangey mush – a bit like the NTSC pictures put through the IBA‘s DICE standards convertor we used to see on British television in the 70s. But, I must admit, it does have a certain kind of charm. And, above all, Paulo did an incredible job in coming up with an Apple II filter – it’s an ingenious bit of coding.

If you want to try it out for yourself, the filter is available to download from here. Bear in mind that the filter is pretty slow, so it’s best to stick to small images unless you have a fast computer.

MSX Picture Filter for The GIMP

Now that Paulo Silva’s (nitrofurano) ZX Spectrum filter for The GIMP was working nicely, I thought I’d like to try converting one of his other sdlBasic picture filters into a Python GIMP plug-in.

I chose the MSX1 Screen 2 filter, as it looked quite similar to the ZX Spectrum filter. I’d never actually seen an MSX computer working (I saw some switched off in a shop once) so I didn’t really know what to expect until I read up on Wikipedia.

Whereas the ZX Spectrum suffered from attribute clash on the character square level, MSX1 suffered from attribute clash on the character row level so I was expecting the resulting images to look like slightly better ZX Spectrum images. And so it turned out.

To compare, here is John Liven’s photograph of a cottage:

Cottage – Photo: John Livens

And here it is processed by the ZX Spectrum filter:

Cottage – ZX Spectrum

And finally by the MSX1 filter:

Cottage – MSX1

Converting the filter was straightforward, and I managed to find and fix a small bug in the sdlBasic original whilst I was going along.

As always, the finished MSX1 filter can be downloaded from here.

Unweaving the Rainbow

As I promised a couple of days ago, I’ve tweaked nitrofurano‘s ZX Spectrum filter for The GIMP so that you can now undo (and redo!) the effects of the filter properly.

Not a favourite album, but a nice cover

To get undo to work I needed to create a duplicate of the current layer to work on, and then merge that down into the original layer when the filter has finished its work.

From XOR to AOR

That way, The GIMP seemed to remember the original layer and could go back to it when you used undo.

So now, hopefully, it’s all finished. The final version of the filter is available to download from here. People with Windows or Macs wanting to try the plug-in need to follow the instructions here. GNU/Linux users can just copy it into their ~/.gimp2.6/plug-ins folder and set the Execute permission.

ZX Spectrum +3

Two days ago I blogged about getting nitrofurano‘s Python ZX Spectrum image filter for The GIMP working, and yesterday I blogged about speeding it up. However, Paulo e-mailed me just after I’d posted and said that the filter wasn’t working as it should.

I had assumed that the filter just wasn’t supposed to work on small images – such as ones at the ZX Spectrum resolution of 256 x 192. So if we took a 256 x 192 image like this:

Original image at 256 x 192

The best we could hope for would be this:

Put through The GIMP version of filter

However, Paulo pointed out that his sdlBasic version of the filter would produce this:

Put through sdlBasic version of filter

But having looked at the Python code for The GIMP filter he couldn’t work out what was wrong. I was intrigued, and decided to have a look too.

Paulo thought that the problem probably lay in one of the loops that were processing the image, but I thought that was unlikely, particularly as he’d checked them so thoroughly against his sdlBasic original. The loops just contained maths, and maths tends to be pretty similar in any language.

Sure enough, the problem lay not in the maths but in the idiosyncratic weirdness of Python. I blame Eric Idle, personally.

The first problem was the way in which Paulo had dimensioned the lists (elderly gentlemen like me call them arrays) he used to work on character blocks. He’d done this:

r0 = [[0] * 8] * 8
g0 = [[0] * 8] * 8
b0 = [[0] * 8] * 8

Which is perfectly sensible, but the problem is in Python almost everything is copied by reference rather than by value. Numbers are copied by value, so [0] * 8 does create a list containing eight different zeros.

However lists are copied by reference so [[0] * 8] * 8 creates a list containing eight references to the same list. That means that any change made to one row of this multidimensional list affects all the other rows too – effectively cutting the resolution of the filter down to the character block level. This caused the blockiness.

To solve it we needed to do this:

r0 = [[None] * 8 for i in range(8)]
g0 = [[None] * 8 for i in range(8)]
b0 = [[None] * 8 for i in range(8)]

What we are doing now is using a list comprehension to create a brand new list eight times, which is what we are after.

Another problem was that instead of referring to the nested lists using list[y][x] Paulo had used list[x][y]. So, for instance we had this:

b0[x2][y2] = str1[2]
g0[x2][y2] = str1[1]
r0[x2][y2] = str1[0]

When we should have had this:

b0[y2][x2] = str1[2]
g0[y2][x2] = str1[1]
r0[y2][x2] = str1[0]

It’s very easy to do – in fact I’ve done it myself. Many times!

Regarding Python’s weirdness, it more often works for you than against you and that’s why I love the language. For instance, in Paulo’s sdlBasic version of the filter he had to do this to swap two values:

if ikattr < paattr:
tmpr = ikattr
ikattr = paattr
paattr = tmpr

Whereas in Python you can use the far more “Pythonic”:

if ikattr < paattr:
ikattr, paattr = paattr, ikattr

Anyway, now the filter was fixed and I could have some fun with some ZX Spectrum proportioned stupid rubbish. Here is Central News at 256 x 192:

It’s 1982 again!

And here is a Tyne Tees/Channel 4 endcap – again at 256 x 192:

Unworthy of Half Man Half Biscuit

However, Paulo used it to produce something much grander:

by nitrofurano – Click to enlarge

This isn’t the end of the story, unfortunately, as now I have to get the filter’s Undo feature working – but tomorrow you’ll be pleased to hear there will be something completely different.

The latest version of the ZX Spectrum image filter for The GIMP is available to download from here.

ZX Spectrum Filter Revisited

Well, a day is a long time in Free Software. Since I posted yesterday about the ZX Spectrum filter for The GIMP, I’ve had a lovely exchange of e-mails with the original author nitrofurano, I’ve improved the filter further and I’ve found out why it was written.

Spectral Spectrum

First things first, improving the filter. I had become rather rusty at working on filters for The GIMP but eventually everything came flooding back to me.

The first thing that helps when writing a Python filter in The GIMP is to run The GIMP from the command line in a terminal window. That way you get to see all the error messages the plug-in produces and are not working “blind”. You can also see the output of any print statements you add to help you debug.

The second thing I remembered was that you should use a symbolic link to the filter in The GIMP’s plug-in folder, so you can work somewhere more convenient than a hidden folder that’s several levels down.

Sugary Spectrum – click to enlarge

Once I’d got myself working sensibly I could have a look at improving the filter. The first thing I did was to speed the filter using this technique described in Akkana‘s blog.  It cuts down on writing to the actual image, which is slow. Instead you copy the image to a byte array, work with that and then copy all the bytes back to the image when you have finished. Using Akkana’s technique had the added bonus of allowing the filter to be adapted easily work with either RGB or RGBA images.

However, the resulting changes didn’t seem to generate the desired increase in speed until I realised I had stupidly queried the image class’ size and width repeatedly instead of storing the values in variables. Once I did that the filter literally flew.

Nitrofurano (Paulo Silva) has been lovely and very encouraging as I’ve been hacking his lovely code to bits. He’s also as enthusiastic about free software as I am. I think it’s fantastic that people who have never met before can work on each other’s software, share ideas and get to know each other – the GPL really does work as advertised.

Sinclair TV – thanks to Nitrofurano

The reason the code was written originally was to be part of a very interesting project Paulo is working on to create “retro” vision web-cams. You can find out more about it here.

You can download the updated python-fu ZX Spectrum filter for The GIMP here.