GLE

From Just Solve the File Format Problem
Jump to: navigation, search
File Format
Name GLE
Ontology

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;
}
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox