GRP Image Format

From Staredit Network Wiki
Jump to: navigation, search
  • Byte = 8 bits
  • Word = 2 bytes (Short)
  • Long = 4 bytes
  • All values are unsigned.

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
}