GLE
From Just Solve the File Format Problem
GLE is a simple monochrome graphics format used for storing the Energy Star logo in AMI BIOS images. Full splash screens are usually stored in the PCX format.
Structure
The layout of a GLE file is as follows.
| Name | Length | Description |
|---|---|---|
| magic | 3 bytes | Always contains 'G' 'L' 'E', i.e. 47 4c 45.
|
| ??? | 1 byte | Always equal to 1 in files known to this author. It is unknown whether it should be considered a part of the magic number, format version number, bit depth, set of flags or some other indicator. |
| width | 1 byte | Image width, in character cells; usually 11. One cell is 8 pixels wide. |
| height | 1 byte | Image height, in character cells; usually 3. One cell is 14 pixels high. |
| fgcolor | 1 byte | CGA colour number of foreground (1) pixels; usually 10 (light green). See wikipedia:Color Graphics Adapter#Color palette. |
| bgcolor | 1 byte | CGA colour number of background (0) pixels; usually 0. |
| data | width × height × 14 bytes | The image data itself. The pixel data is stored in a way identical to the EPAv1 format: character cell by character cell, left to right, top to bottom. Each character cell occupies 14 bytes: the first byte corresponds to the first row of the cell, and the most significant bit corresponds to the leftmost pixel. |
Converter
The following C99 program converts a GLE image to XPM.
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
struct gle_header {
char magic[3];
uint8_t reserved; /* = 1 */
uint8_t width;
uint8_t height;
uint8_t fgcolor;
uint8_t bgcolor;
};
static const uint_least32_t cga_palette[16] = {
0x000000, 0x0000aa, 0x00aa00, 0x00aaaa,
0xaa0000, 0xaa00aa, 0xaa5500, 0xaaaaaa,
0x555555, 0x5555ff, 0x55ff55, 0x55ffff,
0xff5555, 0xff55ff, 0xffff55, 0xffffff,
};
int main(int argc, char *argv[]) {
if (!argv[1]) {
fprintf(stderr, "usage: %s $filename\n", argv[0]);
return 1;
}
FILE *inf = fopen(argv[1], "rb");
struct gle_header header;
char magic[3];
if (!fread(&header, sizeof(header), 1, inf)) {
if (feof(inf))
fprintf(stderr, "%s: %s: cannot read header: premature end of file\n", argv[0], argv[1]);
else
fprintf(stderr, "%s: %s: cannot read header: %s [%d]\n", argv[0], argv[1], strerror(errno), errno);
return 1;
}
if (memcmp(header.magic, "GLE", 3)) {
fprintf(stderr, "%s: %s: magic number mismatch\n", argv[0], argv[1]);
return 1;
}
if (header.reserved != 1) {
fprintf(stderr, "%s: %s: reserved byte == %u (!= 1), conversion may fail\n", argv[0], argv[1], header.reserved);
}
uint8_t bitmap[header.width * header.height * 14];
if (!fread(bitmap, sizeof(bitmap), 1, inf)) {
if (feof(inf))
fprintf(stderr, "%s: %s: cannot read bitmap data: premature end of file\n", argv[0], argv[1]);
else
fprintf(stderr, "%s: %s: cannot read bitmap data: %s [%d]\n", argv[0], argv[1], strerror(errno), errno);
return 1;
}
printf("/* XPM */\n");
printf("static char *gle[] = {\n");
printf("\"%u %u 2 1 \",\n", header.width * 8, header.height * 14);
printf("\" c #%06x\",\n", cga_palette[header.bgcolor]);
printf("\"@ c #%06x\",\n", cga_palette[header.fgcolor]);
for (size_t y = 0; y < 14 * header.height; ++y) {
printf("\"");
for (size_t x = 0; x < header.width; ++x) {
uint8_t b = bitmap[(y - y % 14) * header.width + 14 * x + (y % 14)];
printf("%c%c%c%c%c%c%c%c",
(b >> 7) ? '@' : ' ',
(b >> 6) & 1 ? '@' : ' ',
(b >> 5) & 1 ? '@' : ' ',
(b >> 4) & 1 ? '@' : ' ',
(b >> 3) & 1 ? '@' : ' ',
(b >> 2) & 1 ? '@' : ' ',
(b >> 1) & 1 ? '@' : ' ',
(b ) & 1 ? '@' : ' '
);
}
printf("\",\n");
}
printf("};\n");
return 0;
}