RFC 809

UCL facsimile system

๐Ÿ“… published February 1982, from ietf

RFC 809: UCL FACSIMILE SYSTEM ๐ŸŽ€

Bestie, the title block is giving very important vibes. The author is Tawei Chang โœจ, and the paper was written in the Department of Computer Science at University College London. It's an INDRA Note (1185) and is listed as a Working Paper, dated Feb. 1982. The original doesn't list anything it obsoletes or updates, so there's nothing to report there ๐Ÿงš


ABSTRACT: okay so this note is all about the computerised facsimile system the Department of Computer Science at UCL built ๐Ÿ’– First it looks at what the system can do and the experiments that went with it. Then it talks about the design rules it followed. Last, it covers how the system was actually implemented, and the full details live in the appendices ๐Ÿซถ


NOTE: ๐Ÿ“Ž Figures 5 and 6 are available if you email a request to Ann Westine at USC-Information Sciences Institute, 4676 Admiralty Way, Marina del Rey, California, 90291 (or WESTINE@ISIF). Include your name and postal mailing address, and say you want figures 5 and 6 from RFC 809.

OR: ๐Ÿ’ป you can grab both figures online from these files on the SRI-NIC online library:

<NETINFO>RFC809a.FAX   and   <NETINFO>RFC809b.FAX

These files use the format described in RFC 769.


Here's the contents, bestie ๐Ÿ“š

Contents

  1. INTRODUCTION...........................................1


  2. SYSTEM FUNCTIONS.......................................2

     2.1 Communication......................................4
     2.2 Interworking with Other Equipment..................8
        2.2.1 Facsimile machines............................8
        2.2.2 Output Devices................................9
     2.3 Image Enhancement..................................11
     2.4 Image Editing......................................15
     2.5 Integration with Other Data Types..................16

  3. SYSTEM ARCHITECTURE....................................17

     3.1 System Requirements................................17
     3.2 Hierarchical Model.................................19
     3.3 Clean and Simple Interface.........................20
        3.3.1 Principles....................................21
        3.3.2 Synchronisation and Desynchronisation.........21
        3.3.3 Data Transfer.................................22
     3.4 Control and Organisation of the Tasks..............22
        3.4.1 Command Language..............................23
        3.4.2 Task Controller...............................23
     3.5 Interface Routines.................................26
        3.5.1 Sharable Control Structure....................26
        3.5.2 Buffer Management.............................27

  4. UCL FACSIMILE SYSTEM...................................28

     4.1 Multi-Task Structure...............................29
     4.2 The Devices........................................29
     4.3 The Networks.......................................30
     4.4 File System........................................31
     4.5 Data Structure.....................................32
     4.6 Data Conversion....................................34
     4.7 Image Manipulation.................................35
     4.8 Data Transmission..................................39

  5. CONCLUSION.............................................41

     5.1 Summary............................................41
     5.2 Problems...........................................42
     5.3 Future Study.......................................46
     Appendix I:   Devices

     Appendix II:  Task Controller and Task Processes

     Appendix III: Utility and Data Formats

     Reference

1. INTRODUCTION โœจ

Okay, so the whole point of a facsimile system is to copy a document or image faithfully from one piece of paper onto another piece of paper that's sitting somewhere else ๐Ÿ“„๐ŸŒธ For a long time, the main way to do fax has been over the telephone network. The thing is, most fax machines can't store a page or edit it before sending, and it's almost impossible for different brands of fax machine to talk to each other ๐Ÿ˜ญ Honestly, fax machines are way behind other electronic communication services, and it's not a good look.

Connecting fax to computer communication techniques makes a huge difference ๐Ÿ”ฅ It isn't just about reliability and efficiency, though that's a win too. The really iconic part is that the computer lets a fax machine plug into a full message and information processing setup ๐Ÿ’… The computer's storage can hold tons of fax data and bring it back super fast. Data conversion lets different types of fax machines communicate with each other. And the fax image can be edited or combined with other kinds of data, like text, voice and graphics, to build a multi-media message that can be spread far and wide over computer networks ๐Ÿฆ‹

So in the Department of Computer Science at UCL, they built a computerised facsimile system to put computer technology, especially communication, to full use in the fax world ๐Ÿ’– They've already done some work to improve fax service in several areas:

  1. Adaptation for computer networks. The fax machine can be used with computer networks. This makes document transmission more reliable and accurate, and it also improves normal point-to-point transfers โœจ
  2. Storage of fax pages. Pages can be queued, which saves operator time. Standard documents can also be kept permanently and sent whenever you want ๐Ÿงš
  3. Interworking with other fax machines. Different makes of fax machine can swap images with each other ๐Ÿซถ
  4. Compression of fax images. This allows more efficient transmission. Different compression schemes are being investigated ๐ŸŒˆ
  5. Display of images on other devices. A colour display shows the result of image processing very vividly ๐ŸŒˆ
  6. Improvement of images. The ability to "clean" fax images allows for an even higher compression ratio, and it also gives a better result at the destination ๐Ÿ’…
  7. Editing of fax pages. You can change pictures, resize images and merge two or more images, all electronically ๐ŸŽ€
  8. Integration with other data types. For now, coded character text can be converted into fax format, and mixed pages containing pictures and text can be manipulated ๐Ÿ‘‘

This note first looks at what the facsimile system can do, and it covers the related experimental work too ๐Ÿ“ Then it discusses the design discipline behind the system. Finally, it describes how the UCL facsimile system was implemented. The appendices give the detailed description of the system, namely:

  • I. Devices
  • II. Task controller and task processes
  • III. Utility routines and data format

2. SYSTEM FUNCTIONS โœจ

The computerised facsimile system is built around an LSI-11 micro-computer running the MOS operating system [14], with two AED62 floppy disk drives [17], a Grinnell colour display [18], a DACOM facsimile machine [16], and a VDU as the system console ๐Ÿ’ป The LSI-11 is also hooked up to several networks, including the ARPANET/SATNET [21], [22] and the UCL Cambridge Ring. Here's a schematic of the system, shown in Fig. 1 ๐Ÿฆ‹

              facsimile machine  bit-map display
                     +------+    +------+
                     !      !    !      !
                     +------+    +------+
           +------+        \      /        VDU
           ! disk !      +----------+    +-----+
           +------+ ---- !  LSI-11  ! -- !     !
           ! disk !      +----------+    +-----+
           +------+           |
                           +------+
                           !  NI  !
                           +------+
                       Network Interface

            Fig. 1  Schematic of UCL facsimile system

So here's how it works ๐ŸŒธ A page gets read on the fax machine, and the image data it makes is stored on a floppy disk. That data can be processed locally on the micro-computer, then sent to a file store on a remote computer across the network. At the remote site, the image data can be processed and printed on a fax machine.

It also works the other way around ๐Ÿ”ฅ The system can receive image data sent by a remote host on the network, and that data can be handled in exactly the same way, including being printed on the local machine.

Section 2.1 discusses the problems involved in sending fax image data over a network. The sections after it deal with working on image data locally ๐Ÿงš

To interwork with other fax machines, the image data has to be converted from one representation format to another. Interworking with other output devices means the image has to be scaled to fit the size of the destination device. These are covered in section 2.2 ๐Ÿ’…

Being able to process images by computer opens the door to so many possibilities ๐ŸŒˆ First, as covered in section 2.3, an image can be enhanced, which improves its quality and allows for more efficient storage and transmission. Second, a fax editing system can be supported, so a picture can be changed and/or combined with other pictures. This is described in section 2.4 โœจ

Coded character text can also be turned into its bit-map representation, so it can be handled as a fax image and merged with pictures ๐Ÿซถ This gives you an environment where multi-type information can be dealt with, and it's discussed in section 2.5 ๐Ÿ‘‘


2.1 Communication ๐ŸŒˆ

The first goal of the computerised facsimile system is to use a computer network to send data between fax machines that are geographically separated ๐Ÿ’–

Normally, fax machines are used with telephone equipment, and the data travels over telephone lines ๐Ÿ“ž Putting fax machines on a computer network is a bit of a problem, though, because a fax machine can't use a computer network directly ๐Ÿ˜ญ A computer is needed to handle the network tasks, so the first phase was to attach the fax machine to a computer. ๐Ÿ’…

We had to build a special hardware interface so the fax machine could talk to a small computer ๐Ÿ’… This interface was made to look exactly like the telephone system to the fax machine. The computer was also programmed to act exactly like another fax machine sitting on the end of a phone line ๐Ÿ“ž So the local fax machine just sent its data to the computer totally happily, thinking it was chatting with a remote fax machine on the other end of a phone wire. ๐Ÿงš Because of the property of the DACOM 6450 used in the experiment [16], the interface could be identical to one built for connecting to an X25 network. The binary synchronous mode of the chip used (SMC COM5025) was perfect for driving the DACOM machine ๐Ÿ”ฅ

On the other side of the computer network there was a similar computer with an identical fax machine. ๐Ÿฆ‹ Sending a fax picture now looked pretty simple: data got pulled from the fax machine into the computer, zoomed across the network like normal computer data, and then got sent from the computer to the fax machine at the far end โœจ The data on the network looks exactly like any other computer data. There is nothing special about it that shows it came from a fax machine ๐Ÿ™ˆ The schematic for this fax transfer system is in Fig. 2.

facsimile
machine
 +---+  interface
 !   !    +--+    +-----+
 !   ! == !  ! == !     ! computer
 +---+    +--+    +-----+
                     |
                      - - - - - -    computer
                    /             \  network

                    \             /             facsimile
                      - - - - - -               machine
                                 |    interface  +---+
                              +-----+    +--+    !   !
                     computer !     ! == !  ! == !   !
                              +-----+    +--+    +---+

           Fig. 2  Facsimile transfer system

The experimental system was used for a joint experiment between UCL and two groups in the United States ๐ŸŒˆ Pictures were exchanged over the ARPANET/SATNET [21], [22] between UCL in London, ISI in Los Angeles, and COMSAT in Washington D.C. (Fig. 3). This setup was chosen because there was no equivalent group available in the UK ๐Ÿ‡ฌ๐Ÿ‡ง

Okay, now the big problem with picture data is how much of it there is ๐Ÿ˜ญ Even with data compression, a single page of fax data can make as much computer data as you'd need to send over 20,000 alphabetic characters, or over a dozen typed pages ๐Ÿ’€ So for any number of pages put into the system, you get an immense amount of computer data. That means transmission is slower than sending text, and way more storage is needed to hold the data ๐Ÿ“ฆ

Another problem showed up super fast once we actually built this thing ๐Ÿฅฒ The network we were using often couldn't keep up with the speed of the fax machine. When that happened, the computer tried to slow the fax machine down. The fax machine read this "slowness" as a communication problem (a telephone line would never act like that), and it would abandon the transfer halfway through the page ๐Ÿ˜ค

                US               UK
                     satellite
 COMSAT                   __
 +---+    +--+           /  \
 !   ! -- !  !           /  \
 +---+    +--+          /    \
   |          \        /      \
 +---+         \      /        \           UCL
 !fax!          \+--+/          \+--+    +---+
 +---+  ARPANET  !  !   SATNET   !  ! -- !   !
                /+--+            +--+    +---+
               /                           |
 ISI         /                          +---+
 +---+    +--+                           !fax!
 !   ! -- !  !                           +---+
 +---+    +--+
   |
 +---+
 !fax!
 +---+

 Fig. 3. The three participants of the facsimile experiments

Why was this happening? Because the fax machine we used was never meant to be hooked up to a computer ๐Ÿ™ƒ It was designed and built for telephone lines. Totally unaware that it was connected to a computer, the fax machine sent data at a constant rate, and that rate was higher than the network could accept. In other words, the computer network we were using was not designed for the transfer rate we were trying to push through it ๐Ÿšซ

Honestly, both of these problems are fixable โœจ Fax machines are now coming onto the market that are designed to talk directly to a computer ๐ŸŽ€ These machines don't mind the delays on the computer interface, and they're fine with stopping and restarting. Also, if fax machines were going to be seriously used on a computer network, the network could just be designed for the high data rate needed. Our problem got worse because we were using a network that was never designed for the data rates our usage needed ๐Ÿ’–

Even though our problems came from the experimental equipment we were working with, we still had to make things better so we could have bigger, more extensive communications ๐Ÿซถ The easiest fix was to add a local storage area in our computer where the data could be held before transmission ๐Ÿ’œ Now a page gets transferred in three stages. First, the fax data is read from the fax machine and stored on a local disk. This happens at high speed because it's just a local operation ๐ŸŽ๏ธ Once that's done, the data is sent over the network to a disk on the remote computer. Finally, the data on that disk is output to the remote fax machine. This improved system is shown in Fig. 4.

                computer network
 fax    computer    - - - -     computer   fax
+---+   +-----+   /         \   +-----+   +---+
!   ! = !     ! =     ==>     = !     ! = !   !
+---+   +-----+   \         /   +-----+   +---+
   - - - + |        - - - -        | + - - >
         | | + - - - - - - - - - + | |
         | | |                   | | |
         V | |                   V | |
         +---+                   +---+
         !   !                   !   !
         !   !                   !   !
         +---+                   +---+
         disk                    disk

    Fig. 4.  The improved facsimile transfer system

The idea behind this method is to decouple the fax machine from the network communications ๐Ÿง  Data is read from the fax machine at full speed, without the delays the computer network would cause. This also makes it way nicer for the human operators, because each page is now read in less than a minute โฑ๏ธ Transmission over the network then happens at whatever speed the network can sustain. This doesn't affect the fax machines at all, because they aren't involved in the sending or receiving ๐Ÿ™Œ The remote fax machine only gets told the data is ready once all of the data has arrived at the remote disk. Then the fax machine gets the data as fast as it will accept it ๐Ÿ’จ


