ROCoding #3: Ellipses and rings

Monday, February 23, 2026

The previous post in this series covered circular or radial blends and gradients. With a few simple modifications the code can be adapted to create elliptical and annular fills. Or eggs and doughnuts, if you prefer 😉.

Again, all these examples will be using various procedures from the previous posts.

RISC OS provides some graphics primitives to draw ellipses, and from BASIC this is:

ELLIPSE [FILL] centreX,centreY, width,height [, angle] 

We won’t be using this however, and we won’t be including the angle setting, which draws a rotated ellipse. Let’s not make it too complicated…

Elliptical gradients

First we add some lines to PROCinit to set up some gradients to use (g%() will be used for generated blends):

DIM bow%(256),plasma%(256),g%(256)
nbow%=FNload_palette_file(”Palettes:bow2/pal”,bow%())
nplasma%=FNload_palette_file(”Palettes:Plasma/pal”,plasma%())
ng%=256

Our new procedure is PROCelliptical_gradient. The arguments are similar to PROCradial_gradient, with the addition of ecc, which is a measure of eccentricity. The horizontal radius is given by rad%, and the vertical radius is rad% multiplied by ecc. So positive values below 1.0 will squash it vertically, while values greater than 1.0 will give a tall ellipse. An ecc value of 1.0 will, of course, be the same as calling PROCradial_gradient.

DEF PROCelliptical_gradient(x%,y%,rad%,ecc,ncols%,gradient%(),flags%)
LOCAL vduvars%,c%(),radp%,s,i,os1%,X%,Y%,Y2%,d%
radp%=rad%>>xeig%
DIM vduvars% LOCAL 24, c%(radp%)
vduvars%!0=136: vduvars%!4=137:vduvars%!8=-1
SYS ”OS_ReadVduVariables”,vduvars%,vduvars%
VDU 29,x%;y%;
i=ncols%/radp%
IF flags% AND 2: s=ncols%-1: i=-i
FOR X%=0 TO radp%-1: c%(X%)=gradient%(s): s+=i: NEXT
os1%=1<<xeig%
FOR Y%=0 TO rad%*ecc-os1% STEP os1%
  Y2%=Y%/ecc*Y%/ecc
  FOR X%=0 TO rad%-os1% STEP os1%
    d%=SQR(Y2%+X%*X%)
    IF d%<(rad%-1) THEN
      SYS CT_SetGCOL%,c%(d%>>xeig%)
      POINT X%,Y%: POINT -X%,Y%: POINT -X%,-Y%: POINT X%,-Y%
    ENDIF
  NEXT
NEXT
VDU 29,vduvars%!0;vduvars%!4;
ENDPROC

The code is fairly similar, apart from the first lines of the Y% loop. We scale the vertical pixel loop (Y%) by ecc, and then the Y%-squared value — Y2% — is rescaled so it becomes, in effect, the Y value of a circular blend. Which is then used to get the colour.

Note that this procedure isn’t very robust, and would benefit from some error checking — for example, the ecc value should be checked it’s greater than zero.

ROC03ell0s.webp
PROCinit
PROCelliptical_gradient(128,128, 128, 0.3, nbow%, bow%(),0)
PROCelliptical_gradient(48,128, 32, 4.0, nbow%, bow%(),2)
PROCmake_blend(yellow%,red%,ng%,g%())
PROCelliptical_gradient(208,128, 32, 2.5, ng%, g%(),0)

This draws two rainbow-filled ellipses with eccentricities of 0.3 (the wide one) and 4.0 (the tall one, with the palette inverted), and a blend between yellow and red.

ROC03ell3.webp

To finish, here’s a collection of 20 random ellipses with random colour blends:

PROCinit
FOR i%=1 TO 20
  PROCmake_blend(RND,RND,ng%,g%())
  xc%=RND(780)+10: yc%=RND(780)+10
  r%=RND(100)+50: e=RND(100)/40+0.1
  PROCelliptical_gradient(xc%,yc%, r%, e, ng%,g%(),0)
NEXT

Annular gradients

An annulus is a ring. As an aside, an annular eclipse is when the Moon appears slightly smaller than the Sun — caused by the lunar orbit being an ellipse, with varying distance from the Earth — and hence the eclipse appears as a ‘ring of fire’.

To create a ring, we provide inner and outer radii to our procedure in the parameters irad% and orad%. If the inner radius is zero, it will act like PROCradial_gradient.

Here’s the code:

DEF PROCannular_gradient(x%,y%,irad%,orad%,ncols%,gradient%(),flags%)
LOCAL vduvars%,c%(),radp%,s,i,os1%,X%,Y%,Y2%,d%
IF irad%>orad% SWAP irad%,orad%
IF (orad%-irad%)<8 ERROR 100, ”Inner and outer radius too similar”
radp%=(orad%-irad%)>>xeig%
DIM vduvars% LOCAL 24, c%(radp%)
vduvars%!0=136: vduvars%!4=137:vduvars%!8=-1
SYS ”OS_ReadVduVariables”,vduvars%,vduvars%
VDU 29,x%;y%;
i=ncols%/radp%
IF flags% AND 2: s=ncols%-1: i=-i
FOR X%=0 TO radp%-1: c%(X%)=gradient%(s): s+=i: NEXT
os1%=1<<xeig%
FOR Y%=0 TO orad%-os1% STEP os1%
  Y2%=Y%*Y%
  FOR X%=0 TO orad%-os1% STEP os1%
    d%=SQR(Y2%+X%*X%)
    IF d%>=irad% AND d%<(orad%-1) THEN
      SYS CT_SetGCOL%,c%((d%-irad%)>>xeig%)
      POINT X%,Y%: POINT -X%,Y%: POINT -X%,-Y%: POINT X%,-Y%
    ENDIF
  NEXT
NEXT
VDU 29,vduvars%!0;vduvars%!4;
ENDPROC

The main difference in the code is checking that d% is between the two radii before drawing anything. The procedure has some rudimentary error checking, to ensure that the ring isn’t unfeasibly thin. I’m also swapping them if they’re in the wrong order. To demonstrate:

ROC03ann1.webp
PROCinit
PROCannular_gradient(400,400, 300,400, nbow%,bow%(),0)
PROCmake_blend(green%,blue%,ng%,g%())
PROCannular_gradient(400,100, 100,280, ng%,g%(),0)
IMG_6770gc.webp

This is the rainbow gradient displayed in a ring with inner radius 300 and outer radius 400. Overlaid is a blend between green and blue with radii 100 and 280.

Incidentally, you’ll notice from the picture on the right that the rainbow gradient is wrong — a real rainbow has red on the outside of the primary bow (the secondary, fainter one, is the other way round). Easy enough to change by setting flags% to %10.

Dwarf Mini and RISC OS

Saturday, February 14, 2026
DM01-01mini.webp

The Dwarf Mini is an ultra-portable “smart telescope”, suitable for photographing deep-sky objects like nebulae and galaxies. It can also be used to image the sun and moon, but isn’t suitable for planetary imaging as the magnification is too small. It’s also useful for terrestrial imaging.

There is no eyepiece — you don’t look through it — and all operations are controlled via a tablet or smartphone, in our case a Pixel 6a. It’s motorised and can track astronomical objects automatically, either by just plonking it down on a flat surface or, for more accuracy in longer exposures, setting up an equatorial mount: just attach it to a tripod and align the scope to the pole star. There are built-in filters for deep-sky objects, a magnetically attached solar filter, and the device can take many images and stack them to increase the quality.

There are two cameras, wide-field and telephoto. The scope communicates with your phone using NFC, Bluetooth or wifi, giving a live display. The wifi can connect over your home LAN or directly, using its own server. All operations are controlled remotely, so (given adequate wifi range) you can do an observing session from inside your own home — a distinct advantage on cold winter nights. There’s a built-in comprehensive sky atlas and the app has a help system, and there’s a full manual online, also available as a PDF.

An example

DM01-02sun.webp

So what do the images look like? We’ve had terrible weather recently, but today was our first clear day for ages. And here’s the sun at 8:30 this morning.

There are three small sunspots visible, confirmed via the SpaceWeather site. It’s a stack of 20 photos, each with 1/200sec exposure. Tracking was perfect — all I needed to do was point it at the sun and the rest was automatic.

DM01-03birds.jpg

And just to show it can do more, here are some starlings, photographed a few hours later. All shots were taken through an open window.

Accessing the files

While the phone is connected to the Mini, you can download the final stacked image to your phone as a standard JPEG, and then transfer it to your NAS or computer for perusal and editing. But to access the full uncompressed data — which consists of a number of raw images in FITS or TIFF format along with shooting data, calibration images and a PNG file of the stacked result — you need a different connection.

The manual for the scope claims that you can access the full images via a USB C-C cable, also used for charging the scope’s battery. But I’ve not been able to get that to work with any of our devices/computers — for example, if we plug the scope into our phone using the supplied cable it just starts charging the scope’s battery from the phone. I’m not alone in this; a number of other users report the same problem.

Fortunately, the Dwarf Mini has a built-in wifi server, and this method works perfectly, giving access to the full data over FTP. And RISC OS will happily connect to it so you can download images:

DM01-04ftp0.png
  • Power on the Dwarf Mini
  • Wait until the Mini’s indicator is a circling green light
  • On RISC OS, select the device from wifi networks
  • Enter the wifi password (the default is in the manual)
  • Wait until the iconbar connection icon is green
  • Now you can use FTPc to connect:
    Host: 192.168.88.1
    Security: 0 - None…
    Passive: On

Add this connection to FTPc’s user menu with an appropriate name. For reference, I’m using a 4te2 running RISC OS 5.31.

Once you’re connected, you should see see a filer-like display, as right. You can navigate this like a filer window and copy files by drag-and-drop.

Note that my main internet connection is via an ethernet cable. This operates concurrently with the wifi, so I’m able to copy files straight over to our NAS. Also note that if the scope isn’t connected to a phone, it will power down after 10 minutes or so — the ftp connection does not override this.

The Astronomy directory will contain a number of subdirectories containing the actual data. The names of these contain useful information — for instance, the data for the sun picture above is inside:

DWARF_RAW_TELE_Sun_EXP_0.005_GAIN_10_2026-02-14-08-36-33-624

This tells you which lens was used (TELE), the target (Sun), the exposure times (0.005sec), the gain used (10 — this is roughly like the ISO setting in a camera), and the date and time (YYYY-MM-DD-hh-mm-ss-mss). It’s unfortunate that FTPc’s display can’t be made wider; you have to navigate the menu to Info to see the full name.

Inside the directory there’ll be a number of files like this:

Sun_0.005s10_Astro_20260214-083640954_25C.fits

…which is a FITS file. Again, there’s useful information here: the target (Sun), exposure time (0.005sec), the gain (10), the internal filter in use (Astro), and the date and time (YYYYMMDD-hhmmssmss). And lastly, 25C is the sensor temperature.

There’ll also be a file called shotsinfo.json, which can be opened as a text file:

{
    ”DEC”: 0.0,
    ”RA”: 0.0,
    ”binning”: ”1*1”,
    ”exp”: ”1/200”,
    ”format”: ”FITS”,
    ”gain”: 10,
    ”ir”: ”Astro”,
    ”maxTemp”: 25,
    ”minTemp”: 25,
    ”shotsStacked”: 20,
    ”shotsTaken”: 20,
    ”shotsToTake”: 20,
    ”target”: ”Sun”
}

DEC and RA are the celestial coordinates of the target. For the sun and moon this is not set, as the device tracks the target using the image itself, rather than knowing its position in the sky. For other objects, when you request a target the scope will analyse the star pattern it sees, and work out exactly where in the sky it’s pointing — an impressive process known as plate solving. The scope can then slew to the target’s position.

The stacked.jpg file is the one you can access on the phone, and there are also stacked versions as a 16-bit png and a 16-bit FITS file.

If you look at one of the FITS files in a text editor (double-click and hold), there’s a header like this:

