GRP Image Format
From Staredit Network Wiki
- Byte = 8 bits
- Word = 2 bytes (Short)
- Long = 4 bytes
- All values are unsigned.
Contents
GRP File Layout
- GRP Header
- Image Header * number of images
- Line Offsets * number of images * image height
- RLE Line * number of images * image height
GRP Header
Struct Size: 6 bytes
- Word - number of images
- Word - maximum width
- Word - maximum height
- Image Headers - one header for each image
Image Header
Struct Size: 8 bytes
- Byte - difference from maximum width (?)
- Byte - difference from maximum height (?)
- Byte - width (in pixels)
- Byte - height (in pixels)
- Long - offset to Line Offsets: the number of bytes from the beginning of the file to the offset for each line.
Line Offsets
Struct Size: 2 bytes * image height
- Word - offset to a RLE Line in bytes from the location of this Line Offsets.
- Word - another offset...
- Word - another...
- Word - another...
- ...
RLE Line
- Byte - Instruction and length:
- if bit 7 is on, it indicates X number pixels are skipped aka transparency.
- if bit 6 is 1 indicates X number of pixels are "this" color. (RLE compression part)
- else X normal pixels should be copied over.
eh... i got lazy, sorry. :/
Example Code
struct definitions
struct grp_image_s
{
uint8_t x_offset;
uint8_t y_offset;
uint8_t width;
uint8_t height;
uint32_t offsets;
};
struct grp_header_s
{
uint16_t num_images;
uint16_t max_width;
uint16_t max_height;
};
struct color_s
{
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t alpha;
};
read the whole file into sprite_data
uint8_t sprite_data = new uint8_t[file_size_in_bytes];
allocate a color_s for each pixel (for just one image)
grp_header_s* gr_file_header = (grp_header_s*)sprite_data;
color_s* pixels = new color_s[grp_file_header->max_width *
grp_header->max_height ];
decoding algo
for (k = 0; k < num_images; ++k)
{
current_image = (grp_image_s*)(sprite_data + 6 + (k * sizeof(grp_image_s)));
line_offsets = (uint16_t*)(sprite_data + current_image->offsets);
image_width = current_image->width;
image_height = current_image->height;
memset(pixels, 0, grp_header->size_x * grp_header->size_y * sizeof(color_s));
for (y = 0; y < image_height; ++y)
{
line_data = (uint8_t*)line_offsets + line_offsets[y];
line_pixels = pixels + (image_width * y);
for (data_offset = x = 0; x < image_width;)
{
if (line_data[data_offset] & 0x80) // transparent
{x += line_data[data_offset++] & 0x7f;}
else if (line_data[data_offset] & 0x40) // data run
{
length = x + (line_data[data_offset++] & 0x3f);
rle_index = line_data[data_offset++];
while (x < length) {line_pixels[x++] = palette[rle_index];}
}
else // normal
{
for (length = x + line_data[data_offset++]; x < length;)
{line_pixels[x++] = palette[line_data[data_offset++]];}
}
}
}
COPY pixels TO ANOTHER PLACE
}