The downside of this system is that the person sending the pages doesn't know how long it'll take before they're actually printed on the other side ๐Ÿ˜ฌ If the operator inputs several pages in quick succession, they get stored on disk, and it might take a while before the last page is actually delivered to its destination. Honestly, this isn't always a bad thing ๐ŸŒธ When lots of operators are sending data to the same destination, it's a definite win to be able to input pages and have the system deliver them once the destination is free ๐Ÿ‘‘ That's way better than the current telephone system, where the operator has to keep re-dialing the remote fax machine until somebody picks up ๐Ÿ“ž๐Ÿ’€

2.2 Interworking with Other Equipment โœจ

2.2.1 Facsimile machines ๐Ÿ–จ๏ธ

As we mentioned earlier, fax machines produce a huge amount of data per page because of how the pages are encoded ๐Ÿ˜ฉ To cut down on the data that has to be transmitted, various compression techniques are used. Fax machine manufacturers came up with their own proprietary ways of compressing and encoding the data ๐Ÿ”’ Unfortunately, this meant different fax machines couldn't interwork at all ๐Ÿ™ƒ In the system described in the last section, pictures could only be exchanged between sites that had identical fax machines. The new set of CCITT recommendations will reduce how much differences in equipment get in the way ๐ŸŒˆ

Having the data on a computer is iconic because we can manipulate it any way we want ๐Ÿงšโ€โ™€๏ธ For example, we could convert data from the form used by one fax machine into the form another one needs. That means interworking between different types of fax machines can actually happen ๐ŸŽ‰

Developing this system happened in two stages: decompressing the fax data from the coded form used by our machine into an internal data form, and then recompressing the internal form into the encoded form the destination machine needs. Two programs were written to do these two operations ๐Ÿ’ป

At the same time, we were developing compression and decompression programs for machines that use other techniques ๐Ÿฆ‹ In particular, we developed programs to handle the recently approved CCITT recommendation for facsimile compression [15]. The CCITT came up with two varieties of compression, depending on the resolution being used. ๐Ÿ’–

Unfortunately, bestie, there were no facsimile machines on the network that use the CCITT compression technique ๐Ÿ˜ญ. The new methods still gave us two big wins ๐ŸŽ€. First, it proved the data could be converted inside a small computer, so machines of different types could be supported on the network โœจ. Second, it let us compare the compression results. You can read the details in [13] ๐Ÿ“š.

Essentially, these showed that the DACOM technique our facsimile machine uses is comparatively poor ๐Ÿ™ˆ. Considerably less data needs to be transmitted if some other method is used ๐Ÿ’–. This brings up another possibility: we could change the compression of the data to reduce the volume for transmission, then change the data back again at the destination ๐Ÿฆ‹. This may save considerable transmission time, especially if fast computers or special hardware are easily available ๐Ÿš€. It hasn't been tried in our system yet, because none of the other users on the network can change the data format back into what their machines require ๐Ÿ’€.

There are lots of other, more efficient compression schemes, e.g. block compression [7] and predictive compression [8] ๐Ÿง . We just haven't incorporated them into our system yet ๐ŸŒธ.

2.2.2 Output Devices

One area we've explored is using devices other than facsimile machines to output the data ๐Ÿ‘‘. Facsimile machines are both expensive to buy and relatively slow to operate ๐Ÿ˜ฉ. So we looked into a TV-like screen to display the data, just like character VDUs are commonly used to show text ๐Ÿ“บ. This needs bit-map displays, with an address in memory for each position on the screen ๐Ÿ’œ. Full colour and multiple shades can be used too, as long as the bit-map storage is appropriately large ๐ŸŒˆ. It's simple in principle, but actually getting the techniques working took considerable effort ๐Ÿ˜ค.

The problems come from the way the facsimile image is encoded ๐Ÿ™ƒ. Raw facsimile images are rows of small dots, each one recorded as a black or white space. When they're arranged together, they build up a picture, kind of like how a newspaper picture is made ๐Ÿ—ž๏ธ. The catch is that the number of dots on a facsimile page isn't the same as on most screens ๐Ÿ˜ฌ. For instance, the DACOM facsimile machine uses 1726 dots across each page, but a screen usually has just 512 dots across ๐Ÿ“. So to show the picture on screen, the 1726 dots have to be squeezed into just 512 dots. Put another way, 1214 dots must be thrown away without losing the picture ๐Ÿ˜ฑ!

It's reducing the number of picture elements that causes the trouble ๐Ÿ˜ญ. We could just keep every third dot or so from the facsimile page and display only those. Or we could take three or more at a time and try to convert the group into a single black or white dot. Unfortunately, in both cases, data can get lost that is necessary to the picture ๐Ÿ’”. For example, a facsimile encoding of an architect's drawing could easily end up with a complete line removed, totally changing how the image looks ๐Ÿ—๏ธ.

After lots of experimenting, we came up with a method for reducing the number of dots without destroying the picture ๐ŸŽ‰. It's a thinning technique, where key elements of the picture are thinned but not removed โœจ. Sometimes, when the detail gets too fine, some elements get merged. But in those situations, the eye wouldn't have been able to see that detail anyway ๐Ÿ‘€. The details of this technique are described in [3] and [4] ๐Ÿ“–.

It may also be required that a picture be enlarged ๐Ÿ”. This can be done by simply duplicating each pixel in the picture. For a non-integral ratio, the picture can be expanded up to the nearest integer and then shrunk to the correct size ๐Ÿ“. However, this method may degrade the image quality. For example, the oblique contour may become stepped, especially when the picture is enlarged too much ๐Ÿ˜ต. This problem can be solved with an iterative enlargement algorithm ๐Ÿช„. Each time a pixel is replaced with a 2x2 array of pixels, and the pattern of that array depends on the original pixel and the pixels surrounding it ๐Ÿงฉ. This procedure is repeated until the requested ratio is reached ๐Ÿ”. If the ratio is not a power of 2, the same method as the one for non-integral ratios is used ๐Ÿ’….

As a side effect of developing this technique, we could freely change the size and shape of an image ๐Ÿฅณ. The picture can be expanded or shrunk, or it can be distorted. Distortion, where the horizontal and vertical dimensions of the image are changed by different amounts, is often useful in image editing ๐ŸŽจ.

This ability to change the image size meant we could display the image on a screen as well as output it on a facsimile machine ๐Ÿ–ฅ๏ธ. For a user of a computerised facsimile system, this is a super useful feature ๐Ÿ’–. Images can be displayed on screen much faster than on a facsimile machine, and displays are significantly cheaper than facsimile machines too ๐Ÿค‘. An installation could have lots of screen displays where the image can be viewed, but maybe only one facsimile machine for hard copy ๐Ÿ–จ๏ธ. It's kind of like how many computer setups today have limited printers because of their cost, while display screens are way more numerous ๐Ÿ’ป.


2.3 Image Enhancement

One thing we really wanted to investigate was image enhancement ๐ŸŒŸ. Enhancing an image is a very tricky operation. As the name implies, it means the image is improved in some sense ๐Ÿซ . But under program control, this is hard to achieve: what the program thinks is an improvement, a human might judge to be distinctly worse ๐Ÿ™…โ€โ™€๏ธ.

Our enhancement attempts were aimed especially at printed documents and other forms of typed text ๐Ÿ“„. The experiment was double pronged: we hoped to make the image easier for humans to read, while also making it easier for the computer to handle ๐Ÿง ๐Ÿ’•.

In our earlier experiments, we'd noticed that the encoding of printed matter was often very poor ๐Ÿ˜–. This was especially noticeable when we enlarged an image. Instead of each character having smooth edges like the original document, the edges were very rough. Unexpected notches and excrescences were caused by the facsimile scanner ๐Ÿ™€. They not only degrade the image quality, but also decrease the compression efficiency. A typical enlargement of several characters is shown in Fig. 5 ๐Ÿ‘‡.

Fig 5. An enlargement of an typed text

The enhancement method we adopted was first employed at Loughborough University [5] ๐ŸŽ“. This method smooths the edges of the dark areas on the image โœจ. The technique considers each dot in the image in turn. The dot is either left as it is, or changed to the opposite colour (white to black or black to white), depending upon the eight dots that surround it ๐ŸŽฏ. The particular pattern of surrounding dots that is required to change the inner dot's colour controls the harshness of the algorithm [6], [8] ๐ŸŒถ๏ธ.

In our first set of experiments, the result was definitely worse than the original ๐Ÿ˜ฌ. Square-like characters such as H, L, and T came out very well ๐Ÿ™Œ. But anything with a slope (M, V, W, or S) became so bad that the oblique contours were stepped ๐Ÿ’€. The method was then modified to produce a result that was far more acceptable. The image looked a lot cleaner than the original ๐Ÿงผ. Fig. 6 shows the same text as Fig. 5, but after it has been cleaned โœจ.

Fig. 6 A cleaned text

The effect of these can be hard to see clearly ๐Ÿ‘“. So we used the colour on our Grinnell display to show the original picture and the outcome of various picture processing operations, superposed in different colours ๐ŸŒˆ. This brings out the effect of the operations very vividly ๐Ÿคฉ.

It was mentioned above that the enhancement was done not only to improve the image for reading, but also for easier processing by the computer ๐Ÿ’ป. As described earlier, the image from the facsimile machine is compressed in order to reduce the amount of data. The cleaning allows a higher compression rate, so more efficient transmission and/or storage can be achieved ๐Ÿ™Œ.

We learned some important lessons from the enhancement exercise ๐Ÿ“. Originally, we thought the main attraction of enhancement would be improving readability. In the end, we found that improving readability was very difficult, especially because the facsimile image was so poor ๐Ÿ˜ญ. Instead, we found that reducing the compressed output was more important ๐Ÿ’…. By reducing the data to be transmitted by a quarter, significant savings could be made ๐Ÿค‘. But before such a technique could be used in a live system, the time it takes to produce the enhancement must be weighed against the time that would be saved in transmission โฑ๏ธ.

2.4 Image Editing

By editing, we mean that the facsimile picture can be changed, or combined with other pictures, while it's stored inside the computer ๐Ÿช„. Earlier we said we could change the size and shape of a facsimile image. That technique was later combined with an overlaying method that let one picture be combined with another [12] ๐Ÿซถ.

To do any editing, the picture has to be displayed so the user can see it ๐Ÿ‘€. In our case, we displayed the picture on the bit-map screen ๐Ÿ–ฅ๏ธ. The image took up the left-hand side of the screen, and the right side was reserved for the picture being built ๐Ÿงฉ. The user could select an area of the left-hand screen and move it to a position on the right-hand screen ๐Ÿ–ฑ๏ธ. Several images could be displayed in succession on the left, with areas selected and moved to the right ๐ŸŽ€. Finally, the right-hand screen could be printed on the facsimile machine ๐Ÿ–จ๏ธ๐Ÿ’–.

Selecting an area of the picture was done with a coloured rectangular subsection ๐ŸŸช. It was controlled by a program in the computer and could be moved around on the screen ๐Ÿฆ‹. The rectangular subsection

okay so the rectangle could be moved around with instructions the operator typed in ๐ŸŽ€. It could go up or down, and it could get bigger or smaller, whatever they wanted. Once the right area was picked, the program remembered the coordinates and slid that coloured rectangle over to the right-hand side of the screen ๐Ÿฆ‹. Then the user picked an area again, the same way. When they were done editing, the program cut the selected part out of the left-hand screen and reshaped it to fit the rectangle on the right-hand screen. Then the result got displayed so they could see it ๐Ÿ‘€โœจ

When an image was being edited, the editor also had to keep a second scaled copy for display. Why? Bc the screen had different dimensions from the facsimile machine ๐Ÿ™ˆ The actual editing stuff, like chopping and merging, happened on the original image data files at the full resolution the facsimile machine could handle ๐Ÿ’…

2.5 Integration with Other Data Types โœจ

the facsimile machine is lowkey so much more than just a fax input/output device ๐Ÿ–จ๏ธ๐Ÿ’– It can also work as a printer for other kinds of data, like coded character text and geometric graphics. Right now, text can be converted into facsimile format and printed on the machine. Mixed pages with pictures AND text can also be handled by our system ๐ŸŒˆ Mixing facsimile images with geometric graphics is still a topic for future research, so that's a later glow-up ๐Ÿ”ฎ

To turn a character string into its facsimile format, the system keeps a translation table that stores the patterns of the characters available in the system, so they can be retrieved. The input string gets translated into a set of scan lines. Each scan line is made by joining together the matching character patterns from the string ๐Ÿงฉ

That translation table is basically a software font, and it can be edited and modified ๐Ÿ–Š๏ธ Only one font is available for now, but it's super easy to add other character fonts. And a font can even be loaded remotely from a database over the communication network ๐Ÿ›ฐ๏ธ๐Ÿ’œ

This opens up some really fun applications. For example, the machine could act as a Teletex printer, as long as the Teletex character font is included in the system. In that case, the text images might get distorted so they fit the presentation format the Teletex service asks for ๐Ÿ“  Similarly, Prestel viewdata pages could be displayed on the Grinnell screen ๐Ÿ“บโœจ

Pictures can also be mixed with text by combining this text conversion with the editing from the previous section. This should be seen as a notable step towards multi-type processing ๐Ÿฆ„๐Ÿ’…

And this doesn't just support a local multi-type environment. Multi-type information can also be sent over a network ๐ŸŒ Right now, though, a mixed page with text and pictures can only be sent once it's been represented in a bit-map format ๐Ÿ˜ฉ It would be way more efficient to send the text and the pictures separately, then rebuild the page at the destination site ๐Ÿง  That would need a multi-type data structure that both communicating sites understand, and that's the tea ๐Ÿซ–๐Ÿ’–

3. SYSTEM ARCHITECTURE โœจ