SIMPLE  =                    T / file does conform to FITS standard
BITPIX  =                   16 / number of bits per data pixel
NAXIS   =                    2 / number of data axes
NAXIS1  =                 1280 / length of data axis 1
NAXIS2  =                  720 / length of data axis 2
EXTEND  =                    T / FITS dataset may contain extensions
BZERO   =                32768 / offset data range to that of unsigned short
BSCALE  =                    1 / default scaling factor
DATE-OBS= ’2026-02-14T08:36:40.944′ / Time end of exposure
EXPTIME =                0.005 / [s] Exposure Time
GAIN    =                   10 / Gain
RESTACK =                    0 / is Mega Stack
XBINNING=                    1 / binning factor used on X axis
YBINNING=                    1 / binning factor used on Y axis
FILTER  = ’Astro   ’           / selected filter
CAMERA  = ’TELE    ’           / shooting camera
XPIXSZ  =                  2.9 / [um] pixel size in microns (with binning)
YPIXSZ  =                  2.9 / [um] pixel size in microns (with binning)
FOCALLEN=                 150. / [mm] Focal length of telescope in mm
DET-TEMP=                   25 / Detector temperature in C
RA      =                   0. / [deg] Observe object RA coordinate (J2000)
DEC     =                   0. / [deg] Observe object DEC coordinate (J2000)
OBJECT  = ’Sun     ’           / Observe object
BAYERPAT= ’RGGB    ’           / Bayer pattern
EQMODE  =                    0 / Equatorial mode
FIRMWARE= ’1.0.22.1′           / telescope firmware version
MACADDR = ’xxxxxxxxxxxx’       / telescope MAC address
TELESCOP= ’DWARF mini’         / DWARFLAB telescope
INSTRUME= ’DWARF mini’         / DWARFLAB instrument
ORIGIN  = ’DWARFLAB’           / DWARFLAB TEAM
END

Solar and lunar photography has a resolution of 1280×720, while everything else is 1920×1080. The raw data is 16-bit graphics — just to be clear, that’s 16-bits per channel. And here’s where RISC OS will have problems: there is little software that can process 16-bit graphics files.

PhotoDesk will load the 16-bit PNG. I haven’t played around much, but on a star field image, the Increase contrast setting of Image processing>Gamma does a good job of reducing colour noise.

ChangeFSI can sort-of handle FITS files. But with limitations: you’re losing data (and low-level light data is very important in astronomical imaging), and you’ll get a greenish tinge which needs to be processed out. This is due to the RGGB Bayer pattern of the detector, which is quite standard.

I’ll be investigating this further, and will report on results here. Let’s hope for … clear skies! Which we had briefly last night, enough to get a first attempt at a random star field:

DM01-05stars.webp

Well, I say random — it’s actually centred on the star HIP 80364, which, if you google it, turns out to be a star in the game Elite: Dangerous. So, a RISC OS connection…

ROCoding #2: Circles

Tuesday, January 20, 2026

The first post in this series covered filling a rectangle with blends and gradients. This time we’ll look at generating circular or radial blends and gradients, which is a bit more complicated. All these examples will be using various procedures from the previous post.

RISC OS provides graphics primitives to draw outline and filled circles. From BASIC:

ROC02circ0.webp
PROCinit
SYS CT_SetGCOL%,&40dd4000
CIRCLE 64,192,60
CIRCLE FILL 192,64,60

The parameters are the centre coordinates and the radius, in OS units. As an aside, here’s the additive RGB triplet as used in the PhotoDesk manual, showing the complementary cyan, magenta and yellow colours. The circles are blended with the OR operation:

ROC02circ0rgb.webp
PROCinit
SYS CT_SetGCOL%,red%
CIRCLE FILL 128,160,80
SYS CT_SetGCOL%,blue%,,,,1
CIRCLE FILL 170,88,80
SYS CT_SetGCOL%,green%,,,,1
CIRCLE FILL 92,88,80

So, can we use these primitives to create a radial blend? Here’s a first attempt:
[Read more…]

ROCoding #1: Rectangles

Friday, December 12, 2025

Coming back to RISC OS has been interesting. I’ve had to re-learn a number of things, like using the WIMP and, in particular, graphics programming. I hope this article will be the first of a series explaining my learning curve, and hopefully providing some useful programs. It’s fairly basic — in all senses! — but does assume some familiarity with RISC OS and BBC BASIC.

