This repository contains some hourglass modules for RISC OS.
The modules are constructed from animated GIFs through a number of transformations:
- The GIF is split into its compnent frames using ImageMagick.
- The frames processeed into what will be used as the frames of the hourglass:
- They are trimmed to remove borders.
- Colour are changed to reduce the colours to the 3 available on RISC OS.
- Shape transformations may add borders.
- The background is made transparent.
- An animated GIF of the result is constructed.
- The frames are quantised into the 4 palette colours and written into a python module.
- The python module is used to generate sources which can make the frames appear:
- A BASIC program that applies the frames sequentially.
- An assembler library that can be used to set the frames.
- RISC OS AMU files are then invoked to build this into code:
- A standalone C program calls the library, in a similar manner to the BASIC code.
- A module is built which calls the library when the Hourglass SWIs are called.
The result is that from a single make
command, RISC OS hourglasses are made from GIFs.
The full build process requires cross compiling tools, but the repository contains the outputs sufficient that the sources may build on RISC OS.
artrayd1
: A bulbous hourglass which turns over, using just a single colour.artrayd1-filled
: Same asartrayd1
, but with a filled center.artrayd1-bordered
: Same asartrayd1-filled
, but with a border around it.artrayd2
: Simple black hourglass which turns over, using just a sigle colour.artrayd2-filled
: Same asartrayd2
, but with filled center and bordered.cog
: A SVG based cog which just turns, using a single colour.cog-bordered
: Same ascog-bordered
, but with a black border around it.catgbp1990
: A rotating earth.
nkozin
: Simple hourglass beside a pointer, unfilled.nkozin-filled
: Same asnkozin
, but with a filled centre.
The difference between these hourglasses is essentially just the source.gif
file, and the build-shape.sh
which constructs the image data in shape.py
.
dir <hourglass directory>
amu -f ^.MakefileROTest BUILD32=1
amu -f ^.MakefileROModule BUILD32=1
- Locate your source image - a PNG, GIF, SVG or similar.
- PNG and SVG are ok for some images, and might be good for static or simple rotation (like the cog), but an animated GIF gives more options.
- Create a new directory for the hourglass.
- Copy the source image as
source.EXT
. - Copy one of the
build-shape.sh
scripts from an existing directory.- If you're processing an SVG, cog example should be suitable.
- If you're processing a GIF, the other animated examples should be suitable.
- Change the
build-shape.sh
until you have a set of simple frames you like; lots of bits you can do here:- The initial extraction of the images has a
convert
command that either extracts the PNG, extracts many frames from a GIF or rotates the SVG. This will need modifying to makeframe_#.png
that we will work work. This is the source for each frame we create, so it needs to be large enough to rescale well, but we don't need to worry too much about colours. - Update the
width
andheight
to the width and height you want the hourglass to be - remember that RISC OS Classic only supports hourglasses up to 32 pixels wide. The aspect ratio of the output should probably match the aspect ratio of the input if you want to keep the same shape of the image. - Update the
activex
andactivey
to the position of the active point on the hourglass. Usually this is the centre of the hourglass, for which you can just leave the values empty and it will be calculated from the width and height (rounded down). - Update the
frameperiod
with how long you want between frames in centiseconds. Usually you'll leave this as 2 or 3 and then update it at the end once you've worked out how well it works. - Update the
palette
to reflect the colours you want to process out of the source image. These are up to 4 colours (the first of which should be white, or the background colour) which will be taken from the source image - all the rest will be quantised to those 4. They don't have to be the final image colours, but they should be the primary colours you want to extract. - Update the
generatedpalette
to reflect the colours you're going to make. This is a little more complicated, but essentially if you're adding or changing colours in the subsequent processing stage, that's where you'd add those colours. Normally you leave this as the same as thepalette
and come back later to add new colours if necessary. - Update the
riscospalette
to the colours you want to use in the hourglass. The colours you generate in the processing step will be extracted, but you can use any colours your like for the results, so an hourglass that was originally red can actually get coloured as blue by setting the colour to red in thegeneratedpalette
(and maybepalette
), but blue for that colour index inriscospalette
. - Look at the 'Trim and reduce' section which processes the
frame_#.png
images intosimple_#.png
(which are images we will actually use). This is the most complicated part of the process because ImageMagick is not easy to work with at times, but very powerful.- Firstly, the loop has to reference all the frames so that we process them all (assuming you want to process them all - you can select just certain frames if you want, but usually you'll process all of them). The
$(seq 0 #)
command needs updating so that all the frame numbers are processed. - Now the processing of the image in the convert statement needs to be updated; this is more tricky. You will almost certainly need to consult the ImageMagick documentation if you are doing anything more then tweaking the image here. The CI system uses ImageMagick 6.9, and if you've got ImageMagick 7 installed you may find differences, particularly in the handling of the alpha channel.
- There are examples of different operations in the supplied hourglasses. This is why they get more complex - so you can see what's changed between them.
- Filling: Automatic filling of the shape is used in many of them, but is easiest to see in
artrayd1-filled
. However, sometimes the automatic filling doesn't work, and it's necessary to manually fill a shape, which is demonstrated innkozin-filled
. - Bordering: Bordering is given as an example on top of that in
artrayd1-bordered
, but also in thecog-bordered
hourglass. Shaving is performed on most of the hourglasses.
- Filling: Automatic filling of the shape is used in many of them, but is easiest to see in
- There are many ugly effects you can get due to the scaling and misalignment of pixels, and there are many problems caused by the lack of colours. Try to make the hourglass line up to the pixel grid where possible, so that there aren't jagged edges, and try to get the scaling such that horizontal and vertical lines don't change in shape due to grid alignment issues. This is why it's commonly better to draw these small icons by hand.
- You could replace this whole section with more intelligent generation code. So long as you get out frames in
simple_#.png
, they can be made into an hourglass.
- Firstly, the loop has to reference all the frames so that we process them all (assuming you want to process them all - you can select just certain frames if you want, but usually you'll process all of them). The
- Update the
ordered_images
to give the correct order for the frames. This is usually a set ofseq <start> <end>
commands which list the frames to use in the final image. It is common for the animation to not start where you want it to, so reordering the images is useful - this is the case for some of the hourglasses whose source images start out by rotating, but we want them to start with falling sand. Similarly, repeating some frames can make them static for longer, which is used in the artrayd hourglasses to make the final clump of sand stay put before rotating. - Throughout these changes, running the script and then seeing what comes out in the
simple_#.png
files is a tedious but expected process.
- The initial extraction of the images has a
- Symlink the Makefile to the one at the root of the repository; this means that the same build process will be run for the job.
ln -s ../MakefileForHourglass Makefile
- Run the whole build with
make
. If you don't have the cross-compiling RISC OS tools, usemake USE_ROBUILD=1
to generate the RISC OS modules using the build.riscos.online service. - Check the results on RISC OS.
- Run the
hourglass_basic
program to check that it does the right thing. - Run the
aif32.hourglass_test
program to check that the assembler has been built correctly. - Load the
rm32.Hourglass
module and issue*Hon
to check that it behaves as expected.
- Run the
- Rinse and repeat.
- If you're really happy with the hourglass, why not add it to the main repository:
- Update the top level
Makefile
to add the directory name to theHOURGLASSES
variable. - Run
make
(orUSE_ROBUILD=1 make
if you don't have the cross-compiling tools).- Wait for all the hourglasses to build!
- Check that the
artifacts
directory now includes your new hourglass module. - Update this
README.md
to describe your hourglass. - Commit it all to git.
- Usually I squash the changes down to a single change (or structured set of changes), to make the history easier.
- Make sure that the generated files that aren't ignored are also committed. This allows anyone without access to the build process (specifically ImageMagick, but also Python) to still build the hourglass.
- Create a PR.
- Usually you'd fork the github repository, push and then create a pull request for the changes. This process is outside the scope of this document.
- Update the top level