Now let's talk about the general design and implementation rules for a computerised facsimile system that does all the functions from the earlier sections ๐ŸŽ€ We'll go over the system requirements first, then a hierarchical model where the modules on different layers each run as their own separate processes. After that comes the Clean and Simple interface used for inter-process communication, then the task controller (the boss that organises the tasks in a requested job), and finally some experimental work on a more convenient user programming environment and a more efficient data transfer method ๐Ÿซถ

3.1 System Requirements

In a computerised facsimile system, images are stored in digital form ๐Ÿ”ข To make that happen, a page gets scanned by the optical scanner on the facsimile machine, and a digital number gets produced for how dark each pixel is ๐Ÿ–ค High resolution is needed to keep the detail, so facsimile data files are usually pretty chunky ๐Ÿฐ To store and send them efficiently, the data has to be compressed as much as possible ๐Ÿ“ฆ

Right now, facsimile machines from different manufacturers have different properties, like different compression methods and different resolutions ๐Ÿ˜ตโ€๐Ÿ’ซ There are also some international standards for facsimile compression, used for data sent over the public data network. These mean the facsimile data has to be converted from one representation form to another, so people who are far apart and use different machines can still talk to each other ๐ŸŒ๐Ÿ’Œ And fancier stuff, like image editing, needs the system's processing facilities too ๐Ÿ’…

When a facsimile image is being processed, it should be represented in a common format or internal data structure. That's what gets used to pass information between the different processing routines ๐Ÿ” For convenience and efficiency, this internal structure should be pretty well compressed, and it should be easy for the computer to manipulate ๐Ÿ’ป In our experimental work, the line vector was picked as the standard unit, with a simple run-length compression used on it [3] ๐Ÿงƒ Some processing routines might use other data formats, like bit-map. But it's on those routines to convert between their format and the standard one ๐Ÿ™Œ

The system should have several processing routines, and each one does one primitive task, like chopping, merging, or scale-changing โœ‚๏ธ You can build a huge variety of processing operations as long as those task modules can be organised flexibly. Being able to organise tasks flexibly should be thought of as one of the most important requirements of the system ๐Ÿ‘‘

One option is to run the processing routines separately, using temporary files as the communication media. It's very simple, but honestly it's far too inefficient ๐Ÿ˜ญ

As mentioned above, the information unit for communication between processing routines is the line vector. That means the routines could be organised as embedded loops, where a routine takes its input line from the source routine in the inner loop and passes its output line to the destination routine in the outer loop [3]. Obviously this is pretty efficient! But it isn't realistic for our system, because building different processing loops at run-time is super hard, and flexible task organisation becomes impossible ๐Ÿ™…โ€โ™€๏ธ

In a real-time operating system environment, the primitive tasks can be implemented as separate processes. This approach gets discussed in detail in the following sections, and it gives us the flexibility we need ๐Ÿฆ‹โœจ

3.2 Hierarchical Model

As shown in Fig. 7, the modules in a single computer fall into three layers ๐Ÿงš Here's the diagram:

                       +---------+
                       !         ! task controller
                       +---------+

                              tasks
                +---+  +---+  +---+  +---+  +---+
                !   !  ! !   !  !   !  !   !
                +---+  +---+  +---+  +---+  +---+
                  |      |                    |
                +---+  +---+                +---+
                !   !  !   ! device drivers !   !
                +---+  +---+                +---+
            - - - | - -  |  - - - - - - - - - | - - - -
                +---+  +---+                +---+
                !   !  !   !    physical    |   !
                !   !  !   !    devices     !   !
                +---+  +---+                +---+

                 Fig. 7  The hierarchical model

So here's the breakdown ๐Ÿ’–

(1) Device Drivers, the lowest layer in the model. The modules here handle the I/O activity of physical devices, like the facsimile machine, the display, and the floppy disk ๐Ÿ’พ This layer takes the I/O programming burden off the task modules above it, which is honestly such a relief ๐Ÿ˜Œ

(2) Tasks, which do all the processing primitives and handle the different data structures ๐Ÿ› ๏ธ Above each physical device's driver, there are one or more device-independent modules. They work as an information source or sink in the task chain (more on that below). A file system module lets other modules store and retrieve information on secondary storage, like a floppy disk ๐Ÿ“‚ Decompression and recompression routines convert the data structures of facsimile image information, so the facsimile machines can talk to the rest of the system ๐Ÿ“  Processing primitives, like chopping, merging, and scaling, are implemented as task modules in this layer. They're designed so they can be concatenated to carry out more complex jobs, which is giving Lego vibes ๐Ÿงฑ And as far as the system is concerned, the protocols for data transmission over computer networks are also treated as task modules in this layer ๐ŸŒ

(3) Task Controller, which organises the task processes to perform the specified job ๐ŸŽ€ It gives application-layer users a procedure-oriented language, so they can define the requested job as a chain of task modules. The chain is literally represented by a character string:

<source_task>|{<processing_task>|}<sink_task>

Following a command like that, the task controller picks the relevant task modules and links them together in the proper order using logical links ๐Ÿ”— Then it runs the tasks on the chain under its control, so the data from the source gets processed and the result gets put into the sink ๐Ÿซถ

3.3 Clean and Simple Interface โœจ

3.3.1 Principles โœจ

Okay so, in this app it's really important to build the software in a modular way ๐Ÿงฉ The plan is to put together a set of modules that each handle a different image processing task. Then there's another set of transport modules, which have to be built for shipping data over the different networks the UCL system is attached to. In our computerised facsimile system, these task modules are implemented as separate processes, and the whole system depends on those processes talking to each other. The interface they use for that was designed to be universal. It doesn't care which modules are on either end, and it's called the Clean and Simple interface [20]. This section is all about that interface ๐Ÿ’–

The Clean and Simple interface handles the synchronisation and transfer of full-duplex data streams between two communicating processes ๐Ÿฆ‹ So it has three big parts: connection synchronisation, data transfer, and connection desynchronisation. We'll go through each one below.

A connection gets started by one of the two processes, and that one usually belongs to a higher layer. Like, the interface between protocols of different layers is always initiated by the higher layer, though sometimes the connection is started passively by the primitive 'listen'. You'll see in the next section that task processes can talk to each other through their connections to the higher layer (the task controller), and that's what makes flexible task organisation possible ๐Ÿ‘‘

The process that starts the connection is called the 'master' process, and the other one is the 'slave' process. The master is also in charge of resource allocation for both processes. By 'resource' we mean mostly the memory areas for the message structure and the data buffer. Making the definition asymmetric like this means nobody gets confused about who allocates what ๐Ÿ™…

The interface runs on the signal-wait mechanism the operating system provides. A data structure called CSB (Clean and Simple Block) holds the function, the data buffer, and other info, and it gets sent as the event message whenever one process signals another [20] ๐Ÿ“ฌ


3.3.2 Synchronisation and Desynchronisation ๐Ÿค

Connection synchronisation happens in two steps. First, the two processes swap their identifiers for that specific connection using a getcid primitive. Usually the pointer to the task control structure of the process gets used as the connection identifier ๐Ÿชช

Then the 'master' sends an open CSB with the appropriate parameter string, which passes the initialisation info. This info (also called the open parameter) depends on the process, or more accurately on the task. For example, the parameters for the file system should be the file name and the access mode. As long as the 'slave' accepts the request, the connection is established and data can be transferred through the interface ๐ŸŽ€

To desynchronise the connection, the 'master' initiates a 'close' action. The 'slave' can also report an error state or an EOF (end of file) state to request a connection desynchronisation ๐Ÿ™ˆ

The listen primitive in our system is reserved for processes that receive a request from remote hosts on the networks ๐ŸŒ


3.3.3 Data Transfer ๐Ÿ“ฆ

While the Clean and Simple interface is asymmetric when it comes to connection synchronisation, data transfer is completely symmetric once the connection has been established. Data is allowed to flow in both directions, even though the operations are quite different ๐Ÿ”„

There are two primitives for data transfer, read and write. To send some data to the 'slave', the 'master' signals it with a CSB containing the write function and a buffer filled with the data. After consuming the data, the 'slave' returns the CSB to report the result status of the transmission ๐Ÿ’Œ

To go the other way and receive data from the 'slave', the 'master' uses a read CSB with an empty buffer. Once the 'slave' has the CSB, it fills the buffer with the data requested and then returns the CSB ๐Ÿ“


3.4 Control and Organisation of the Tasks ๐Ÿงš

Another big deal in the multi-process architecture of the UCL facsimile system is the need to systematise the control and organisation of the tasks. That's the job of the task controller, and this section covers how it works ๐Ÿ‘‘

3.4.1 Command Language ๐Ÿ’ฌ

As mentioned earlier, the task controller supports a procedure-oriented language. That's how the user, or the routines of the upper layers, define the jobs they want. A command should contain the following information:

  1. the names of the task processes which are involved in the job.
  2. the open parameters for these task processes.
  3. the order in which the tasks are to be linked.

The last item is quite important, though usually the same order as the one given in the command gets used ๐ŸŽฏ

A command in this language is presented as a zero-ended character string. In the task name strings and the attribute strings of the open parameters, '|', '"', and ',' must be excluded, because they'll be treated as separators. Here's the definition below, where '|' (the separator of the command strings in the language) does not mean 'OR'. ๐Ÿ™ƒ

<command_string> ::= <task_string>
<command_string> ::= <task_string>|<command_string>
<task_string> ::= <task_name>
<task_string> ::= <task_name>"<open_parameter>
<open_parameter> ::= <attribute>
<open_parameter> ::= <attribute>,<open_parameter>

3.4.2 Task Controller ๐ŸŽ›๏ธ

In our experimental work, the task controller module is called fitter. That name is borrowed from UNIX and kind of hints at how the module works. According to the command string, it links the specified tasks into a chain, and the data gets processed along that chain to fulfil the job requested (Fig. 8) โ›“๏ธ

                            tasks
                +-----+    +-----+    +-----+
                !  a  ! -> !  b  ! -> !  c  !
                +-----+    +-----+    +-----+

                     Fig. 8  The task chain

Since all modules, including fitter itself, are implemented as processes, the connections between modules should be via the Clean and Simple interfaces. Upon receiving the command string, the fitter parses it to find each task process involved and opens a connection to it. Formally, the task processes are chained directly, but logically there's no direct connection between them. All of them are connected to the fitter (Fig. 9) ๐Ÿ•ธ๏ธ

                           fitter
                       +-------------+
                   +-- !             ! --+
                   |   +-------------+   |
                   |          |          |
                   V          V          V
                +-----+    +-----+    +-----+
                !  a  !    !  b  !    !  c  !
                +-----+    +-----+    +-----+

          Fig. 9 The connection initiated by the fitter

For each of the processes it connects, the fitter keeps a table called pipe. When the command string is parsed, the pipe tables get double-linked to represent the specified order of data flow. For one process, its pipe table holds two pointers: a forward one pointing to its destination and a backward one pointing to its sources. Besides the pointers, it also keeps the info needed to identify the task process and the corresponding connection ๐Ÿ—‚๏ธ

Fig. 10 illustrates the chain of the pipe tables for the job "a|b|c". Note that the forward (output) chain ends at the sink, while the backward (input) chain ends at the source. In this sense, the task processes are chained in the specified order via the fitter (Fig. 11). The data transfer along the chain is initiated and controlled by the fitter, with each process getting the input from its source and putting the output to its destination ๐Ÿš‚

               +-----+    +-----+    +-----+
               !  * -+--> !  * -+--> !  0  !
               +-----+    +-----+    +-----+
               !  0  ! <--+- *  ! <--+- *  !
               +-----+    +-----+    +-----+
               !  a  !    !  b  !    !  c  !
               +-----+    +-----+    +-----+
               !     !    !     !    !     !
               !     !    !     !    !     !
               +-----+    +-----+    +-----+

                     Fig. 10  The pipe chain
                           fitter
                       +-------------+
                   +-> ! * -> * -> * ! --+
                   |   +-------------+   |
                   |         | A         |
                   |         V |         V
                +-----+    +-----+    +-----+
                !  a  !    !  b  !    !  c  !
                +-----+    +-----+    +-----+

                     Fig. 11  The data flow

This strategy makes the task organisation so flexible that only the links have to be changed when a new task chain is to be built up. In such an environment, each task process can be implemented independently, provided the Clean and Simple interface is supported. This also makes extending the system quite easy ๐ŸŒˆ

The fitter manipulates one job at a time. But it must maintain a command queue to cope with the requests, which come simultaneously from either the upper level processes or other hosts on the network ๐Ÿ“‹

3.5 Interface Routines ๐Ÿ› ๏ธ

In a modular, multi-process system such as the UCL facsimile system, the structure of the interface routines is very important. The CSI of section 3.3 is fundamental to the modular interface, and a common control structure is also essential. This section gives some details about both the sharable control structure and the buffer management ๐Ÿงฐ

3.5.1 Sharable Control Structure ๐Ÿ”

Though the CSI specification is straightforward, the implementation of the inter-process communication interface may be rather tedious, especially in our system, where there are many task processes to be written. Not only does each process have to implement the same control structure for signal handling, but the buffer management routines must also be included in all the processes ๐Ÿ˜ญ

The 'csinit' primitive is called for a task process to check in ๐Ÿงš An information table gets allocated, and the pointer to that table is returned to the caller as the task identifier. That identifier is what you use for every call to these interface routines ๐ŸŽ€. Each task process then waits by invoking the csopen primitive ๐Ÿ’ค, which does not return until the calling process is scheduled. Once the connection between the process and the fitter is established, the call returns the pointer to the open parameter string of the task, and the corresponding task gets started ๐Ÿฆ‹. A typical structure of the task process (written in C) looks like this:

static int mytid;       /* task identifier */

task()
{
        char *op;       /* open parameter */

        mytid = csinit();
        for(;;) {
                op = csopen(mytid);
                ...     /* the body of the task */
        }
}

After the task program runs, the process calls csopen and waits again ๐Ÿ” The portability of the task routines is improved by a huge amount ๐Ÿ™Œ Only the interface routines should be changed if the system were to run in a different operating environment ๐ŸŒธ

3.5.2 Buffer Management ๐ŸŽ€

The package of interface routines also gives you universal buffer management, so the task processes are freed from that burden ๐Ÿซถ The allocation of the data buffers is the responsibility of the higher level process, the fitter. If the task processes allocated their own buffers, some redundant copying would have to happen ๐Ÿ˜ฉ So the primitives for data transfer, csread and cswrite, are designed like this:

char *csread(tid, need);
char *cswrite(tid, need);

Here tid is the identifier of the task and need is the number of data bytes to be transferred. The primitives return the pointer to the area that satisfies the caller's requirement. csread returns an area containing the data the caller asked for. cswrite returns an area where the caller can copy the data to be transferred. The copied data gets written to its destination at a proper time, without the caller having to do anything ๐Ÿ’… Obviously, the unnecessary copy operations can be avoided โœจ It is recommended that the data buffer returned by the primitives be used directly to attain higher performance ๐Ÿš€

To make this work, each time a piece of data is required, the size of the buffer needed is compared with the size of the unused buffer area in the current CSB. If the unused area is not less than the needed size, the current buffer pointer is returned ๐Ÿ‘ Otherwise, a temporary buffer has to be employed. The data is copied into the buffer until the requested size is reached. In this case, the temporary buffer is returned instead of a part of the current buffer ๐Ÿง 

A cswrite call with the need field set to zero tells the interface routine that no more data will be sent ๐Ÿ›‘ That causes a close CSB to be sent to the destination routine.

If there is not enough data available, csread returns zero to indicate the end of data ๐Ÿ

4. UCL FACSIMILE SYSTEM ๐Ÿ’œ

Now we get into the implementation of the computerised facsimile system developed in the Department of Computer Science at UCL ๐Ÿ“ 

This system has several components ๐Ÿงฉ Since the total system is a modular and multi-process one, a specific system must be built up for a specific application. The way that this is done is discussed in section 4.1. The specific devices and their drivers are described in section 4.2. The system can be attached to a number of networks. In the UCL configuration, the network interface can be direct to SATNET [22], SERC NET [23], PSS [24], and the Cambridge Ring. The form of network connection is discussed further in section 4.3. The system must transfer data between the facsimile devices and the disks, and between the networks and the disks. For this, a filing system is required, which is discussed in section 4.4.

A key aspect of the UCL system is flexibility of devices, networks, and data formats ๐Ÿ’– The flexibility of devices is achieved by the modular nature of the device drivers (section 4.2). The flexibility of network is discussed in section 4.8. The additional flexibility of data structure is described in section 4.5. The flexibility can be utilised by incorporating conversion routines as in section 4.6. An important aspect of the UCL system is the ability to provide local manipulation facilities for the graphics files ๐Ÿ–ผ๏ธ The facilities implemented for local manipulation are discussed in section 4.7. In order to transfer files over the different networks of section 4.3., a high level data transmission protocol must be defined. The procedures used in the UCL system are discussed in section 4.8. ๐Ÿฆ‹

4.1 Multi-Task Structure ๐Ÿงฉ

The task controller and processing tasks are implemented as MOS processes. A number of utility routines are provided for users to build new task processes and modules at application level ๐Ÿ› ๏ธ

In the environment of MOS, a process is included in a system by specifying a Process Control Table when the system is built up. The macro setpcte is used for this purpose, and the meaning of its parameters is defined in [14].

#define setpcte(name,entry,pridev,prodev,stklen,
    relpid,relopc)
  {0,name,entry,pridev,prodev,stklen,relpid,relopc}

A Device Control Table (DCT) has to be specified for each device when the system is built up. A DCT can be defined anywhere, since devices are referenced by the DCT address ๐Ÿ“ The macro setdcte is designed to declare devices, and the meanings of its parameters are specified in [14]. This method is used in the device descriptions ๐Ÿ’…

#define setdcte(name,intvec,devcsr,devbuf,devinit,
    ioinit,intrpt,mate)
  {04037,intrpt,0,0,name,mate,intvec,devinit,
    devcsr,devbuf,ioinit}

4.2 The Devices ๐Ÿ“Ÿ

As mentioned in section 2, apart from the general purpose system console, there are three devices in the system to support the facsimile service. These are:

(1) AED62 Floppy Disk, which is used as the secondary memory storing the facsimile image data. Above its driver, a file system is implemented to manage the data stored on the disks, so that an image data file can be accessed through the Clean and Simple interface. This file system is discussed in detail in the next section. For some processing jobs, the image data has to be buffered on a temporary file, lest time-out occurs on the facsimile machine ๐Ÿ’พ

(2) DACOM Facsimile Machine, which is used to input and output image data. It reads an image and creates the corresponding data stream. On the other hand, it accepts the image data and reproduces the corresponding image. Above its driver, there is an interface task to fit the facsimile machine into the system, with the Clean and Simple interface being supported. The encoding algorithm for the DACOM machine is described in [19] ๐Ÿ“ 

(3) Grinnell Colour Display, which is used as the monitor of the system. Above its driver, an interface task is implemented so that the image data in standard format can be accepted through the Clean and Simple interface ๐ŸŒˆ

The detailed description of these devices can be found in Appendix 1. The interface task and the description for each device are listed in the following table. The interface tasks can be directly used as data source or sink in a task string ๐Ÿงš

      Device       Interface Task  Description

AED62 Floppy Disk        fs()      aed62(device)
DACOM fax Machine       fax()      dacom(device)
Grinnell Display   grinnell()      grinnell(device)

Note that the DCTs for the facsimile machine and Grinnell display have been included in the corresponding interface tasks, so there is no need to declare them if these tasks are used ๐Ÿ™ˆ

4.3 The Networks ๐ŸŒ

There are three relevant wide-area networks terminating in the Department of Computer Science at the end of 1981. These are:

(1) A British Telecom X25 network (PSS, [24]).

(2) A private X25 network (SERC NET, [23]).

(3) A Defence network (ARPANET/SATNET, [21], [22]).

In addition, there is a Cambridge Ring as a local network ๐Ÿ’

For the time being, the UCL facsimile system is directly attached to the various networks at the point NI (Network Interface) of Fig. 1 ๐Ÿ”Œ

As mentioned earlier, pictures can be exchanged via the SATNET/ARPANET, between UCL in London, ISI in Los Angeles, and COMSAT in Washington D.C.. The Network Independent File Transfer Protocol (NIFTP, [9]) is used to transfer the image data ๐Ÿ›ฐ๏ธ This protocol has been implemented on LSI under MOS [10]. In addition, we at UCL have put NIFTP on an ARPANET TOPS-20 host, which can act as an Internet File Forwader (IFF). In this case, TCP/IP ([28], [29]) is employed as the underlying transport service. Since TCP provides reliable communication channels, the provision of checkpoints and error-recovery procedures are not included in our NIFTP implementations ๐Ÿ™Œ

In the X25 network, the transport procedure is NITS/X25 ([25], [26]). Though pictures can be transferred to the X25 networks, no experimental work has been done, because:

(1) There is at present no collaborative partner on these networks.

(2) The LSI-11, on which our system is implemented, has no direct connection to these networks ๐Ÿ˜…

Locally, image data can be transmitted to the PDP11-44s running the UNIX time-sharing operating system. At present, the SCP ring-driver software uses permanent virtual circuits (PVCs) to connect the various computers on the ring ๐Ÿ’œ

4.4 File System ๐Ÿ—‚๏ธ

A file system has been designed, based on the AED62 double density floppy disk, for use under MOS. It is itself implemented as a MOS process supporting the Clean and Simple interface. The description of this task, fs(fax), can be found in Appendix 2 โœจ

In a command string, the file system task is picky ๐Ÿ’…: it can only be the data source or the data sink, so it has to sit at the very first or very last spot. If it's first, the file gets read. If it's last, the file gets written ๐ŸŽ€.

There are three access modes:

  • Read a file
  • Create a file
  • Append a file

The file name and access mode are passed in as the open parameters โœจ.

Let's walk through one, because it's so iconic ๐Ÿฆ‹. Say you want to read a document on the facsimile machine and save the data stream it creates onto the file system. The command string you need is:

        fax"r|fs"c,doc

where: fax - interface task for facsimile machine r - read from facsimile machine fs - file system task c - create a new file doc - the name of the file to be created.

Wanna dump a file instead? Meet od() ๐Ÿงš. It's a task process that works as a data sink in a command string.

4.5 Data Structure ๐Ÿ“ธ

Facsimile image data comes from a high-resolution raster scanner, so the original picture can be reproduced faithfully. The data represents binary images: monochrome, with two levels of intensity, which makes it bit-mapped graphics ๐Ÿ–ค๐Ÿค.

The simplest version is the bit-map itself. Each bit is one picture element, lined up in the same order the original picture gets scanned, with 1s for black pixels and 0s for white ones. Editing is easy-peasy: two images in bit-map format can be merged with a simple logic OR operation, and any specific pixel can be grabbed with a simple calculation. The catch is that it's usually huge because the resolution is so high, which makes it almost unrealistic for storage or transmission ๐Ÿ˜ญ.

So facsimile image data should be compressed to reduce its redundancy, so storage and transmission can be efficient ๐Ÿ’œ.

Run-length encoding is a useful compression scheme. Instead of storing the pattern, you store the counts of consecutive black and white runs to represent the image ๐ŸŒˆ.

Vector representation, where the run-lengths are coded as integers or bytes, is a useful internal representation of images ๐Ÿฆ‹. It's reasonably compressed and also quite easy to process. Chopping, scaling and mask-scanning are examples of the processing operations it supports. A conversion between different compression schemes may have to happen by decompressing the data into vector format first and then recompressing it. Retrieval gets easier with a line index, which gives the pointers to each line of the image ๐Ÿงญ.

A higher compression rate leads to more efficient transmission, but it comes at the expense of ease of processing ๐Ÿฅฒ. One example is the Huffman Code used in the CCITT 1-dimensional compression scheme. The data can be compressed more efficiently, but it's rather difficult to manipulate directly.

Taking the correlation between adjacent lines into account, 2-dimensional compression can achieve an even higher compression rate ๐Ÿš€. CCITT 2-dimensional compression and the DACOM facsimile machine use this method.

It's desirable to integrate facsimile images with other data types, like text and geometric graphics, and the structure of those other types must then be incorporated into the system ๐Ÿซถ. Right now only text structure is available, while the structure for geometric graphics is a topic for further study ๐Ÿ”ฎ.

The facsimile system supports the following data structures. Their descriptions, if any, are listed too, and you can find them in Appendix 3 (except for dacom(device)) ๐Ÿ“‹.

type    structure       compression     description

bit-map  bit-map               -              -
        vector          1D run-length   vector(fax)
        dacom block     2D run-length   dacom(device)
        CCITT T4        1D run-length   t4(fax)
                        2D run-length   t4(fax)

text    text                  -         text(fax)

Vector format is widely used as an internal data structure for data transfer between task processes ๐Ÿšš. The set of interface routines has been extended with two subroutines, getl() and putl(), which read and write line vectors directly through the Clean and Simple interface ๐Ÿง. You can find these in Appendix 3 (getl(fax) and putl(fax)).

To check the validity of a vector file, there's a check task process, check(), that works as a data sink in a command string. It can also dump the vector elements of specific lines ๐Ÿ”.

4.6 Data Conversion ๐Ÿ”„

To convert one data structure into another, the system provides several conversion modules in two categories: task processes and subroutines ๐Ÿ’–. The task processes are MOS processes that can only be used in the environment described in this note. The subroutines are written in C and are compatible under UNIX, so they're more generally usable.

Character strings or text can be converted into vector format, so you can form an integrated image that combines picture and text ๐Ÿ“๐Ÿ–ผ๏ธ.

The following table lists these conversion modules, including their functions and descriptions (which can be found in Appendix 3) ๐Ÿ—‚๏ธ.

module  type          from          to      description

decomp  process       dacom         vector   decomp(fax)
recomp  process       vector        dacom    recomp(fax)

ccitt   process       vector        t4       ccitt(fax)
                      t4            vector

bitmap  subroutine    vector        bitmap    bit-map(fax)
tovec   subroutine    bitmap        vector    tovec(fax)

ts      subroutine    ASCII string  vector   ts(fax)
string  process       ASCII string  vector   string(fax)
tf      process       text          vector   tf(fax)

Each DACOM block contains a Cyclic Redundancy Check (CRC) field, so the system supplies a subroutine, crc(), to calculate or check the CRC code ๐Ÿ” (see crc(fax)).

If a vector file is to be printed on the DACOM facsimile machine, the image data should be re-compressed into the DACOM-block format first. The command string looks like this ๐Ÿ–จ๏ธ:

fs"e,pic|recomp|fax"w

where   fs     - file system task
        e      - read an existing file
        ic     - file name
        recomp - re-compression task
        fax    - interface task for facsimile machine
        w      - print an image on facsimile machine

4.7 Image Manipulation ๐ŸŽจ

Four processing task processes are provided in the system:

  1. Chop, which applies a defined window to the input image โœ‚๏ธ.
  2. Scale, which enlarges or shrinks the input image to the defined dimensions ๐Ÿ“.
  3. Merge, which puts the input image on the specified area of a background image ๐Ÿงฉ.
  4. Clean, which removes the noise on the input image ๐Ÿงผ.

The Clean and Simple interfaces are supported in these processing tasks, so the tasks can be used in command strings. However, these tasks can be neither source nor sink in a command string ๐Ÿ™…. The data format of their input and output is vector.