We’ll start with some things you can do when drawing rectangles. While writing the Solar application I wanted to provide some better backgrounds for the graphs. A plain background is easy, of course: just use RECTANGLE FILL with some appropriate colour, like this.

rect0.webp
GCOL 0,&ff,&dd,&ff
RECTANGLE FILL 0,0,256

…which draws a 256×256 square at the graphics origin. More generally, RECTANGLE accepts both width and height, which can be negative.

First up, we’ll generate a blend between two colours, from the bottom to the top of the rectangle. We’re assuming a full-colour display here, which is necessary for displaying blends with any fidelity. The Solar application graphs are built up by redirecting all graphics output to a sprite, then letting the Wimp handle displaying them on screen; this takes care of any mismatch between the screen and graph colour depths.
[Read more…]

BASIC 5 vs BASIC64 [updated]

Saturday, November 29, 2025

[Updated 5 Dec 2025. Now includes BASIC FPA timings, and text updated. DIV is now included.]

While writing the Gradgrind program (qv) I wondered if it would benefit from running under BASIC64 (or VI), as opposed to BASIC 5 (V). So I ran up a few simple speed tests (and they are simple — don’t take the results as definitive benchmarks). Although the program runs acceptably fast on my setup (a 4té2, which is based on a Pi 4b), it uses a fair amount of real arithmetic. The chief difference between the two versions is that BASIC 5 stores reals in 5 bytes, while BASIC64 uses 8 bytes. BASIC64 itself has two variants, VFP using the vector floating point operations available on the Pi’s ARM processor, and FPA using software floating point.

To use each variant:

  • basic <file> Runs <file> using BASIC V. This is also the default setup for double-clicking a BASIC file.
  • basic64 <file> Runs <file> under BASIC VI, which will select the VFP variant if available, otherwise uses FPA.
  • basicvfp <file> Forces the VFP variant, if available.
  • basicfpa <file> Forces the FPA variant.

The program to generate these results is available from the Downloads page.

System details:
R-Comp’s 4té2 (based on the Raspberry Pi 4b) running RISC OS 5.31 (21-Jul-24) at 1.5Ghz
BBC BASIC V 1.85 (03 Oct 2022)
BBC BASIC VI 1.85 (03 Oct 2022) VFP
BBC BASIC VI 1.85 (03 Oct 2022) FPA

Notes on the tests

  • All tests were run in single-tasking mode (not in a task window).
  • Each test (other than the WHILE/REPEAT ones) is enclosed in a FOR…NEXT loop, with the index variable running from 1 to 100,000,000. So they are run 100 million times. This was chosen so that an empty loop runs in about 1 second. Other than tests 3, 4 and 6, the index variable is an integer.
  • The description specifies what operation is inside the loop.
  • All timings are in seconds with centisecond resolution, other than the total time which is in minutes:seconds.
  • The “Assignment a%=long…” tests are done because I often use systematic prefixes for variable names, and I wondered if having many variable names with identical prefixes would slow things up. The testing program defines 300 variables called “VeryLongVariableNameWithIncrementingSuffix001%” to “VeryLongVariableNameWithIncrementingSuffix300%”.

