ELF is a highly advanced layered image format designed by Black Belt Systems to support its WinImages products.
Although other layered image file formats exist (e.g., Photoshop®'s ".PSD" format), they presuppose a number of defined layer mode behaviors, and in some cases do not allow for layers of a size not equal to a base layer. They all define a comparatively limited total number of layer modes. Some formats also require a base layer, or imply one. Additionally, many previously defined layered formats offer very poor image data compression, resulting in overweight filesizes that unnecessarily waste filesystem space.
Generally speaking, in the image manipulation software community, it is considered "not a good idea" to define a new file format unless you really have a good reason, or reasons. Well, we did: We knew for certain that any combination of the above-described problems would severely cripple the capabilities of WinImages' layered image handling.
So we created a brand new format to ensure that WinImages's layering may be as flexible as possible and may grow and develop completely unfettered by previous application's various design issues and limitations. Since at this time we can show that WinImages' layered image handling is demonstrably superior in almost every way to other high-end image applications, we see the creation of this format as having been completely justified.
We have made many details available on ELF so that software developers may, if they so choose, implement a reasonable level of support for the file format. This is offered freely to the developer community, regardless of shareware, freeware or commercial application implementations.
We only require that any person or company publishing an application with ELF support let us know that your application will read and/or write ELF files. We can then make you aware any time the specification is advanced, and you can then make an informed decision about keeping your application up to date. We'll also be very pleased to list your application both in the shipping documentation and the network-level documentation. It is our belief that such cooperation helps everyone.
ELF-2 is "Big Endian". MS byte first, LS byte last, MS word first, MS word last. This means that the HEX number 0x01234567 would be represented in the file by a stream of bytes in this order:
<-- beginning of file0x01 0x23 0x45 0x67end of file -->
When reading and writing ELF-2 files, care must be taken to arrange the long (signed 32 bit) variables in the Big-endian order. Byte entities are read one at a time, and are in the correct order, they need no correction on any platform as long as they are read one byte at a time. (char arrays, the CO structs).
ELF-2 files are sequences of RGBA image layers, nearest to deepest ordered, which combine to form a master image of the dimensions specified in the elf_header structure. All layers have alpha (not just a place for it, they actually have an alpha mask for each set of R,G, and B layers). Layers may be any size at all, larger, the same as, or smaller than the master image in either or both dimensions. Because layers may be any size, there can be areas where layers do not overlay previous layers. Where layers do not overlap, full transparency is assumed. ELF-2 files do not implement "channels" though channelized software can reconstruct much of an ELF-2 file by developing R, G, B and A channels linked as layers. Similarly, WinImages implements Photoshop® "blend" channels by turning them into Grey Mask layers — "There's more than one way to skin a file format!"
Channel data is 0-255 R,G,B,A (red, green, blue, alpha). Zero alpha is fully transparent, 255 alpha is fully opaque. String data is zero-delimited. Aspect data is handled as, numerator, denominator. You must convert it to DPI via:
Because of the defined DPI conversion, it is acceptable to place DPI directly into the numerator variables, and 1, or zero, into the denominator variables. Since zeros are coverted to one's, it's the same thing after correctly reading the file.
A number of mechanisms exist to ensure that reading ELF files goes in a predictable, replicable manner:
First, the file format provides magic numbers, and they must be used to ID the file. Extension is not sufficient. Readers must check both the number in the header and the number in each layer structure.
Second, ELF-2 files (and ELF files) have a version number; 2 for ELF-2 and 1 for ELF. Readers must read this number and match it against their internal capabilities. ELF readers will not be able to read ELF-2 files without additional heuristics.
Offsets of zero in non-local layers indicate that layers line up with the master image at the upper left hand corner. Positive X and Y offsets indicate offset left and down into the master image, respectively. Local layers develop offsets from the upper left of the base layer in the local stack; the base layer in turn is offset from the master.
In the publicly documented compression formats, image data is stored top of image to bottom of image, in scanlines of all red, followed by all green, followed by all blue, followed by all alpha.
In the publicly documented compression formats, image data is stored left to right. Pixels at the left side of the image are encountered first when reading or decompressing image scanline data.
There are three supported compression modes, and an uncompressed mode. Two modes are public, one is proprietary. WinImages allows the proprietary high compression mode to be turned off so that ELF files may be saved in a format that external applications can read.
The first public format uses ZLIB's INFLATE and DEFLATE compression methods. This compression mode is indicated by a compression flag value of ELF_ZCOMP.
The second public format (and the one that seems to work best) is a type of RLE. This compression uses a single signed byte to flag runs or block copies; this same byte is also a duplicate or copy count. This compression mode is indicated by a compression flag value of ELF_RLECOMP.
The third, proprietary format is undocumented as to method, but is detailed enough so that such blocks can be skipped in a defined manner. This compression mode is indicated by a compression flag value of ELF_TCOMP.
Finally, ELF layers can stored uncompressed. This is indicated by a flag value of ELF_NOCOMP.
ELF_ZCOMP Compression Description |
---|
This compression mode is implemented using ZLIB, version 1.1.3, July 9th, 1998. The deflation algorithm used by gzip (also zip and zlib) is a variation of LZ77 called "deflate" along with a matching decompressor called "inflate." Scan lines are stored with a big-endien 4-byte length of the compressed data prior to the compressed data itself, then the compressed data follows. Each of the R,G,B and A chunks has its own length and data block. ![]() Some testing (not very extensive, perhaps 25 images) has indicated that not only is DEFLATE/INFLATE definitely quite a bit slower than ELF_RLECOMP compression and decompression, it usually will result in a significantly larger file as well. For this reason, R6 writes RLE compressed ELF files only in the non-high compression mode, though it can read both RLE and DEFLATE types of compression for compatibility's sake. |
ELF_RLECOMP Compression Description |
---|
If the byte read is positive, then copy that many more bytes verbatim from the incoming byte stream into the channel. For instance, if an 0x03 is encountered, then the next three bytes are to be read into the channel. Before inserting the data in the channel, check for channel overrun error by count + total bytes generated thus far, and if not overrun, read the three bytes, and increase the channel position. check for end of channel, and if not end of channel, load another flag byte. If the flag is negative, this indicates that you will be duplicating the next byte. For example, you read a -4 as the flag byte. To determine how many times to duplicate the byte, negate it (-4 becomes 4) and add one, so that you would now have 5. Be aware that this is not "complement and add one", it is negate and add one. Before inserting the data in the channel, check for channel overrun error by count + total bytes generated thus far, and if not overrun, read the next byte from the file, and insert 5 copies of that byte into the channel. Check for end of channel (x width) and if not reached, read the next flag byte. No compressed run extends beyond a scan line component, for instance the red could be a single run, but the green will be a new run. |
ELF_TCOMP High Compression Mode |
---|
This compression mode begins with a 4-byte chunk size, followed by that many bytes of data in a proprietary format. If you encounter an ELF_TCOMP compressed layer, read the four byte chunk size into a SIZE variable, and then discard the next SIZE number of bytes. Fill the layer with white RGB data and 100% transparent (0) alpha information. This layer is not readable outside of WinImages' applications. |
ELF_NOCOMP Uncompressed Data Description |
---|
Uncompressed layers are just that, completely uncompressed. Channel data for a width of 320 pixels will contain 320 red bytes immediately followed by 320 green bytes, 320 blue bytes, and finally 320 alpha bytes. |
Compression is specified per-layer. It is possible for an ELF file to contain a mix of compressed and non-compressed layers, and that the compression mode types themselves are mixed. Why? Because the compression modes used cannot guarantee to produce a compressed output, especially from "noisy" source data. This allows applications to store uncompressed layers in place of compressed layers when the compression results in output larger than input, and it also allows an application to pick the compression mode that results in the highest data compression. For this reason, readers must always support all implemented public compression modes. If a minimal ELF writer is to be designed, the best single choice for compression is ELF_RLECOMP.
Application behavior of testing compressed results before committing to a compressed representation is optional, but recommended. An additional benefit of this approach is that image loading may also be faster when uncompressed versions of noisy sources are stored.
When reading the image, the morelayers flag will be one as long as there are additional layers to read. A zero morelayers means you're about to read the last layer. So if the first morelayers is zero, there is only one layer in the image.
Mode tells you how to rebuild the composite master image. See the #defines below. If the image contains modes that are not described here, it will have a new version number; that lets your reader know it can't deal with the ELF file properly. Observe the version number!
Opacity essentially is a second, global, alpha for the layer.
Visible is a switch. 1 means it is visible, 0 means it's not used to display the final image.
Color1 and color2 are RGBA entities that will be used in future layer modes, not yet implemented in version 1.
In ELF, there is no "base" layer; instead, a master view is generated that is created from the layers in the ELF file. In this way, the problems that predefined base layers incur are completely avoided.
There is no gamma component predefined, as that is a local issue for the monitor/room combination, properly decided by the user of the software displaying the file, if indeed such amenities are available. Similarly, there are no chromasticities defined.
The general structure of a 5-layer ELF version 2 file looks like this:
elf_header block (master image defined here - there is no image data)
elf_layer block (topmost layer)
RGBA channel data
elf_layer block...
RGBA channel data
elf_layer block...
RGBA channel data
elf_layer block...
RGBA channel data
elf_layer block (deepest layer)
RGBA channel data
|
ELF, or ELF-1, is a compatible subset of ELF-2. A properly implemented ELF-2 reader can read ELF-1 files with no trouble, and no special casing, because all new field uses are either set to zero with compatible meaning of zero, or values represented in an ELF-1 file mean the same thing in an ELF-2 file. ELF-2 files, however, cannot be read by an ELF-1 reader, as modes exist that will not translate properly without additional flags that do not make it through ELF-1 flag filtering, layer modes and mechanisms exist in an ELF-2 file that cannot be understood by an ELF-1 reader, and layers may be stored in previously unknown compression states.
ELF is "Big Endian". MS byte first, LS byte last, MS word first, MS word last. This means that the HEX number 0x01234567 would be represented in the file by a stream of bytes in this order:
0x01 0x23 0x45 0x67
When reading and writing ELF files, care must be taken to arrange the long (signed 32 bit) variables in the Big-endian order. Byte entities are read one at a time, and are in the correct order, they need no correction on any platform as long as they are read one byte at a time. (char arrays, the CO structs).
ELF files are sequences of image layers, nearest to deepest ordered, which combine to form a master image of the dimensions specified in the elf_header structure. All layers have alpha (not just a place for it, they actually have masks). Layers may be any size at all, larger, the same as, or smaller than the master image in either or both dimensions. Because layers may be any size, there can be areas where layers do not overlay previous layers. Where layers do not overlap, full transparency is assumed.
Channel data is 0-255 R,G,B,A (red, green, blue, alpha), in that order. Zero alpha is fully transparent, 255 alpha is fully opaque. String data is zero-delimited. Aspect data is handled as, numerator, denominator. You can convert it to DPI via:
The file format provides magic numbers, and they must be used to ID the file. Extension is not sufficient.
Offsets of zero indicate that images line up at the upper left hand corner. Positive offsets indicate offset into the image.
Image data is stored top of image to bottom of image, in scanlines of all red, followed by all green, followed by all blue, followed by all alpha.
Compression is a type of RLE. This compression uses a single signed byte to flag runs or block copies; this same byte is also a duplicate or copy count.
If the byte read is positive, then copy that many more bytes verbatim from the incoming byte stream into the channel.
For instance, if an 0x03 is encountered, then the next three bytes are to be read into the channel. Before inserting the data in the channel, check for channel overrun error by count + total bytes generated thus far, and if not overrun, read the three bytes, and increase the channel position. check for end of channel, and if not end of channel, load another flag byte.
If the flag is negative, this indicates that you will be duplicating the next byte.
For example, you read a -4 as the flag byte. To determine how many times to duplicate the byte, negate it (-4 becomes 4) and add one, so that you would now have 5. Be aware that this is not "complement and add one", it is negate and add one. Before inserting the data in the channel, check for channel overrun error by count + total bytes generated thus far, and if not overrun, read the next byte from the file, and insert 5 copies of that byte into the channel. Check for end of channel (x width) and if not reached, read the next flag byte.
No compressed run extends beyond a scan line component, for instance the red could be a single run, but the green will be a new run.
Uncompressed layers are just that, completely uncompressed. Channel data for a width of 320 pixels will contain 320 red bytes immediately followed by 320 green bytes, 320 blue bytes, and finally 320 alpha bytes.
Compression is specified per-layer. It is possible for an ELF file to contain a mix of compressed and non-compressed layers. Why? Because RLE does not always produce a compressed output, especially from "noisy" source data. This allows applications to store uncompressed layers in place of compressed layers when the RLE compression results in output larger than input.
This application behavior is optional, but recommended. An additional benefit is that image loading is also faster when uncompressed versions of noisy sources are stored.
When reading the image, the morelayers flag will be one as long as there are additional layers to read. A zero morelayers means you're about to read the last layer. So if the first morelayers is zero, there is only one layer in the image.
Mode tells you how to rebuild the composite master image. See the #defines below. If the image contains modes that are not described here, it will have a new version number; that lets your reader know it can't deal with the ELF file properly. Observe the version number!
Opacity essentially is a second, global, alpha for the layer.
Visible is a switch. 1 means it is visible, 0 means it's not used to display the final image.
Color1 and color2 are RGBA entities that will be used in future layer modes, not yet implemented in version 1.
In ELF, there is no "base" layer; instead, a master view is generated that is created from the layers in the ELF file. In this way, the problems that predefined base layers incur are completely avoided.
There is no gamma component predefined, as that is a local issue for the monitor/room combination, properly decided by the user of the software displaying the file, if indeed such amenities are available. Similarly, there are no chromasticities defined.
The general structure of a 5-layer ELF version 1 file looks like this:
elf_header block (master image defined here - there is no image data)
elf_layer block (topmost layer)
RGBA channel data
elf_layer block...
RGBA channel data
elf_layer block...
RGBA channel data
elf_layer block...
RGBA channel data
elf_layer block (deepest layer)
RGBA channel data
|