For example, a facsimile page can be cleaned and then printed on the facsimile machine ๐Ÿ–จ๏ธโœจ. Note that the image data must be recompressed before being sent to the facsimile machine. If the original data is in DACOM block form, it has to be decompressed first, because the processing tasks only accept line vectors. The command string is shown below.

fs"e,page|clean|recomp|fax"w

where   fs     - file system task
        e      - read an existing file
        page   - file name
        clean  - cleaning task
        recomp - re-compression task
        fax    - interface task for facsimile machine
        w      - print an image on facsimile machine

The descriptions of these processing tasks can be found in Appendix 2 (chop(fax), scale(fax), merge(fax), and clean(fax)) ๐Ÿ“š.

In the tasks chop and merge, a window is set by giving the coordinates of its vertices. But it's usually rather difficult for a human user to decide the exact coordinates ๐Ÿ˜ต. So the system supplies a subroutine, choice(), which specifies a rectangular subsection of an image through interactive manipulation of a rectangular subsection on the screen of the Grinnell display showing the image ๐Ÿ–ฑ๏ธ. It provides a set of interactive commands so a user can intuitively choose the area they're interested in. Note that this subroutine must be called by a MOS process, and the Grinnell display must be included in the system.

By means of these image processing modules, the image editing described in section 2.4 can be carried out ๐Ÿช„. Let's look at an example. An image abstracted from a picture 'a' is to be merged onto a specified area of another picture 'b'. First, the two pictures 'a' and 'b' should be displayed on the left half and right half of the screen, respectively. Assume both are standard DACOM pages with dimensions 1726x1200. They have to be shrunk to fit the dimensions of the half screen (256x512). If the data format is not vector, conversion should be carried out first. The required command strings are:

   e,a|scale"1726,1200,256,512|grinnell"0,511,255,0,z,g
     fs"e,b|scale"1726,1200,256,512|grinnell"256,511,511,0,z,b

     where   fs            - file system task
             e             - read an existing file
             a             - file name
             b             - file name
             scale         - scale task
             1726,1200     - old dimension
             256,512       - new dimension
             grinnell      - grinnell display interface task
             0,511,255,0   - presentation area (the left half)
             256,511,511,0 - presentation area (the right half)
             z             - zero write mode
             g             - green
             b             - blue

In an application process, the subroutine choice() is called in the following ways for the user to choose the areas on both pictures ๐Ÿ‘‘

     choice(r, 1726, 1200, 1, 0, 0);
             /* choice the area on 'a' */
             /* r    - red
                1726 - width of the original picture
                1200 - height of the original picture
                1    - left half of the screen
                0    - the subsection can be of any width
                0    - the subsection can be of any height
              */
     choice(r, 1726, 1200, 2, 0, 0);
             /* choice the area on 'b' */
             /* r    - red
                1726 - width of the original picture
                1200 - height of the original picture
                2    - right half of the screen
                0    - the subsection can be of any width
                0    - the subsection can be of any height
              */

okay so here we go ๐ŸŽ€ when the user finishes editing, the coordinates of the chosen rectangles get handed back to us โœจ the table below shows an example. the widths and heights in it are worked out from those coordinates, and they tell us the source image has to be enlarged to fit its destination ๐Ÿ”

              (0, 0)
                +-------------------------------> x
                |
                |  (x0, y0)     w
                |     +--------------------+
                |     !                    !
                |     !                    !
                |     !                    ! h
                |     !                    !
                |     !                    !
                |     +--------------------+
                |                       (x1, y1)
                V
                y

     original   x0      y0      x1      y1      w       h

        a       30      40     100     120      70      80
        b      100     100    1100    1100    1000    1000

at this point we can finally get our goal done ๐Ÿ’– by running the job below. the result image is going to be saved as a brand new file called 'c' ๐Ÿฅน

     fs"e,a|chop"30,40,100,120|scale"70,80,1000,1000
         |merge"b,0,100,100,1100,1100|fs"c,c

     where   fs                - file system task
             e                 - read an existing file
             a                 - file name
             chop              - chop task
             30,40,100,120     - the area to be abstracted
             scale             - scale task
             70,80             - old dimension
             1000,1000         - new dimension
             merge             - merge task
             b                 - file name of the background image
             0                 - to be overlaid
             100,100,1100,1100 - the area to be overlaid
             fs                - file system task
             c                 - create a new file
             c                 - the name of the file to be
                                 created

4.8 Data Transmission โœจ

okay this part is the networking glow-up ๐Ÿฆ‹ to send facsimile image data over computer networks (using the setup in Fig. 1), the Network Independent File Transfer Protocol [9] gets built as a MOS task process. it supports the Clean and Simple interface from section 3.3 [10], which means this module can be used directly inside a command string ๐Ÿ’… it always runs in initiator mode, but server mode is supported too. you can read all about it in Appendix 2 (ftp(fax)) ๐Ÿ“–

since it's network-independent, it uses a transport service to talk across the networks ๐ŸŒ and the Clean and Simple interface is also what handles the chat between the module and the transport service processes ๐Ÿซถ

so picture this ๐Ÿ–ผ๏ธ an image file lives in a remote file system and needs to get printed on your local facsimile machine. the data travels over the ARPANET [21], with Transport Control Protocol (TCP) [28] as the underlying transport service. like we said before, the network delay can cause a time-out on the local facsimile machine ๐Ÿ˜ญ so the job has to be split into two subjobs.

  1. Subjob (1): fetch the remote file. the remote file gets sent over with the NIFTP module. the twist is that instead of going straight to the facsimile machine, the received data gets stored in a temporary file ๐Ÿงš
          ftp"r,b,ucl,fax,pic;tcp:1234,10,3,3,42,4521|fs"c,tmp

          where   ftp - NIFTP task
                  t   - receive
                  b   - binary
                  ucl - remote user name
                  fax - remote password
                  pic - remote file name
                  tcp - transport service process

                  parameters for the transport service:

                      1234      - local channel number
                      10,3,3,42 - remote address
                      4521      - channel reserved for the
                                  remote server

                  fs  - local file system task
                  c   - create a new file
                  tmp - the name of the file to be created
  1. Subjob (2): print it. the temporary file gets read, and the image is sent to the facsimile machine for printing. here it's assumed the data is already in DACOM block form, so no conversion is needed ๐Ÿ“
          fs"e,tmp|fax"w

          where   fs     - file system task
                  e      - read an existing file
                  tmp    - file name
                  fax    - interface task for facsimile machine
                  w      - print an image on facsimile machine

ok now the exciting bit ๐ŸŒˆ we can swap image data with ISI and COMSAT! ๐Ÿฅณ DACOM block is the only format that works right now, because all three participants have DACOM facsimile machines and no other data format is available at both ISI and COMSAT ๐Ÿ™ˆ but the ARPA-Facsimile community plans to adopt the CCITT standard for future work โœจ and as mentioned earlier, UCL already has this facility ๐Ÿ’œ

above NIFTP, there's a simple protocol that controls the transmission of facsimile data ๐ŸŽ€ in it, a facsimile data file is defined like this: every DACOM block gets a 2-byte header at the front. that header has a length-byte (the length of the block, header included) and a code-byte (the type of the block) ๐Ÿง here's the diagram:

             |<--- header ---->|<------ 74 bytes ------->|
             +--------+--------+-------------------------+
             ! length !  code  !       DACOM block       !
             +--------+--------+-------------------------+

the length-byte is 76 (decimal) for all DACOM blocks ๐Ÿ”ข the code-byte is 071 (octal) for a setup block and 072 for a data block ๐ŸŒธ there's also a special EOP block that marks the end of a page ๐Ÿ›‘ it's just the header, with the length-byte set to 2, and its code-byte is undefined. a facsimile data file can hold several pages, and they're separated by EOP blocks ๐Ÿ“„


5. CONCLUSION ๐ŸŽ€

5.1 Summary

okay bestie, the history is iconic ๐Ÿ•ฐ๏ธ facsimile transmission techniques were invented back in 1843, but it wasn't until recent years that integrating with computer communication systems gave rise to "great expectation" ๐Ÿ˜ญ this system captures the compatibility and flexibility of computerised facsimile systems ๐Ÿ’…

in this system, facsimile no longer just means the transmission device. it means the function of moving hard copy from one place to another ๐Ÿ“จ the system doesn't just allow more reliable and accurate document transmission over computer networks, it also lets images be manipulated electronically ๐Ÿ–ผ๏ธ an image can be converted from one representation format to another, so different makes of facsimile machines can talk to each other ๐Ÿซถ a picture can even be shown on different bit-map devices, like a TV-like screen, because it can be scaled to get around the incompatibilities ๐Ÿ“บ and the system provides windowing and overlaying facilities, which means a sophisticated editor can be supported ๐Ÿ‘‘

one of the most important parts of this system is that text can be converted into its bit-mapped representation and integrated with pictures ๐Ÿคฏ geometric graphics could be included too. so the facsimile machine could act as a printer for multi-type documents ๐Ÿ–จ๏ธ it's clear that facsimile will play an important role in future information processing systems ๐Ÿฆ‹

as far as the system itself goes, here are the advantages we can recognise โœจ even though we focused on the facsimile system, lots of these features apply just as well to other information-processing systems ๐Ÿ’–

  1. Flexibility: user jobs can be organised easily. all you have to do is make the logical links for the appropriate task processes ๐Ÿงฉ
  2. Simplicity: the interface routines take care of things like signal handling and buffer management. by avoiding that burden, the task processes become very "clean and simple" ๐Ÿงผ
  3. Portability: the interface routines also make the task processes totally independent of the operating environment. only these routines need to be modified if the environment changes ๐ŸŒ
  4. Ease of extension: the power of the system can be simply and infinitely extended by adding new task processes โญ
  5. Distributed Environment: this approach can easily be extended to a distributed environment, where limitless hardware and software resources can be provided ๐ŸŒˆ

5.2 Problems

ngl, this part is a bit of a letdown ๐Ÿ˜ญ the network we used for the experiments was not designed for image data transmission. the data transfer is so slow that a time-out may happen on the facsimile machine ๐Ÿ™ˆ local buffering solved this, and pictures were successfully exchanged over the network, but the slowness is still rather disappointing given how much image data there is ๐Ÿ’€ the measurement showed the throughput was around 500 bits/sec. in other words, it took at least 5 minutes to transfer a page ๐Ÿ•” this was caused by the network, not our system ๐Ÿซ  the situation has improved recently. however, more efficient compression schemes are still required ๐Ÿฅบ

at present, the system must be directly attached to the network to be accessed ๐Ÿ”Œ the network ports are in high demand, though, so frequent reconfiguration is needed ๐Ÿ” ugh, a real main character problem ๐Ÿ’…

The facsimile system can ONLY hang out on the local network, the Cambridge Ring ๐Ÿ’, and any foreign networks have to reach it through gateways that plug into the ring ๐ŸŒธ. This is shown in Fig. 12 โœจ. The X25 network connects through an X25 gateway, XG [25], and SATNET connects through another gateway, SG [25]. Both networks work at the transport level, and XG and SG support the relevant transport procedures ๐Ÿ’…. For XG that means NITS/X25 ([26], [27]). For SATNET it means TCP/IP ([28], [29]) ๐Ÿซถ.

UCL facsimile
  system          - - - - - - - -
+--------+      /                 \      +------+
!        ! ----    Cambridge Ring   ---- !  PE  !
+--------+      \                 /      +------+
                  - - - - - - - -            |
                    /         \              |
              +------+       +------+        |
              !  XG  !       !  SG  ! --- SATNET
              +------+       +------+
              /       \
            PSS    SERC NET

     Fig. 12  Schematic of UCL network connection

Okay so when the network software and the application software live on the same machine, the Clean and Simple interface from Section 3.5 is what the modules use to talk to each other ๐ŸŽ€. When the gateway software got moved onto its own separate machine, an Inter-Processor Clean and Simple [30] was needed ๐Ÿฆ‹. The right transport process gets handed over to the relevant gateway, and the right facilities get set up for addressing that gateway ๐Ÿ’œ. Otherwise the software doesn't need much changing to handle the distributed case โœจ.

In our experimental work we ran into these problems too ๐Ÿ˜ญ:

  1. The primary memory of the LSI-11 is so small that we cannot build a system with all the modules we've developed ๐Ÿ’€. To transfer an edited picture using the NIFTP module, we first have to load an editor system to input and process the picture, and only then load the NIFTP system to transmit it ๐Ÿ™ˆ.
  2. Image processing procedures run super slowly ๐Ÿข. For example, shrinking a picture to fit the screen of the Grinnell display takes several minutes ๐Ÿ˜ฉ. This stops the system from being widely used in its present form ๐Ÿšซ.
  3. Floppy disks are far from adequate as secondary storage for image data files ๐Ÿ’พ. We have two double-density floppy disk drives, and each disk holds about 630K bytes. But an image page contains at least 50K bytes, and sometimes that number can double for a really complex picture ๐Ÿ“. So only a limited number of pages can be stored ๐Ÿ˜”.

On the other hand, our department has two PDP11-44s running UNIX, plus big disks giving us tons of file storage ๐Ÿ‘‘. Their processing speed is much higher than the LSIs' ๐Ÿš€. The UNIX file system gives us a super convenient information-management environment ๐Ÿ’…, and that gave us the idea that UNIX could pretend to be a file server in charge of storing and managing the image data ๐Ÿงš. Then all the processing tasks could run on UNIX โœจ. This doesn't just fix the problems above, it also brings these extra perks ๐ŸŒˆ:

  1. UNIX gives us a way better software-development environment than LSI MOS ever can or will ๐Ÿ’….
  2. The facsimile service can be enhanced to support many users at a time ๐Ÿซถ.
  3. The UNIX file system is so sophisticated that it can handle more complex data entities ๐Ÿง .