Test BASIC V BASIC VI VFP BASIC VI FPA
Empty FOR loop (int) 0.97 1.02 0.98
Empty FOR loop (int, no spaces) 1.01 1.15 1.00
Empty FOR loop (real) 3.09 1.11 65.07
Empty FOR loop (real, no spaces) 3.10 1.10 65.05
Empty FOR loop, NEXT I% (int) 3.02 3.04 2.97
Empty FOR loop, NEXT I (real) 5.12 3.76 67.05
Assignment A%=100 4.17 4.13 23.61
Assignment a%=100 4.14 4.14 30.69
Assignment a%=b% (100) 4.39 4.39 23.63
Assignment a=0.5 4.19 4.02 53.65
Assignment a=b (0.5) 4.89 3.82 53.78
Assignment a%=Very…x001% 4.38 4.39 23.63
Assignment a%=Very…x300% 4.39 4.39 23.62
Integer maths a%=b%+c% (100+50) 6.62 6.63 26.16
Integer maths a%=b%-c% (100-50) 6.62 6.63 26.26
Integer maths a%=b%*c% (100*50) 6.78 6.78 26.28
Integer maths a%=b%/c% (100/50) 16.47 8.44 181.51
Integer maths a%=b%DIVc% (100DIV50) 7.96 7.62 27.55
Real maths a=b+c (0.5+0.2) 7.93 5.85 154.60
Real maths a=b-c (0.5-0.2) 8.43 5.88 135.51
Real maths a=b*c (0.5*0.2) 7.90 5.85 134.98
Real maths a=b/c (0.5/0.2) 17.88 6.69 171.36
Real maths a=b^c (0.5^0.2) 46.09 90.33 1651.64
Real maths a=SQRb (0.5) 15.96 5.40 103.40
Trig a=RADb (0.5) 6.24 4.52 85.88
Trig a=SINb (0.5) 19.28 46.44 768.88
Trig a=COSb (0.5) 28.86 47.25 794.56
Trig a=TANb (0.5) 26.89 74.45 757.27
WHILE loop (int, I%=I%+1) 10.89 10.80 31.46
WHILE loop (int, I%+=1) 9.39 9.38 9.38
REPEAT loop (int, I%=I%+1) 11.58 11.16 32.17
REPEAT loop (int, I%+=1) 9.52 9.49 9.52
Total (m:s) 5:18 6:50 92:43

Takeaways

  • BASIC VI FPA is slow. If you run the test program be prepared to cook and eat your dinner while it shuffles along. And possibly include a nap.
  • I’m puzzled why integer operations under BASIC VI FPA are so slow; I wasn’t expecting these to vary much. Addition, subtraction, multiplication and the DIV operator are about 4 times slower than BASIC V. Using / to divide is even worse, 11 times slower. And even simple integer assignments are about 6 times slower.
  • Note that using a real variable as the index in a FOR…NEXT loop in BASIC VI FPA is twenty times slower than BASIC V (and over sixty times slower than BASIC VI VFP).
  • Don’t use variables after NEXT; it’s three times slower, and they’re very rarely needed. This can make a considerable difference for nested FOR loops.
  • I’ve done both “A%=” and “a%=” assignments to check if so-called ‘resident integer variables’ (A% to Z%) still give a speed benefit. But it seems there’s no advantage now to using them.
    Ancient history note: this feature dates back to the Acorn Atom (my first computer back in 1980 — I soldered it together!), when A-Z were the only variables you had (integer only); if you wanted more you had to use arrays (just AA to ZZ) or indirection. BBC BASIC evolved from Atom BASIC — indeed, you could get it on the Atom as an add-on board — and the resident integer variables on the BBC Micro’s original BASIC were a legacy.
  • The long variable name tests don’t appear to make much difference. But it turns out that both versions use a fairly sophisticated caching strategy for variable names, so this isn’t really a valid test. I’d be interested to know if the same strategy is used for procedure/function names (which I haven’t tested here).
  • Integer maths is pretty much identical between BASIC V and BASIC VI VFP, with the exception of division which is twice as fast in BASIC VI VFP.
  • Simple real maths is faster in BASIC VI VFP than BASIC V, by about 25-30%; again, division is twice as fast. It’s interesting that BASIC VI VFP’s real maths operations are slightly faster than their integer equivalents. Of course, different values may give a different result.
  • Square root — a common operation — is three times faster in BASIC VI VFP.
  • Avoid exponentiation if you can — it’s a very expensive operation, in all versions.
  • I was a bit surprised that BASIC VI VFP’s trig functions weren’t better. Although they are, of course, much more accurate.
  • Using += and -= to increment/decrement variables gives a small but useful speed increase, particularly under BASIC VI FPA.

Conclusion

No, it wouldn’t really be worth Gradgrind using BASIC VI VFP. For much of the real arithmetic involved I’ve used pre-calculation, and the speed increase would be minimal.

Downloads

Download the program from the Downloads page.

Gradgrind update

