Here is how both sequence and bitmap headers are represented internally:
  
  typedef unsigned char byte_t;
  struct header_t
  {
    byte_t   h_bits;      // bits per pixel (currently 1 or 2)
    byte_t   h_count;     // number of bitmaps in the file (1..255)
    byte_t   h_width;     // original width
    byte_t   h_height;    // original height
    bitmap_t h_body[ 1 ]; // bitmaps
  };
  struct bitmap_t
  {
    byte_t b_xorg;        // x-origin, pels
    byte_t b_yorg;        // y-origin, pels
    byte_t b_width;       // raster width, pels
    byte_t b_height;      // raster height, pels
    byte_t b_raster[ 1 ]; // scanlines
  };
 
And here is how rasters are stored (i.e. how b_raster[] is formed; process of
loading must be just the opposite). Please note that (x1, y1, x2, y2) is a
non-transparent rectangle of original frame (0, 0, header_t::h_width,
header_t::h_height).
  x1 = bitmap_t::b_xorg;
  y1 = bitmap_t::b_yorg;
  x2 = x1 + bitmap_t::b_width - 1;
  y2 = y1 + bitmap_t::b_height - 1;
  total_bits = header_t::h_bits;
  for( y = y1; y <= y2; y ++ )
  {
    bit = 7;
    byte = 0;
    for( x = x1; x <= x2; x ++ )
    {
      pixel = "pixel at x, y"
      byte |= total_bits == 1 ? ( pixel == P_BLACK ) << bit:
        (( pixel ^ 3 ) & 3 ) << bit - 1;
      bit -= total_bits;
      if( bit < 0 ) putc( byte, file ), bit = 7, byte = 0;
    }
    if( bit != 7 ) putc( byte, file );
  }
 
At last, here is how rasters are loaded by emulator. Although it addresses
loading, this example is probably less useful than previous, because code in
emulator converts 1- and 2-bit pixels into bytes, on the fly, for more simple
and effective processing. Cybiko applications are not supposed to behave this
way, i.e. they must not expand rasters.
  x1 = bitmap_t::b_xorg;
  y1 = bitmap_t::b_yorg;
  x2 = x1 + bitmap_t::b_width - 1;
  y2 = y1 + bitmap_t::b_height - 1;
  total_bits = header_t::h_bits;
  bit = 0 // current bit, 1..8;
  byte = 0 // cyrrent packet;
  int get_bit( FILE* file, int& bit, int& byte )
  {
    if( bit == 0 ) byte = (byte_t) getc( file ), bit = 8;
    if( byte == EOF ) die( "get_bit: premature end-of-file" );
    return ( byte & 1 << -- bit ) != 0;
  }
  for( y = y1; y <= y1; y ++ )
  {
    for( x = x1; x <= x2; x ++ )
    {
      pixel = 0;
      for( b = 0; b < bits; b ++ )
      {
        pixel <<= 1;
        pixel += get_bit( file, bit, byte );
      }
      switch( pixel )
      {
        case 0: pixel = clr_white; break;
        case 1: pixel = bits == 1 ? clr_black: clr_ltgray; break;
        case 2: pixel = clr_dkgray; break;
        default: pixel = clr_black;
      }
      "pixel at x, y" = pixel;
    }
    bit = 0; // abandon trailing bits ( end of scanline )
  }
 
  
 |