The 44s and the LSI-11 (which the facsimile machine and Grinnell display are attached to) are all connected to the UCL Cambridge Ring ๐Ÿ’. That means you can build a distributed processing environment where a job on one computer can be kicked off by another, and then the job gets carried out by both computers working together ๐Ÿค.

In that distributed setup, the LSI-11 microcomputer plus the facsimile machine basically become a totally passive facsimile server ๐Ÿฆ‹, controlled by a UNIX user ๐Ÿ‘‘. A page gets read on the facsimile machine, and the image data stream it produces is sent to UNIX over the ring ๐Ÿ“จ. The image data gets stored as a UNIX file and can be processed if needed ๐Ÿ’œ. It can also be sent over the ring back to the facsimile server, where it gets reprinted on the facsimile machine ๐Ÿ–จ๏ธ.

IPCS [30] is far from adequate for building this kind of distributed environment ๐Ÿ˜ค, because it doesn't give you any facility for organising a remote job. In our system, the task controller was modified so that command strings can be supplied from a remote host on the network ๐ŸŒ. Once it accepts the request, the task controller organises the relevant task chain, and the requested job runs under its control ๐ŸŽ€. Running a distributed job may require synchronisation between the two computers โฑ๏ธ. These problems are discussed in detail in [31] ๐Ÿ“–.

Generally speaking, a distributed system built on a local network that supplies cheap, fast, and reliable communication could be the ultimate solution to the operational problems in this section ๐ŸŒŸ. In a system like that, different system operations get carried out in the most suitable places ๐Ÿ’–.

For now, this system only has a procedure-oriented task-control language ๐Ÿ“œ. The command string of the fitter can be typed from the system console directly, and the matching job gets organised and executed โŒจ๏ธ. In theory, that's enough to cope with any requirement a user has ๐Ÿค“. But when a job gets complex, typing commands becomes super tedious and prone to error ๐Ÿ˜ตโ€๐Ÿ’ซ.

Above the task controller, a job-controller layer is required ๐Ÿง. It provides a problem-oriented language so the user can easily put their requirement to the system ๐Ÿ—ฃ๏ธ. When a command comes in, the job controller translates it into a command string for the task controller and passes that string along so the operation request gets done ๐Ÿš€. Sometimes one job has to be divided into several subjobs, which get dealt with separately ๐Ÿงฉ. The job controller should also be responsible for high-level calculation and management, so the user doesn't need to care about system details ๐Ÿ’….

In the system that supports facsimile service under UNIX, a set of high-level commands is provided ๐ŸŽ€. The command strings for the facsimile station get arranged automatically, and they're totally hidden from the UNIX user ๐Ÿ™ˆ.


5.3 Future Study ๐Ÿ”ฎ

At the next stage, our attention should move to a higher-level, more sophisticated system that supports a multi-type environment ๐ŸŒˆ. In a system like that, the facsimile machine wouldn't just work as a facsimile input/output device. It should also play the role of a printer for multi-type documents ๐Ÿ–จ๏ธ. That's because other data types, e.g. coded character text and geometric graphics, can be easily converted into bit-mapped graphics format, which the facsimile machine is able to accept ๐Ÿ’œ.

First of all, a data structure should be designed to represent multi-type information ๐Ÿงฑ. In a distributed environment, that structure should be understood all over the system, so multimedia messages can be exchanged ๐Ÿ’Œ.

In a future system, different services should be supported, including viewdata, Teletex, facsimile, graphics, slow-scan TV, and speech ๐ŸŽ€. The techniques developed for facsimile will be generalised for use with other bit-mapped image representations, such as slow-scan TV ๐Ÿฆ‹.

To improve the performance of the facsimile system, we are investigating how to use an auxiliary special-purpose processor to perform some of the image processing operations โšก. Such a processor will be essential for the higher data rate involved in slow-scan TV ๐Ÿ”ฅ.


Reference ๐Ÿ“š

  • [1] P. T. Kirstein, "The Role of Facsimile in Business Communication", INDRA Note 1047, Jan. 1981.
  • [2] T. Chang, "A Proposed Configuration of the Facsimile station", INDRA Note 922, May, 1980.
  • [3] T. Chang, "Data Structure and Procedures for Facsimile Signal Processing", INDRA Note 923, May, 1980.
  • [4] S. Treadwell, "On Distorting Facsimile Image", INDRA Note No 762, June, 1979.
  • [5] M. G. B. Ismail and R. J. Clarke, "A New Pre-Processing Techniques for Digital Facsimile Transmission", Dept. of Electronic Engineering, University of Technology, Loughborough.
  • [6] T. Chang, "Mask Scanning Algorithm and Its Application", INDRA Note 924, June, 1980.
  • [7] M. Kunt and O. Johnsen, "Block Coding of Graphics: A Tutorial Review", Proceedings of the IEEE, special issue on digital encoding of graphics, Vol. 68, No 7, July, 1980.
  • [8] T. Chang, "Facsimile Data Compression by Predictive Encoding", INDRA Note No 978, May. 1980.
  • [9] High Level Protocol Group, "A Network Independent File Transfer Protocol", HLP/CP(78)1, alos INWG Protocol Note 86, Dec. 1978.
  • [10] T. Chang, "The Implementation of NIFTP on LSI-11", INDRA Note 1056, Mar. 1981.
  • [11] T. Chang, "The Design and Implementation of a Computerised Facsimile System", INDRA Note No. 1184, Apr. 1981.
  • [12] T. Chang, "The Facsimile Editor", INDRA Note 1085, Apr. 1981.
  • [13] K. Jackson, "Facsimile Compression", Project Report, Dept. of Computer Science, UCL, June, 1981.
  • [14] R. Cole and S. Treadwell, "MOS User Guide", INDRA Note 1042, Jan. 1981.
  • [15] CCITT, "Recommendation T.4, Standardisation of Group 3 Facsimile Apparatus for Document Transmission", Geneva, 1980.
  • [16] "DACOM 6450 Computerfax Transceiver Operator Instructions", DACOM, Mar. 1977.
  • [17] "AED 6200LP Floppy Disk Storage System", Technical Manual, 105499-01A, Advanced Electronics Design, Inc. Feb. 1977.
  • [18] "The User Manual for Grinnelll Colour Display".
  • [19] D. R. Weber, "An Adaptive Run Length Encoding Algorithm", ICC-75.
  • [20] R. Braden and P. L. Higginson, "Clean and Simple Interface under MOS", INDRA Note No. 1054, Feb. 1981.
  • [21] L. G. Roberts et al, "The ARPA Computer Network", Computer Communication Networks, Prentice Hall, Englewood, pp485-500, 1973. ๐Ÿ“š
  • [22] I. M. Jacobs et al: "General Purpose Satellite Network", Proc. IEEE, Vol. 66, No. 11, pp1448-1467, 1978. ๐Ÿ›ฐ๏ธ
  • [23] J. W. Burren et al, "Design fo an SRC/NERC Computer Network", RL 77-0371A, Rutherford Laboratory, 1977. ๐Ÿง 
  • [24] P. T. F. Kelly, "Non-Voice Network Services - Future Plans", Proc. Conf. Business Telecommunications, Online, pp62-82, 1980. ๐Ÿ’ผ
  • [25] P. T. Kirstein, "UK-US Collaborative Computing", INDRA Note No. 972, Aug. 1980. ๐Ÿค
  • [26] "A Network Independent Transport Service", PSS User Forum, Study Group 3, British Telecom, London, 1980. ๐Ÿ“ก
  • [27] CCITT, Recommendation X3, X25, X28 and X29 on Packet Switched Data Services", Geneva 1978. ๐ŸŒธ
  • [28] "DoD Standard Transmission Control Protocol", RFC761, Information Sciences Inst., Marina del Rey, 1979. ๐Ÿ’–
  • [29] "DoD Standard Internet Protocol", RFC760, Information Sciences Inst., Marina del Rey, 1979. โœจ
  • [30] P. L. Higginson, "The Orgainisation of the Current IPCS System", INDRA Note No. 1163, Oct. 1981. ๐ŸŽ€
  • [31] T. Chang, "Distributed Processing for LSIs under MOS", INDRA Note No. 1199, Jan. 1982. ๐Ÿฆ‹

Appendix I: Devices โœจ

NAME

aed62 - double density floppy disk ๐Ÿ’พ

SYNOPSIS

DCT aed62
setdct("aed62", 0170, 0170450, 0170450,
        aedini, aedsio, aedint, 0);

DESCRIPTION

okay so the Double Density disks have 77 tracks, numbered 0 to 76 ๐Ÿง. Each track has 16 sectors (sometimes called blocks), which makes 1232 sectors on each side of the disk, numbered 0 to 1231. Each sector holds 512 bytes, so that's 630,784 bytes on each side of the floppy. Literally a whole lotta data, bestie ๐Ÿ’…

Only one side can be accessed at a time ๐Ÿ™ˆ. There is only one head per drive, and it sits on the underside of the disk. To reach the other side, you have to manually take the disk out and put it back in the other way up. Main character struggle, ngl ๐Ÿ˜ญ

Each block is actually two blocks on the disk: an address ID block and a data block ๐Ÿฆ‹. The address ID block is used by the hardware and holds the track number, the block number, and the size of the data block that follows. When an operation is happening, the seek mechanism first finds the block by reading the address ID blocks and literally "hunting" for the right one. It will hunt for up to 2 seconds before reporting a failure โณ.

Both the address ID and the data blocks are followed by a checksum word. The hardware maintains it, and it's hidden from the user ๐Ÿซฃ. When writing, the checksum is calculated and appended to the block. When reading, it's verified (for both the ID and data blocks), and any error is reported as a Data Check. On a write, nothing checks the data block, and the hardware has no idea if it was written correctly. The only way to verify it is to read it ๐Ÿ”.

There are two drives in the unit, but they cannot be used simultaneously ๐Ÿšซ. If an operation is in progress on one drive, no access can be made to the other until the first operation is complete. The driver will queue requests for both drives, though, and make sure they are performed in order ๐Ÿซถ.

The MOS driver is called aed62.obj, and it operates on the following IORB entries ๐Ÿงš.

irfnc

The operation to be performed, as follows:

0 - Read
1 - Write
2 - Verify
3 - Seek

Read and Write cause data to be transferred to and from disk. Verify does a hardware read without transferring the data to memory, and it's used for verifying that the data can be successfully read. The checksum at the end of the block of each sector is verified by the hardware. The seek command is used to move the disk heads to a specified track. ๐ŸŽฏ

irusr1

The drive number. Only Zero or One is accepted. This is matched against the number dialed on the drive. If the number is specified on both drives, or neither, a hardware error will be reported. ๐Ÿ”ฅ

irusr2

The Sector or Block Number. Must be in the range 0 to 1231 inclusive. irusr2 specifies the block number that the transfer is to begin at for Read and Write, the beginning of the verified area for the Verify command, and the position of the head for the Seek command. In the latter case, the head will be positioned to the track that contains the block. ๐ŸŒˆ

iruva

This specifies the data address, which must be even (word boundary). If an odd address is given, the low order bit is set to zero to make it even. Not required for the Seek or Verify commands. ๐Ÿ“

irbr

Transfer length as a positive number of bytes. Not required for the seek command, but it IS used by the Verify command so that the correct number of blocks may be verified. The disk is only capable of transferring an even number of bytes. If an odd length is given, the low order bit is made zero to reduce the length to the lower even value. The length is NOT restricted to the sector size of 512 bytes. If the length is greater than 512, successive blocks are read or written until the required transfer length has been satisfied. If the length is not an exact multiple of 512 bytes, only the specified length will be read or written. Note that the hardware always reads and writes a complete sector, so specifying a shorter length on a read will cause the remainder of the block to be skipped. On a write, the hardware will repeat the last specified word until the sector is full. ๐Ÿงƒ

The driver will attempt to recover from all soft errors. There is no automatic write or read verify like on mag tapes, so data that is incorrectly written will not be detected as such until a read is attempted. For this reason, the verify feature can be used (see above) to force the checking of written data ๐Ÿ’œ. When an error is detected while performing a read, the offending block will be re-read up to 16 times, and disk resets will be attempted during this time too. If all of that fails, a hardware error indication is returned to the user. Other errors that are possible are Protection Error (attempt to write to a read-only disk) and User Error, which indicates that the parameters in the IORB were incorrect. Errors such as there being no disk loaded, or the drive door being open, are NOT detectable by the program. The interface sees these as Seek Errors (i.e. soft errors), so the driver will retry several times before returning a Hardware Error indication to the user. It should be noted that error recovery can take a long time. As mentioned above, there is a 2 second delay before a seek error is reported by the hardware, for instance โณ๐Ÿ’€.


NAME

grinnell - colour display ๐ŸŒท

SYNOPSIS

DCT grndout
setdct("grndout", 03000, 0172520, 0172522,
        grnoi, grnot, grnoti, &grndin);
DCT grndin
setdct("grndin", 03000, 0172524, 0172526,
        grnoi, grnot, grnoti, &grndout);

DESCRIPTION โœจ

okay so the Grinnell colour display is giving 512x512 pels ๐ŸŒˆ That's the whole screen. You get three colours to play with (red, green and blue), but there's no grey scale, so no moody black-and-white looks ๐Ÿ’… It has three graphics modes:

  1. Alphanumeric: the input ASCII characters get displayed at the selected positions on the screen ๐Ÿ’–
  2. Graphic: basic geometric elements, like lines and rectangles, get drawn with graphics commands โœ๏ธ
  3. Image: the input data gets read as bit patterns, and the matching images get illustrated ๐Ÿ–ผ๏ธ

