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 }