Sunday, November 16, 2025
mainwindow6.png

Gradgrind has been updated to 0.92beta, with new features and a number of important bug fixes.

New features include the ability to import/export GIMP palettes, modify palette files in more ways, and an extra display for the palette.

Download directly, or see the Downloads page for full details of the changes.

Gradgrind is a RISC OS program. It will not run under any other OS.

More Work on !Solar

Friday, October 17, 2025

I’ve been adding a display mode to my solar panel analysis program to show the monthly variation in output. It shows the anomaly in percentage terms against the average output for the month. Here are the results for 2012 to May 2025:

Special2P2.webp

Each vertical line represents a month. The very bad result for April 2016 (the line would extend below the graph) is due to the panels being offline for half the month while our roof was replaced. And May 2025 is bad because only the first 10 days are being counted.

It’s interesting to compare this with the following graph, courtesy of the Met Office:

2024_Sunshine_Anomaly_1991-2020.webp

Source:https://www.metoffic … shine-anomaly-graphs
(Select the “Sunshine” option, and “2024” from the drop-down list.)

This shows the sunshine recorded over the whole country for 2024, broken down into regions. Now 2024 was our worst year so far for the panels — it was even worse than 2012, the so-called “year without a summer”.

Look at the 2024 section in the top graph, and note how the only above-average months, coloured orange, were January, June and December. (And even very good results for winter months make very little difference to the yearly figures — we can generate more power in one summer day than the whole of December or January).

Now look at the lower graph, the England results (also in orange). The figures here — remembering they’re for the whole country — are in pretty good agreement, with January and June being the only above-average results in the first half of the year. They disagree about August, which was slightly above average, and December, which was well down for England as a whole. We did better here in Yorkshire, about 9% above average.

WebP on RISC OS

Thursday, October 9, 2025

About WebP

WebP — capitalised thusly — is a graphics format developed by Google intended as a replacement for JPEG, PNG and GIF formats; most modern browsers can handle WebP images. The format supports both lossy and lossless compression, as well as animation and an alpha channel. WebP files may contain metadata (in ICCP, EXIF or XMP formats) such as a thumbnail image and technical details such as the camera settings used.

WebP was first fully released in 2018, and since then has been getting progressively more widespread on the web. It claims to have various advantages over previous formats, chiefly in reduced file size (though there is criticism regarding fidelity). The following table shows how its usage on the web has been increasing, expressed as the percentage of websites which use the format:

2020 2021 2022 2023 2024 2025 (Jan) 2025 (Oct)
0.2% 0.5% 3.0% 6.5% 10.8% 14.9% 17.9%