The values used to build commands are explained in the Grinnell User Manual ๐Ÿ“– but I've also listed them below so you don't have to go digging ๐Ÿซถ

      #define LDC     0100000   /* Load Display Channels */

      #define LSM     0010000   /* Load Subchannel Mask */
      #define   RED   0000010   /* Read Subchannel */
      #define   GREEN 0000020   /* Green subchannel */
      #define   BLUE  0000040   /* Blue subchannel */

      #define WID     0000000   /* Write Image Data */
      #define WGD     0020000   /* Write Graphic Data */
      #define WAC     0022000   /* Write AlphanumCh */

      #define LWM     0024000   /* Load Write Mode */
      #define   REVERSE  0200   /* Reverse Background */
      #define   ADDITIVE 0100   /* Additive (not Replace) */
      #define   ZEROWRITE 040   /* Dark Write */
      #define   VECTOR    020   /* Select Vector Graph */
      #define   DBLEHITE  010   /* Double Height write */
      #define   DBLEWIDTH 004   /* Double Width write */
      #define   CURSORAB  002   /* Cursor (La+Lb,Ea+Eb) */
      #define   CURSORON  001   /* Cursor On */

      #define LUM     0026000   /* Load Update Mode */
      #define   Ec        001   /* Load Ea with Ec */
      #define   Ea_Eb     002   /* Load Ea with Ea + Eb */
      #define   Ea_Ec     003   /* load Ea with Ea + Ec */
      #define   Lc        004   /* Load La with Lc */
      #define   La_Lb     010   /* Load La with La + Lb */
      #define   La_Lc     014   /* Load La with La + Lc */
      #define   SRCL_HOME 020   /* Scroll dsiplay to HOME */
      #define   SRCL_DOWN 040   /* Scroll down one line */
      #define   SCRL_UP   060   /* Scroll up one line */

      #define ERS     0030000   /* Erase */
      #define ERL     0032000   /* Erase Line */
      #define SLU     0034000   /* Special Location Update */
      #define   SCRL_ZAP 0100   /* unlimited scroll speed */

      #define EGW     0036000   /* Execute Graphic Write */
      #define LER     0040000   /* Load Ea relative */
      #define LEA     0044000   /* Load Ea */
      #define LEB     0050000   /* Load Eb */
      #define LEC     0054000   /* Load Ec */
      #define LLR     0060000   /* Load La Relative */
      #define LLA     0064000   /* Load La */
      #define LLB     0070000   /* Load Lb */
      #define LLC     0074000   /* Load Lc */
      #define   LGW     02000   /* perform write */

      #define NOP     0110000   /* No-Operation */

      #define SPD     0120000   /* Select Special Device */
      #define LPA     0130000   /* Load Peripheral Address */
      #define LPR     0140000   /* Load Peripheral Register */
      #define LPD     0150000   /* Load Peripheral Data */
      #define RPD     0160000   /* ReadBack Peripheral Data */
      #define MEMRB     00400   /* SPD - Memory Read-Back */
      #define DATA      01000   /* SPD - Byte Unpacking */
      #define   ALPHA   06000   /* LPR - Alphanumeric data */
      #define   GRAPH   04000   /* LPR - Graphic data */
      #define   IMAGE   02000   /* LPR - Image data */
      #define   LTHENH  01000   /* take lo byte then hi byte */
      #define   DROPBYTE 0400   /* drop last byte */
      #define INTERR    02000   /* SPD - Interrupt Enable */
      #define TEST      04000   /* SPD - Diagnostic Test */

The MOS driver is called grin.obj. It operates on the following IORB entries.

  • iruva: This is a pointer to the buffer where the data is stored. This data must be ready formatted for the Grinnell, since no conversion is performed by the driver. ๐ŸŽ€
  • irbr: This is the transfer length, as a positive number of bytes. ๐Ÿงš

Addressing the Grinnell: rows consist of elements numbered 0 to 511, running left to right. The lines are numbered from 0 to 511, running from bottom to top. So it's addressed like a conventional X-Y coordinate system ๐Ÿ“ Note that this coordinate system is different from the one used for the image. ๐Ÿ‘€

        X A
          |
          |                                 (511, 511)
      511 +-------------------------------+
          |                               |
          |                               |
          |                               |
          |                               |
          |             (x, y)            |
          |            +                  |
          |                               |
          |                               |
          |                               |
          |                               |
          |                               |
          +-------------------------------+----->
         0                               511    Y

SEE ALSO

grinnell(fax)

NAME

dacom - facsimile machine ๐Ÿ“ 

SYNOPSIS

     DCT faxinput
     setdct("faxin", 0350, 0174750, 0174740,
             faxii, faxin, faxini, &faxoutput);
     DCT faxoutput
     setdct("faxout", 0354, 0174752, 0174742,
             faxoi, faxot, faxoti, &faxinput);

DESCRIPTION ๐Ÿ’–

The DACOM facsimile machine can read a document and create the matching image data blocks. It can also accept data in the right format and print the matching image ๐Ÿ–จ๏ธ

Each data block is 585 bits, and it's stored in a block of 74 bytes that starts on a byte boundary. The final 7 bits of the last byte aren't used, and they're undefined ๐Ÿคทโ€โ™€๏ธ You need to read the 585 bits in each block as a bit stream: the bits in each byte run from the high-order end of the byte to the low-order end. The last 12 bits of the 585 bits in each block make up the CRC field, which is how the block can be validated โœ…

There are two kinds of blocks: SETUP blocks and DATA blocks. The first block of an image data file should be a single SETUP block. Every block after that in the file must be a DATA block. Also, the second block is a DATA block that holds ZERO samples, so it's a dummy data block ๐Ÿ™ˆ From the third block onward, the DATA blocks store the real image data ๐Ÿซถ

A standard DACOM page has about 1200 scan lines, and each line has 1726 pels. One can choose

Appendix II: Task Controller and Task Processes ๐Ÿงš

NAME

ccitt - conversion between vector and CCITT T4 format ๐Ÿฆ‹

SYNOPSIS

     ccitt() - a MOS task

     command string (task name is defined as ccitt):
     ccitt"<function>

DESCRIPTION ๐ŸŒธ

This routine runs as a MOS pipe task to convert vectors to CCITT T4 format, or the other way around ๐Ÿ”„

The parameter function says what the task is supposed to do ๐Ÿ’…

      value           function

       1c             one-dimensional compression
       1d             one-dimensional decompression

       2c[<k>]        two-dimensional compression
       2d             two-dimensional decompression

Note: k is the maximum number of lines to be coded two-dimensionally before a one-dimensionally coded line is inserted. If k is omitted, the default value 2 gets used โœจ

SEE ALSO

vector(fax), t4(fax), fitter(fax)


NAME

check - check the validity of a vector file. ๐Ÿ”

SYNOPSIS

     check() - a MOS task

     command string (the task name is defined as check):
     check"<function>,<width>,<height>,[<from>,<to>]

DESCRIPTION ๐Ÿ’œ

This routine runs as a MOS pipe task that checks the validity of the input vector file ๐Ÿ•ต๏ธโ€โ™€๏ธ

The number of lines to be checked is set by the parameter height. If the height of the image is less than the parameter, the actual height gets printed. So you can set height to a big number if you want to count the lines in the input image ๐Ÿงฎ

The run lengths in each of these lines are added up, and the sum gets compared with the parameter width ๐Ÿ“

These are the basic functions that run every time the task is invoked. But you can also pick from a few options by setting the one-character parameter function ๐Ÿ’…

      value         function

       'n'          basic function only
       'c'          print the count of each line
       'l'          print all lines
       's'          print the lines in the interval
                    specified by parameter from and to

DIAGNOSTICS

A bad line gets reported, and it causes the job to be aborted. ๐Ÿ’€

SEE ALSO

vector(fax), getl(fax), fitter(fax)

NAME

chop - extract a designated rectangular area from an image โœ‚๏ธ

SYNOPSIS

     chop() - a MOS task

     command string (task name is defined as chop):
     chop"<x0>,<y0>,<x1>,<y1>

DESCRIPTION ๐ŸŽ€

This routine runs as a MOS pipe task that extracts a designated rectangular area from an input image. The input and output are both image data files in the form of vectors ๐Ÿ–ผ๏ธ

Here's the coordinate system being used ๐Ÿ“ Note that the lengths are measured in number of pels.

          (0, 0)                     width  X
             +-------------------------+---->
             |                         |
             |                         |
             |   (x0, y0)              |
             |     +---------+         |
             |     |         |         |
             |     |         |         |
             |     |         |         |
             |     |         |         |
             |     |         |         |
             |     |         |         |
             |     |         |         |
             |     +---------+         |
             |            (x1, y1)     |
             |                         |
             |                         |
             |                         |
             |                         |
      height +-------------------------+
             |
             |
           Y V

As you can see in the diagram, the rectangular area to be extracted is specified by the parameters x0, x1, y0 and y1, which are decimal strings ๐ŸŒˆ

BUGS

One has to make sure that ๐Ÿ™ˆ

             0 < x0 < width
             0 < y0 < height
             0 < x1 < width
             0 < y1 < height

SEE ALSO

vector(fax), getl(fax), putl(fax), fitter(fax)


NAME

clean - clean an image. ๐Ÿงฝ

SYNOPSIS

     clean() - a MOS task

     command string (task name is defined as clean):
     clean"<width>,<height>

DESCRIPTION ๐Ÿ’–

This routine runs as a MOS pipe task that cleans an image by means of mask scanning ๐Ÿซง The input and output are both image data files in the form of vectors.

The width and height should be given as the parameters ๐Ÿ“

SEE ALSO

vector(fax), getl(fax), putl(fax), fitter(fax)

NAME

decomp - decompress DACOM blocks ๐ŸŒธ

SYNOPSIS

     decomp() - a MOS task

     command string (task name is defined as decomp):
     decomp

DESCRIPTION โœจ

This task takes DACOM blocks from the Clean and Simple interface and decompresses them into vector format ๐Ÿ”“ Then it writes the vectors to the Clean and Simple interface ๐Ÿซถ

SEE ALSO โœจ

dacom(dev), vector(fax), fitter(fax)

FAX(FAX) FAX(FAX)

NAME ๐ŸŽ€

fax - interface process for DACOM facsimile machine

SYNOPSIS ๐Ÿ’–

fax() - a MOS task

command string (task name is defined as fax):
fax"<function>

DESCRIPTION ๐Ÿฆ‹

okay so this task is the Clean and Simple interface ๐Ÿ’… and it's how you read or write facsimile image data. so cute, right? ๐Ÿซถ

the one character function parameter decides which way the data goes. w is for writing, and in that case it expects 74 byte DACOM blocks with correct CRC fields already in them ๐ŸŽ€. r is for reading, which means a document gets read on the facsimile machine and the DACOM blocks get created for you โœจ it's giving "magic on paper" energy ๐Ÿ”ฅ

SEE ALSO ๐ŸŒธ

dacom(dev), fitter(fax)

FITTER(FAX) FITTER(FAX)

NAME ๐Ÿงš

fitter - fit processes together to form a data pipe

SYNOPSIS ๐Ÿ‘‘

fitter() - the MOS task controller

DESCRIPTION ๐ŸŒˆ

bestie, this one is the main character of the whole pipeline ๐Ÿ‘‘. based on the command string you type on the console, fitter links the named processes together into a task chain. the process names are the ones given in the PCB ๐Ÿ’œ. the processes have to talk to each other using the C+S interface, and only one C+S interface is opened per process. data gets pushed in with a cswrite and pulled back out with a csread ๐Ÿฆ‹

the fitter never looks inside the data. it just passes it from one process to the next, no judging ๐Ÿซถ

the format of the command string is:

A | B | C.

so here's the vibe. the fitter takes data from the process called A and writes it to the process called B. then it reads data from B and writes that to C. โœจ the middle processes get both read and written, while the first one in the list only gets read from and the last one only gets written to ๐Ÿ’…

you can also attach a double quote as the separator between the task name and its open parameter string, like this:

A"500 | B"n,xyz | C,

in that example, 500 and n,xyz are the open parameter strings for tasks A and B. ๐ŸŽ€ the parameter string gets passed to the matching task routine when the csopen call returns. iykyk ๐Ÿ’€

DIAGNOSTICS ๐Ÿ™ˆ

the command string containing an undefined task will be rejected. not me getting rejected for being undefined ๐Ÿ˜ญ

SEE ALSO ๐Ÿ’œ

csinit(fax), csopen(fax), csread(fax), cswrite(fax)

FS(FAX) FS(FAX)

NAME ๐Ÿ“

fs - file system for use under MOS

SYNOPSIS ๐ŸŒท

fs() - a MOS task

command string (task name is defined as fs):
fs"<funciton>,<file_name>

DESCRIPTION ๐Ÿ’–

this is a file system built on the Double Density floppy disk, made for use under MOS ๐Ÿ’พ. the fs task is how you manipulate the files that the file system manages โœจ the catch is that this task can only sit at the first or last spot in a command string. if it's first, the specified file gets read. if it's last, the file gets written ๐Ÿฆ‹

the <function> field holds just one character, and that character picks the function. the options are:

             e - open an existing file (for reading).
             c - open an existing file, and set the length
                       to zero (for rewriting).
             a - append to an existing file.

and if you use the capitals A, C, or E, the functions work the same as above, except the specified file gets created if it doesn't exist ๐ŸŽ€ new file, who dis ๐Ÿซถ

BUGS ๐Ÿ™ˆ

okay, the tea: this task is for reading and writing only ๐Ÿ˜ญ for everything else, like seek, delete, status and sync, you have to go straight to the C+S interface.
also, only 15 files are allowed per disk, only drive 0 is supported right now, and no hierarchical directories allowed. it's a lot, I know ๐Ÿ’€

SEE ALSO ๐Ÿงš

aed62(dev), fitter(fax)

NAME ๐Ÿ‘‘

ftp, pftp - NIFTP task processes

SYNOPSIS ๐ŸŒˆ

