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; }