[Source: https://w3techs.com/ … w/image_format/all/y ]

WebP on RISC OS

The WebP format is now fairly well supported on RISC OS, at least for still images. PhotoDesk (3.23) can load and save them, and there are the free stand-alone conversion applications Spr2WebP and WebP2Spr courtesy of Richard Coleman, who did the hard work — see Links section below. It’s also been reported that the RISC OS port of ImageMagick 7 can be used to convert WebP files to and from sprites.

RISC OS web browsers which can render static WebP images include NetSurf and Iris.

Animation support is much more limited. As far as I know no-one has ported Google’s img2webp to RISC OS; this can produce animations from a sequence of still images. There are however various online converters.

On RISC OS, the Iris browser can render animated WebP files, but NetSurf can’t.

WebP files have an official filetype of &a66, with type name WebP. The extension is “filename.webp”, and the details should be included in your mimemap file. To check:

  • Open a task window (Ctrl-F12)
  • Type:
    mimemap webp

    If you see the message “No MIME mapping found” you need to add it as follows:

  • Type:
    filer_run inetdbase:mimemap
  • Your system’s mimemap should open in an editor window
  • Look for the “image”+”IANA registered” section, and add the following line (the gaps are tabs):
    image/webp	WebP	a66	.webp
  • Save the file; the setting will take effect after the next boot

Examples

I’m using a couple of images to demonstrate WebP. The flowers picture is a 1280×1280 detail from a photo taken in Zambia by a Canon Ixus, so originally a JPEG. The screengrab image (732×714, 24-bit RGB) is from my in-progress app for reporting on our solar panel installation. These were saved as sprites (which is lossless, of course), and then converted into various formats using various apps and settings.

NB: The images below (in WebP format — if you can’t see them your browser doesn’t support the format) are not the actual images used, they’ve been resized and are just for reference. You can download the original sprite files in the Links section below.

flowers-sm.webp
solar-sm.webp
File sizes for flowers image
Format Size (bytes)
Sprite 6,553,656
JPEG (90) 346,795
JPEG (75) 190,146
WebP (Photo) 105,760
WebP (Lossless) 1,632,468
PNG (Paint/Spr2Png) 2,112,447
PNG (PhotoDeskA) 6,566,686
PNG (PhotoDeskB) 3,053,488
File sizes for screengrab image
Format Size (bytes)
Sprite 2,090,648
JPEG (90) 164,906
JPEG (75) 117,820
WebP (Picture) 45,638
WebP (Drawing) 47,360
PNG (Paint/Spr2Png) 73,579
PNG (PhotoDeskA) 2,095,393
PNG (PhotoDeskB) 117,389

The WebP conversions were done with Spr2Webp, using the settings of Photo and Lossless (for the flowers) and Picture and Drawing (the screengrab). You can also use PhotoDesk, but this uses the same code as Spr2Web so the sizes are pretty much identical. Lossless takes longer (but you’ll usually only need to do it once).

The JPEGs were done with Paint, with the quality settings in parentheses.

The PNGs of the flowers are provided for interest only, as you wouldn’t normally save a photo in this format. Paint and Spr2Png produce identical output, with compression set to 9 in both cases. Paint uses RISC OS’ internal PNG library, while Spr2Png has its own converter.

Of more interest are the PNG entries for PhotoDesk. The first, labelled “PhotoDeskA”, uses the default settings when saving a PNG from PhotoDesk, and they are actually larger than the sprite, possibly due to being interlaced. The second (”PhotoDeskB”) has the settings tweaked. This isn’t straightforward, as the save box doesn’t include any options to change parameters. You have to shift-click on the !PhotoDesk app to open it, then on “Resources”, then on “Formats”, then shift-click on “!3PNG”. Open the directory “Options”, then load “spr2png” which should contain just the text “-ia” (without the quotes). Change this to “-ia9” — the “9” increases compression — and save. Doing this improves the compression markedly, though still not as good as Spr2Png. You could probably improve things more by modifying the options; PhotoDesk’s PNG library is very similar to that used by Spr2Png. Or more simply, as PhotoDesk appears to perform negative compression on PNGs, save as a sprite and drop the icon on Spr2Png. Or load it into Paint and save as a PNG from there.

Summary

It’s quite hard to see much visual difference between these images, with the exception of the JPEG (75) version of the screengrab, where artefacts are visible in colour transitions.

For photographs, WebP in Photo mode is the most efficient, for both lossy (JPEG equivalent) and lossless transmission/storage.

For line drawings or screengrabs use WebP with Picture or Drawing presets.

If you need maximum portability under RISC OS, especially legacy versions, JPEG and PNG are still the best options.

Links

WebP on Google, on Wikipedia
Richard Coleman’s conversion apps (webp2spr, spr2webp and webpinfo, along with desktop front ends)
Darren Salt’s Spr2Png and Png2Spr apps
PhotoDesk is available via the !Store app
Example images as used above (4Mb zipped sprites)

Gradgrind Update

Monday, September 22, 2025

The Gradgrind palette editor for RISC OS has been updated, with a minor bug fix for hex display of colour values.

Download link: Gradgrind 0.91 beta (326k)

Work in progress: !Solar

Saturday, September 20, 2025
ctrl.png

We’ve had solar panels for nearly 14 years now, and the output has been reported daily on our site. The page is currently generated by a Python program running on a Raspberry Pi (a Pi400 at the moment), but I’ve been working on a version running under RISC OS, using BBC BASIC. Here are some samples of the output:

month2024-06-01.png
month2024-07-01.png
day2025-05-01.png
Special2b.png

It’s unfinished as yet, but work continues slowly…