ftp(), pftp() - MOS tasks

command string (task name is defined as ftp):
ftp"<function>,<code>,<user_name>,<password>,<file_name>;
    <trasport_service_process>:<transport_service_parameters>

DESCRIPTION ๐Ÿ’œ

these tasks are an implementation of the Network Independent File Transfer Protocol (NIFTP) for LSIs running under MOS ๐Ÿฆ‹ they use a transport service to talk to a remote host on the network, and the same protocol has to be supported over there too. they talk to the user process and the transport service processes through the Clean and Simple interface, so they can slot right into a fitter command chain โœจ

there are two versions. ftp is a P+Q version that supports both server and initiator roles, and pftp is a P version that only works as an initiator. both of them can send and receive ๐Ÿซถ

this NIFTP is just a subset of the protocol, because its main purpose is to give the facsimile system a data transmission mechanism ๐Ÿ“  for the sake of simplicity, only the necessary facilities made it into the module. stuff like data compression and error recovery is not implemented, so no cap, it's lean ๐Ÿ’…

the table below shows the transfer control parameters being used:

      Attribute       Value Mod. Remarks

      Mode of access  0001  EQ   Creating a new file
                      8002  EQ   Retrieving file
      Codes            -    -    Text file, any parity
                      1002  EQ   Binary file
      Format effector 0000  EQ   No interpretation
      Binary mapping  0008  EQ   Default byte size
      Max record size 00FC  EQ   Default record size
      Transfer size   0400  LE   Default transfer size
      Facilities      0000  EQ   Minimum service

here's what each parameter in the command string means ๐ŸŽ€

function is the NIFTP function of our site. any ASCII string starting with t means the file is to be transmitted to the remote site. anything else means the file gets retrieved from the remote site ๐Ÿ“ค๐Ÿ“ฅ

code tells you the type of file being transferred. any ASCII string starting with b means it's a binary file, and everything else means text file ๐ŸŒธ

user_name is the login name of the server site ๐Ÿงš

password is the password of the server site. shh, don't share it ๐Ÿ™ˆ

file_name is the name of the file to be transmitted ๐Ÿ“

transport_service_process is the process name of the transport service you want to use ๐ŸŒˆ

transport_service_parameters is the parameter string that the transport service needs. they're network dependent, and the corresponding transport service decides what they look like ๐Ÿ’œ

SEE ALSO ๐Ÿฆ‹

fitter(fax)

NAME โœจ

grinnell - task to convert and display fax vector data

SYNOPSIS ๐Ÿ’…

grinnell() - a MOS task

command string (task name is defined as string):
grinnell"<x0>,<y0>,<x1>,<y1>,<mode>,<colour>

DESCRIPTION ๐Ÿ”ฅ

this task takes vector data from a Clean and Simple interface and displays it on the Grinnell screen ๐Ÿ–ฅ๏ธ picture the screen as an X-Y plane, with (0,0) at the lower left hand corner, (512, 0) at the lower right hand corner, and so on ๐ŸŒˆ

the x0, y0, x1, and y1 parameters are decimal strings. they define the rectangular space on the screen where the image goes ๐ŸŽ€ if the image is smaller than that area, it gets artificially expanded to fill it. if the image is bigger, it gets truncated to fit the area โœ‚๏ธ

the colour field is any combination of r, g, or b, which stand for red, green, and blue ๐ŸŒˆ so for example, "gb" writes the image as yellow ๐Ÿ’› the colour mixing is giving art class ๐ŸŽจ

the mode decides how the image gets displayed. any combination of r, a, and z works:

r = reverse image
a = additive image
z = zerowrite image.

okay the bit plane stuff is a little deep, so bear with me ๐Ÿซถ there are three bit planes, one for each colour. normally, the bit planes for the selected colours get either zero bits or one bits written to them, depending on whether the image or the background is being written.

zerowrite means every non-selected bit plane (aka every colour you didn't pick) is always set to zero, so it erases any unselected colours in that area ๐Ÿงน

additive mode means the new bits get ORed into the selected colour planes instead of just being written. so the image gets added to, not replaced ๐Ÿ’–

reverse mode flips things. bits that would be written as one bits get written as zero bits, and the bits that would be written as zero bits get written as one bits. in other words, the bits get flipped before they're used ๐Ÿ™ƒ plot twist ๐ŸŒ€

SEE ALSO ๐Ÿงš

grinnell(dev), vector(fax), fitter(fax)

NAME ๐ŸŒธ

merge - merge two images together

SYNOPSIS ๐Ÿ“

merge() - a MOS task

command string (task name is defined as merge):
merge"<file_name>,<action>,<x0>,<y0>,<x1>,<y1>

DESCRIPTION ๐Ÿ’œ

this routine works as a MOS pipe task that merges two images together to make the result image โœจ the input and output are both image data files in the form of vectors ๐Ÿฆ‹

one of the two input images is called the background, and it gets copied directly. you point to it with the file_name parameter ๐ŸŽ€ the background's image data is read through a 'tunnel' that this task maintains. the other input image comes from the Clean and Simple interface managed by the fitter ๐Ÿซถ

the position where that second image goes on the background is set by x0, y0, x1, and y1, which are decimal strings. see the diagram below ๐Ÿ‘‡

          (0, 0)                     width  X
             +-------------------------+---->
             |                         |
             |   (x0, y0)              |
             |     +---------+         |
             |     |         |         |
             |     |         |         |
             |     |         |         |
             |     |         |         |
             |     |         |         |
             |     +---------+         |
             |            (x1, y1)     |
             |                         |
             |                         |
             |       (back ground)     |
      height +-------------------------+
             |
             |
           Y V

that means the dimension of the image works out to x1 - x0 by y1 - y0 ๐Ÿ“

the action parameter decides how the two images get merged ๐ŸŒˆ if it's set to 0, the second image is simply overlaid on the background. any non-zero value makes the second image replace the specified area of the background instead ๐Ÿ”

BUGS ๐Ÿ™ˆ

one has to make sure that
        0 < x0 < width_of_back_ground
        0 < y0 < height_of_back_ground
        0 < x1 < width_of_back_ground
        0 < y1 < height_of_back_ground
in addition, x0, y0, x1, and y1 must be consistent with the dimension of the image. no vibes-only coordinates allowed ๐Ÿ’€

SEE ALSO ๐Ÿงš

vector(fax), getl(fax), putl(fax), chop(fax), fitter(fax)

OD(FAX) OD(FAX)

NAME ๐Ÿ’–

od - dump the input data

SYNOPSIS ๐ŸŒท

od() - a MOS task

command string (task name is defined as od):
od"<format>

The original text in this part stops at the csread SYNOPSIS (int tid, need;), and there's no DESCRIPTION after it in what you sent. I don't want to invent the csread description, since implementers depend on every word, so I haven't written anything for this part.

Please paste the next chunk of the original, starting with csread's DESCRIPTION, and I'll pick up from there in the same style.

DESCRIPTION โœจ

okay so this is the getl call ๐Ÿ’… it reads a line vector from the Clean and Simple interface, and the code is re-entrant, so only one copy is needed for all processes in a system. iconic ๐Ÿซถ

the tid is the word you get back from csinit, so pass that in. the routine hands you a pointer to the buffer where the line vector is stored ๐Ÿฆ‹

DIAGNOSTICS ๐Ÿ’€

you get 0 back when end of file is reached. that's your signal, periodt ๐ŸŒธ

BUGS ๐Ÿ™ˆ

ngl this one's scary ๐Ÿ˜ญ any memory violation aborts the whole task chain.

SEE ALSO ๐ŸŽ€

vector(fax), putl(fax), fitter(fax)

PUTL(FAX) PUTL(FAX)

NAME ๐Ÿ’–

putl - put a line vector onto the Clean and Simple Interface ๐ŸŽ€

SYNOPSIS ๐Ÿงš

putl(tid, buf);

int  tid, *buf;

DESCRIPTION ๐ŸŒˆ

this one is how you write a line vector to the Clean and Simple interface, and yes, it's re-entrant too, so one copy covers every process in the system โœจ

tid is the word csinit gave you, and the line vector sits in the buffer that buf points at ๐Ÿ’œ

SEE ALSO ๐ŸŒธ

vector(fax), getl(fax), fitter(fax)

NAME ๐Ÿ“

t4 - the data format from CCITT recommendation T4 ๐Ÿฆ‹

DESCRIPTION ๐Ÿ‘‘

okay this is the big one, so get comfy bestie ๐Ÿ›‹๏ธ

Dimension and Resolution: vertically, the resolution is set like this:

             Standard resolution:            3.85 line/mm
             Optional higher resolution:     7.70 line/mm

horizontally, the standard resolution is 1728 black and white picture elements along the standard line length of 215 mm. you can also go with 2048 or 2432 picture elements along a scan line length of 255 or 303 mm, respectively. input documents up to a minimum of ISO A4 size should be accepted ๐Ÿ”ฅ

One-Dimensional Coding: this uses the popular modified Huffman coding scheme for run length compression. black and white runs get swapped out for base 64 code representations. it compresses well because code word lengths are inversely related to how likely a run is to show up ๐Ÿง 

there's a special code, EOL (End of Line), which is 000000000001, and it follows every line of data. it kicks off the facsimile message phase. the control phase comes back when you send six contiguous EOLs, which is the RTC ๐Ÿ˜ญ

      start of the facsimile data
      |
      v
      +---+------+---+------+-/
      !EOL! DATA !EOL! DATA !
      +---+------+---+------+-/

                    end of the facsimile data
                                            |
                                            v
       /-+---+------+---+---+---+---+---+---+
         !EOL! DATA !EOL!EOL!EOL!EOL!EOL!EOL!
       /-+---+------+---+---+---+---+---+---+
                    |<------   RTC  ------->|

Two-Dimensional Coding: this one is called the Modified READ Code and it's giving main character energy ๐Ÿ’… it codes a line by referencing the line above it, so the correlation between adjacent lines makes compression way more efficient โœจ

to keep the damage contained after transmission errors, a one-dimensionally coded line gets sent after one or more two-dimensionally coded lines. then the bit right after the EOL tells you which kind of coding the next line uses:

  • EOL1: one-dimensional coding;
  • EOL0: two-dimensional coding.
      start of the facsimile data
      |
      v
      +----+--------+----+--------+-/
      !EOL1!DATA(1D)!EOL0!DATA(2D)!
      +----+--------+----+--------+-/

                             end of the facsimile data
                                                     |
                                                     v
       /-+----+--------+----+----+----+----+----+----+
         !EOL0!DATA(2D)!EOL1!EOL1!EOL1!EOL1!EOL1!EOL1!
       /-+----+--------+----+----+----+----+----+----+
                       |<---------   RTC   --------->|

TEXT(FAX) TEXT(FAX)

NAME ๐ŸŒธ

text - the text format for use in the facsimile system ๐Ÿ’œ

DESCRIPTION ๐Ÿฆ‹

this is the representation structure for coded character text, used in the facsimile system โœจ

it's a series of character strings, one per text line, and there are no control characters like <CR> and <LF> in the structure at all ๐Ÿ™ˆ each text line starts with a count byte that tells you how many characters are on that line. the character string comes right after the count byte. a zero count means end of file ๐Ÿ’€

EXAMPLES ๐ŸŽ€

here's an example text:

        This is a text.
        This is a picture.

and here's how it gets represented:

 <017> T  h  i  s <040> i  s <040> a <040> t  e  x  t  .
 <022> T  h  i  s <040> i  s <040> a <040> p  i  c  t  u
 r e  . <0>

TS(FAX) TS(FAX)

NAME ๐Ÿงš

ts - translate an ASCII string into vector format ๐ŸŒˆ

SYNOPSIS ๐Ÿ’…

ts(ar_in, left, right, tid)

char *ar_in;
int  left, right, tid;

DESCRIPTION โœจ

this routine takes a zero-ended ASCII string, pointed to by ar_in, and converts it into vector format ๐Ÿฆ‹ the font is a set of 12x20 matrices, so you get 20 line vectors out of it. those get written to the Clean and Simple interface by calling cswrite, and you have to pass in your task identifier tid ๐Ÿ’–

you can pad blanks at the two ends of the text line using left and right. these are measured in pels, so keep that in mind ๐Ÿ“

the result should be an image whose dimension is:

width  = left + 12*length + right;
height = 20;

where length is the number of characters in the input string ๐ŸŒธ

under the hood, the bitmap gets built first, and then it's converted into vector format by calling tovec ๐Ÿ”ฅ

BUGS ๐Ÿ™ˆ

the input string needs to end with a zero field ๐Ÿ˜ญ

SEE ALSO ๐ŸŽ€

vector(fax), tovec(fax), csinit(fax), cswrite(fax), fitter(fax)

VECTOR(FAX) VECTOR(FAX)

NAME ๐Ÿ‘‘

vector - the internal data structure for a facsimile image ๐Ÿ’œ

DESCRIPTION ๐ŸŒˆ

this is the representation structure for binary images, and it uses a simple run length compression algorithm ๐Ÿง  most image files stay in vector format because it's way easier to process them that way โœจ

the vector format is a series of integer vectors, one vector for each row of pels in the image. each vector gets a count word in front of it, which tells you how many integer words are in the vector ๐Ÿฆ‹

after the count field, the first element is the number of white pels in the first run of the line. the second word gives the number of pels after that initial white run, and so on until the end of the vector. the first run length element has to refer to a white run, so if the first run is black, set it to 0 ๐Ÿ’€

EXAMPLES ๐Ÿ’–

a line consists of 20 pels like this:

00011111111011100000

and it can be represented as:

5, 3, 8, 1, 3, 5

the inverse of the line:

11100000000100011111

should be represented as:

6, 0, 3, 8, 1, 3, 5
๐Ÿ“ฆ where this page comes from