Binary File I/O

To store sheet data on disk, it is necessary to write it as binary,
not ascii. It may also be important to store other data along with
the sheet or sheets, such as camera information. Binary file I/O is
handled through the coprocessor.

The binary file protocol is intended to be used also for device files
(e.g. a serial line) if an implementation includes them. When fast
response is required, however, it may be better to add a specific
function to the coprocessor. This might apply, for example, to a fast
camera interface.

Binary files

The following functions are used to manage pointers, called ports,
to binary files. The list command is provided, like the list commands
for storage groups and windows, to allow the user to close unwanted
open binary ports. Notice that all binary ports will be closed if
the coprocessor is restarted (e.g. when linking a new compiled
function).

(open-binary-input-file filename) returns a binary-port

(open-binary-output-file filename) returns a binary-port

(close-binary-port binary-port)

(list-binary-ports) returns the ports for all open binary files

(binary-port-open? binary-port) returns a boolean, true if the
binary-port is still live

(binary-eof-object? object) returns a boolean, true if the object
is a end of file marker for binary files

Writing objects

The binary-write operation is used to write whole objects to the file,
as units and is similar to the scheme write function. This is the
recommended method of storing images.

(binary-write object binary-output-port)

(binary-read binary-read-port) returns the next object in the file
or a scheme end-of-file object

These functions generate errors if they fail.

The Envision binary storage format is documented in [ADD POINTER TO
PAGE OF DETAILS]. Briefly, each object is written out as a tag
indicating what type of object it is, followed by its contents, and
finally an end tag. Because file size is dominated by the packed
bytes of data from large sheets, details of the tagging format and the
representations for small objects (e.g. lists, strings) will never
be critical.

The format permits nested objects (e.g. a list of lists of sheets) and
multiple objects within a file. Thus, a local format can be created
by building a suitable scheme structure (e.g. a vector containing
objects of diverse types) and saving it using binary-write.

Notice that, when a sheet is written to a file, all critical
information is stored with it, so that it can be completely
reconstructed when read from the file. This include, in particular,
the dimensions of the sheet. All data for each sheet is written,
regardless of how large its focus area is.

When several sheets share a common storage area, the writer ought to
store the shared data only once. However, that is not the case at
this time: assume that each sheet will be written independently and,
when they are read back from the file, they will not belong to the
same storage group.

Writing bytes

To handle foreign file formats, compressed formats, and device files,
it is also possible to write raw bytes to a binary file. Write-byte
and read-byte are used to read and write single bytes.

(read-byte binary-input-port) returns an exact integer, or an end-of-file object

The sheet operations write-bytes and read-bytes are available for
writing a large number of bytes efficiently,

(write-bytes binary-output-port sheet)

(read-bytes binary-input-port n)

(read-bytes binary-input-port n sheet) uses the supplied sheet
for the input rather than allocating new storage.

Write-bytes writes the contents of a sheet to a file as packed
bytes. The sheet must be a 1D 8-bit-deep integer-grid, declared to have
no missing values. Any scaling or offset of the codomain values is
ignored. Only the focus area of the sheet is written. This feature
is useful you have filled only part of a fixed-length buffer. It
returns the number of bytes actually written.

Write-bytes cannot be applied to a 2D sheet. This is a deliberate design decision:

The appropriate order depends on the application and the file format.
Making assumptions about storage order may result in a rotated image.

2D sheets represent homogeneous 2D space and the coordinate axes
are supposed to be incidental. There is no sensible notion of order in 2D space.

The user must decide how to order the 2D sheet, copy its contents to a
1D sheet using a suitable user-defined coprocessor function, and then
write the 1D sheet.

Read-bytes reads the next n bytes, returning them as a 1D sheet. The
returned sheet is always n bytes long. It also returns the number of
bytes actually read. If the number read is less than the number
requested, then a sheet of length n is still returned, but the extra
values at the end of the sheet are unspecified as to what their
contents are.

If the optional sheet argument is supplied, read-bytes uses it rather
than allocating new storage. The function fills in the focus area of
the sheet. An error is generated if this sheet's focus area is
shorter than n or the wrong type.