So what was your first program? You know, the first one that meant anything.
My guess is that when you unwrapped your first home computer (mine was a Sinclair Spectrum 48K) the lines of code you typed were little more than snippets – changing some colours on the display, perhaps, or making rude words scroll endlessly down the screen. You may even have progressed to something like:
INPUT "What is your name?", N$ PRINT "Hello ",N$
Then you started looking around for something a little more meaningful. I’m a photographer, in addition to my other sins, and at the time I got my Spectrum I was a section editor on a weekly publication called The Photo. It was a partwork (a magazine that builds into an encyclopaedia) and I was responsible for running the technical sections. So naturally I searched for something photographic that needed computing.
And depth of field turned out to be the ideal candidate. If you’re not into photography, depth of field defines how much of the scene in front on the camera is in focus, in terms of distance from the lens. The point where you’ve focused the lens is obviously sharp, but a region either side will look in-focus too. This has to do with ‘circles of confusion’ (one of my favourite photographic terms). In brief, a point of light that isn’t in focus will form a circle (well, actually a disc, but let’s not quibble) instead of a sharp point. You can clearly see this in areas of the image that are way out of focus – it’s what gives rise to that effect often referred to by that godawful word ‘bokeh’.
However, if the disc is sufficiently small, your eye won’t be able to tell it apart from a point that is fully in focus. How small is small? That depends. In the days of plate or medium-format cameras the maximum size was considered to be 0.05mm (that’s the size of the circle of confusion in the image being formed on the film). For 35mm systems, this was commonly reduced to 0.033mm or 0.03mm. And pernickety people might insist on reducing this to 0.025mm.
The other factors that affect depth of field are the focal length of the lens, the aperture (f-stop) selected and the distance from the lens to the main point of focus. The shorter the focal length or smaller the aperture, the more depth of field. That’s why, on smartphones, pretty much everything in the image is in focus, because they have incredibly short focal length lenses.
There’s another handy phenomenon connected to all this – hyperfocal distance. In most of the technical literature this is defined as being the closest distance from the lens that is rendered acceptably sharp (ie, it’s the closest limit of depth of field) when the lens is focused at infinity.
In practical terms, most photographers understand it slightly differently. It’s the closest distance at which you can focus the lens so that everything from there to infinity is kept sharp by depth of field. In fact, everything from half that distance to infinity will be sharp. This is a handy thing to know because in fast-moving situations, such as a news or documentary photographer might encounter, you can set the focus ring to the hyperfocal distance for the aperture you’re using and shoot away, letting depth of field take care of keeping things in focus. (This was, of course, in the days of manual-focus lenses.)
In case you’re wondering, the difference between a hyperfocal distance calculated using the text book definition and one based on the practical application is very small.
You don’t need to calculate this: lenses always used to have focus scales with depth of field markings for various apertures. You could just set the infinity symbol against one of these marks and that was the hyperfocal distance set.
But, dammit, I was looking for something to compute.
Luckily, I had a copy of ‘The Photographic Lens’ by Sidney Ray. In fact, Sidney was one of our key contributors on The Photo, a charming man who I relied on for technical insights. And the book contains the necessary formulae for calculating depth of field and hyperfocal distance. I still have that book.
And so that was my first real program. I hacked it together on the Speccy and even used the results to publish some tables in The Photo.
Then, when I graduated from the Spectrum to a BBC Micro Model B, the first thing I did (aside from displaying rude words) was re-create this program.
My original copies are long gone, of course. But I was playing around with the BeebEm emulator, running on a Windows VM on my iMac (is that enough layers of abstraction for you?) and thought, why not rewrite that program?
Why not indeed.
I was a little easier this time around. I was using an emulated BBC Master with the Basic Editor ROM installed. It’s not exactly Sublime Text but *BE was a revelation when it first came out.
I decided to write as much of the program as I could from memory – not of the original program but of BBC Basic. It was surprising how much came back, but I confess I had to resort to the manual fairly quickly. It reminded me, though, how good BBC Basic was (and still is), not least in its structured nature. I mean, named procedures and functions with parameters on an 8-bit home micro from the early 1980s? It’s impressive.
The program below is nothing like my original. I have a vague memory that, back then, the program printed out a table with one axis being focus distances (like this new program) and the other axis being apertures. Each cell contained the minimum/maximum limits of depth of field. Also, I think the original asked you to enter details (focal length, depth of field and circle of confusion), then printed the table. There was a cursor line to make it easier to read across the table – I was very proud of how you could move this line up and down with the cursor keys – but it was actually somewhat pointless. But if you wanted to change, say, the focal length you had to end the program and start again.
This time around, there’s a main program loop and a menu allowing you to change any of the four main parameters, which include a focus distance.
The program then displays the depth of field for that combination of factors, the hyperfocal distance for that lens/aperture combination and a table of depths of field for various focus distances. The figures look sensible, so I think it’s working okay. And it was fun. Here’s the code, for what it’s worth:
REM >DOF REM Depth of Field Calculator MODE 3 REM --- MAIN GLOBALS --- flen% = 50 : REM focal length, mm fstop = 8.0 : REM aperture circ = 0.033 : REM circle of confusion, mm dist = 5.0 : REM focus point in meters DoFnear = 0.0 DoFfar = 0.0 hyperfocal = 0.0 REM --- Set up distance index for table --- distances% = 17 : REM max index for dists array DIM dists(distances%) FOR I% = 0 TO distances% READ dists(I%) NEXT REM --- Main Loop --- done% = FALSE REPEAT CLS PROCdisplay sel$ = CHR$(FNmenu) IF sel$ = "Q" THEN done% = TRUE IF sel$ = "A" THEN fstop = FNsetparam(sel$) IF sel$ = "C" THEN circ = FNsetparam(sel$) IF sel$ = "D" THEN dist = FNsetparam(sel$) IF sel$ = "F" THEN flen% = FNsetparam(sel$) UNTIL done% = TRUE CLS END REM distances for table DATA 0.5,0.7,1,1.5,2,3,4,6,8,12,15,25,30,50,75,100,150,200 DEF FNsetparam(ch$) CLS IF ch$="A" THEN prompt$="aperture":min = 1:max = 130:default=fstop IF ch$="F" THEN prompt$="focal length":min=8:max=1000:default=flen% IF ch$="C" THEN prompt$="circle of confusion":min=0.025:max=0.05:default=circ IF ch$="D" THEN prompt$="subject distance":min=0.1:max=1000:default=dist prompt$ = "Enter " + prompt$ PRINT TAB(5,6);prompt$ INPUT TAB(LEN(prompt$) + 6,6);">"param result = param IF param < min THEN result = min IF param > max THEN result = max IF param = 0 THEN result = default =result DEF PROCdisplay PROCcalc(dist) PROChyper @% = &01000006 PRINT TAB(1,0);"Focal Length: "; flen%; "mm" @% = &01000004 PRINT TAB(23,0);"Aperture: f/"; fstop @% = &01020105 PRINT TAB(41,0);"Subj Dist: "; dist; "m" @% = &01020305 PRINT TAB(67,0);"CoC: "; circ; "mm" @% = &01020106 PRINT TAB(1,1); "DoF Near: " ; DoFnear ; "m" PRINT TAB(23,1); "DoF Far: " ; FNfarstr(DoFfar) PRINT TAB(41,1); "Hyperfocal distance: "; hyperfocal; "m" PRINT TAB(13,2); "dist"; TAB(26,2); "near"; TAB(41,2); "far" PRINT TAB(13,3); "----"; TAB(26,3); "----"; TAB(40,3); "----" FOR I% = 0 TO distances% PROCcalc(dists(I%)) @% = &0100003 PRINT TAB(13,4+I%), dists(I%); "m" @% = &01020106 PRINT TAB(23,4+I%)DoFnear;"m" fardist$ = FNfarstr(DoFfar) PRINT TAB(38,4+I%); SPC(6-LEN(fardist$)); fardist$ NEXT ENDPROC DEF FNfarstr(far) IF far > 0 THEN far$ = STR$(far)+"m" ELSE far$ = "-inf-" =far$ DEF PROCcalc(dst) fdist = dst * 1000 : REM work in mm fact = fdist * circ * fstop DoFnear = fdist / (1 + (fact / flen% ^ 2)) DoFnear = DoFnear / 1000 DoFfar = fdist / (1 - (fact / flen% ^ 2)) DoFfar = DoFfar / 1000 ENDPROC DEF PROChyper hyperfocal = ((flen% ^ 2 / (circ * fstop)) + flen%) / 1000 ENDPROC DEF FNmenu PRINT TAB(1,23);"(F)ocal length : (A)perture : (D)istance : (C)ircle of Confusion : (Q)uit" opt% = FALSE REPEAT key% = INKEY(0) REM convert to uppercase if necessary key% = key% AND &DF IF key%=65 OR key%=67 OR key%=68 OR key%=70 OR key%=81 THEN opt%=TRUE UNTIL opt% = TRUE =key%
[UPDATE 11/09/2018] I used Mode 3 in the program above because … well, I had a vague memory of always using that mode. (Or Mode 131 on the Master.) I never much liked squeezing the output from programs into a 40 character-wide screen, and never used the Beeb’s 20-character modes. I didn’t program (or play) games and had a limited need for colour.
But I was surprised when recreating my program how few lines of text were available. And that’s because I’d got a bit confused.
Mode 3 on the Beeb was really intended for communications. It’s a non-graphic mode that gives the 80 x 25 character display needed to match various terminal standards. But I think I mostly used it because it’s just slightly less memory-hungry than the other 80-column mode, Mode 0. In Mode 0 (and also Modes 1 and 2) you lost 20K of the Beeb’s alleged 32K to display memory, so nominally just under 12K left over for your program (and actually somewhat less because of OS requirements, so more like 9K). In Mode 3, you clawed back another 4K for program space.
Even when I upgraded to the BBC Master 128, with its shadow memory making such considerations obsolete, I tended to carry on with that mode (now Mode 131) just out of habit.
But my depth of field program doesn’t require even as much as 12K. Switching to the 80×32 character display of Mode 0 gives me a bit more room to play with.
[UPDATE 12/09/2018] The programs (80- and 40-column versions) are now running on an actual Beeb. I transferred them to my recently fixed BBC Master 128. And this was much easier than it had any right to be thanks to my recent acquisition of a RetroClinic DataCentre. But I think I’ll make that the subject of another post.